1: <?php
2:
3: defined('BASEPATH') OR exit('No direct script access allowed');
4:
5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17: abstract class REST_Controller extends CI_Controller {
18:
19:
20:
21:
22:
23: const HTTP_CONTINUE = 100;
24: const HTTP_SWITCHING_PROTOCOLS = 101;
25: const HTTP_PROCESSING = 102;
26:
27:
28:
29: 30: 31:
32: const HTTP_OK = 200;
33:
34: 35: 36:
37: const HTTP_CREATED = 201;
38: const HTTP_ACCEPTED = 202;
39: const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
40:
41: 42: 43:
44: const HTTP_NO_CONTENT = 204;
45: const HTTP_RESET_CONTENT = 205;
46: const HTTP_PARTIAL_CONTENT = 206;
47: const HTTP_MULTI_STATUS = 207;
48: const HTTP_ALREADY_REPORTED = 208;
49: const HTTP_IM_USED = 226;
50:
51:
52:
53: const HTTP_MULTIPLE_CHOICES = 300;
54: const HTTP_MOVED_PERMANENTLY = 301;
55: const HTTP_FOUND = 302;
56: const HTTP_SEE_OTHER = 303;
57:
58: 59: 60:
61: const HTTP_NOT_MODIFIED = 304;
62: const HTTP_USE_PROXY = 305;
63: const HTTP_RESERVED = 306;
64: const HTTP_TEMPORARY_REDIRECT = 307;
65: const HTTP_PERMANENTLY_REDIRECT = 308;
66:
67:
68:
69: 70: 71:
72: const HTTP_BAD_REQUEST = 400;
73:
74: 75: 76:
77: const HTTP_UNAUTHORIZED = 401;
78: const HTTP_PAYMENT_REQUIRED = 402;
79:
80: 81: 82:
83: const HTTP_FORBIDDEN = 403;
84:
85: 86: 87: 88: 89: 90:
91: const HTTP_NOT_FOUND = 404;
92:
93: 94: 95:
96: const HTTP_METHOD_NOT_ALLOWED = 405;
97:
98: 99: 100:
101: const HTTP_NOT_ACCEPTABLE = 406;
102: const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
103: const HTTP_REQUEST_TIMEOUT = 408;
104:
105: 106: 107: 108:
109: const HTTP_CONFLICT = 409;
110: const HTTP_GONE = 410;
111: const HTTP_LENGTH_REQUIRED = 411;
112: const HTTP_PRECONDITION_FAILED = 412;
113: const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
114: const HTTP_REQUEST_URI_TOO_LONG = 414;
115: const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
116: const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
117: const HTTP_EXPECTATION_FAILED = 417;
118: const HTTP_I_AM_A_TEAPOT = 418;
119: const HTTP_UNPROCESSABLE_ENTITY = 422;
120: const HTTP_LOCKED = 423;
121: const HTTP_FAILED_DEPENDENCY = 424;
122: const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;
123: const HTTP_UPGRADE_REQUIRED = 426;
124: const HTTP_PRECONDITION_REQUIRED = 428;
125: const HTTP_TOO_MANY_REQUESTS = 429;
126: const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
127:
128:
129:
130: 131: 132: 133: 134: 135:
136: const HTTP_INTERNAL_SERVER_ERROR = 500;
137:
138: 139: 140:
141: const HTTP_NOT_IMPLEMENTED = 501;
142: const HTTP_BAD_GATEWAY = 502;
143: const HTTP_SERVICE_UNAVAILABLE = 503;
144: const HTTP_GATEWAY_TIMEOUT = 504;
145: const HTTP_VERSION_NOT_SUPPORTED = 505;
146: const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
147: const HTTP_INSUFFICIENT_STORAGE = 507;
148: const HTTP_LOOP_DETECTED = 508;
149: const HTTP_NOT_EXTENDED = 510;
150: const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
151:
152: 153: 154: 155: 156: 157:
158: protected $rest_format = NULL;
159:
160: 161: 162: 163: 164:
165: protected $methods = [];
166:
167: 168: 169: 170: 171:
172: protected $allowed_http_methods = ['get', 'delete', 'post', 'put', 'options', 'patch', 'head'];
173:
174: 175: 176: 177: 178: 179: 180:
181: protected $request = NULL;
182:
183: 184: 185: 186: 187: 188: 189:
190: protected $response = NULL;
191:
192: 193: 194: 195: 196: 197: 198:
199: protected $rest = NULL;
200:
201: 202: 203: 204: 205:
206: protected $_get_args = [];
207:
208: 209: 210: 211: 212:
213: protected $_post_args = [];
214:
215: 216: 217: 218: 219:
220: protected $_insert_id = '';
221:
222: 223: 224: 225: 226:
227: protected $_put_args = [];
228:
229: 230: 231: 232: 233:
234: protected $_delete_args = [];
235:
236: 237: 238: 239: 240:
241: protected $_patch_args = [];
242:
243: 244: 245: 246: 247:
248: protected $_head_args = [];
249:
250: 251: 252: 253: 254:
255: protected $_options_args = [];
256:
257: 258: 259: 260: 261:
262: protected $_query_args = [];
263:
264: 265: 266: 267: 268:
269: protected $_args = [];
270:
271: 272: 273: 274: 275:
276: protected $_allow = TRUE;
277:
278: 279: 280: 281: 282:
283: protected $_user_ldap_dn = '';
284:
285: 286: 287: 288: 289:
290: protected $_start_rtime = '';
291:
292: 293: 294: 295: 296:
297: protected $_end_rtime = '';
298:
299: 300: 301: 302: 303:
304: protected $_supported_formats = [
305: 'json' => 'application/json',
306: 'array' => 'application/json',
307: 'csv' => 'application/csv',
308: 'html' => 'text/html',
309: 'jsonp' => 'application/javascript',
310: 'php' => 'text/plain',
311: 'serialized' => 'application/vnd.php.serialized',
312: 'xml' => 'application/xml'
313: ];
314:
315: 316: 317: 318: 319:
320: protected $_apiuser;
321:
322: 323: 324: 325: 326: 327: 328: 329:
330: protected $_enable_xss = FALSE;
331:
332: 333: 334: 335: 336: 337: 338:
339: protected $http_status_codes = [
340: self::HTTP_OK => 'OK',
341: self::HTTP_CREATED => 'CREATED',
342: self::HTTP_NO_CONTENT => 'NO CONTENT',
343: self::HTTP_NOT_MODIFIED => 'NOT MODIFIED',
344: self::HTTP_BAD_REQUEST => 'BAD REQUEST',
345: self::HTTP_UNAUTHORIZED => 'UNAUTHORIZED',
346: self::HTTP_FORBIDDEN => 'FORBIDDEN',
347: self::HTTP_NOT_FOUND => 'NOT FOUND',
348: self::HTTP_METHOD_NOT_ALLOWED => 'METHOD NOT ALLOWED',
349: self::HTTP_NOT_ACCEPTABLE => 'NOT ACCEPTABLE',
350: self::HTTP_CONFLICT => 'CONFLICT',
351: self::HTTP_INTERNAL_SERVER_ERROR => 'INTERNAL SERVER ERROR',
352: self::HTTP_NOT_IMPLEMENTED => 'NOT IMPLEMENTED'
353: ];
354:
355: 356: 357: 358: 359: 360:
361: protected function early_checks()
362: {
363: }
364:
365: 366: 367: 368: 369: 370: 371: 372:
373: public function __construct($config = 'rest')
374: {
375: parent::__construct();
376:
377:
378: libxml_disable_entity_loader(TRUE);
379:
380:
381: if (is_php('5.4') === FALSE)
382: {
383:
384: exit('Using PHP v' . PHP_VERSION . ', though PHP v5.4 or greater is required');
385: }
386:
387:
388: if (explode('.', CI_VERSION, 2)[0] < 3)
389: {
390: exit('REST Server requires CodeIgniter 3.x');
391: }
392:
393:
394: $this->_enable_xss = ($this->config->item('global_xss_filtering') === TRUE);
395:
396:
397:
398: $this->output->parse_exec_vars = FALSE;
399:
400:
401: $this->_start_rtime = microtime(TRUE);
402:
403:
404: $this->load->config($config);
405:
406:
407: $this->load->library('format');
408:
409:
410: $language = $this->config->item('rest_language');
411: if ($language === NULL)
412: {
413: $language = 'english';
414: }
415:
416:
417: $this->lang->load('rest_controller', $language);
418:
419:
420: $this->request = new stdClass();
421: $this->response = new stdClass();
422: $this->rest = new stdClass();
423:
424:
425: if ($this->config->item('rest_ip_blacklist_enabled') === TRUE)
426: {
427: $this->_check_blacklist_auth();
428: }
429:
430:
431: $this->request->ssl = is_https();
432:
433:
434: $this->request->method = $this->_detect_method();
435:
436:
437: if (isset($this->{'_' . $this->request->method . '_args'}) === FALSE)
438: {
439: $this->{'_' . $this->request->method . '_args'} = [];
440: }
441:
442:
443: $this->_parse_query();
444:
445:
446: $this->_get_args = array_merge($this->_get_args, $this->uri->ruri_to_assoc());
447:
448:
449: $this->request->format = $this->_detect_input_format();
450:
451:
452: $this->request->body = NULL;
453:
454: $this->{'_parse_' . $this->request->method}();
455:
456:
457: if ($this->request->format && $this->request->body)
458: {
459: $this->request->body = $this->format->factory($this->request->body, $this->request->format)->to_array();
460:
461: $this->{'_' . $this->request->method . '_args'} = $this->request->body;
462: }
463:
464:
465: $this->_args = array_merge(
466: $this->_get_args,
467: $this->_options_args,
468: $this->_patch_args,
469: $this->_head_args,
470: $this->_put_args,
471: $this->_post_args,
472: $this->_delete_args,
473: $this->{'_' . $this->request->method . '_args'}
474: );
475:
476:
477: $this->response->format = $this->_detect_output_format();
478:
479:
480: $this->response->lang = $this->_detect_lang();
481:
482:
483: $this->early_checks();
484:
485:
486: if ($this->config->item('rest_database_group') && ($this->config->item('rest_enable_keys') || $this->config->item('rest_enable_logging')))
487: {
488: $this->rest->db = $this->load->database($this->config->item('rest_database_group'), TRUE);
489: }
490:
491:
492: elseif (property_exists($this, 'db'))
493: {
494: $this->rest->db = $this->db;
495: }
496:
497:
498:
499: $this->auth_override = $this->_auth_override_check();
500:
501:
502:
503: if ($this->config->item('rest_enable_keys') && $this->auth_override !== TRUE)
504: {
505: $this->_allow = $this->_detect_api_key();
506: }
507:
508:
509: if ($this->input->is_ajax_request() === FALSE && $this->config->item('rest_ajax_only'))
510: {
511:
512: $this->response([
513: $this->config->item('rest_status_field_name') => FALSE,
514: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ajax_only')
515: ], self::HTTP_NOT_ACCEPTABLE);
516: }
517:
518:
519: if ($this->auth_override === FALSE && !($this->config->item('rest_enable_keys') && $this->_allow === TRUE))
520: {
521: $rest_auth = strtolower($this->config->item('rest_auth'));
522: switch ($rest_auth)
523: {
524: case 'basic':
525: $this->_prepare_basic_auth();
526: break;
527: case 'digest':
528: $this->_prepare_digest_auth();
529: break;
530: case 'session':
531: $this->_check_php_session();
532: break;
533: }
534: if ($this->config->item('rest_ip_whitelist_enabled') === TRUE)
535: {
536: $this->_check_whitelist_auth();
537: }
538: }
539: }
540:
541: 542: 543: 544: 545: 546: 547:
548: public function __destruct()
549: {
550:
551: $this->_end_rtime = microtime(TRUE);
552:
553:
554: if ($this->config->item('rest_enable_logging') === TRUE)
555: {
556: $this->_log_access_time();
557: }
558: }
559:
560: 561: 562: 563: 564: 565: 566: 567: 568:
569: public function _remap($object_called, $arguments)
570: {
571:
572: if ($this->config->item('force_https') && $this->request->ssl === FALSE)
573: {
574: $this->response([
575: $this->config->item('rest_status_field_name') => FALSE,
576: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unsupported')
577: ], self::HTTP_FORBIDDEN);
578: }
579:
580:
581: $object_called = preg_replace('/^(.*)\.(?:' . implode('|', array_keys($this->_supported_formats)) . ')$/', '$1', $object_called);
582:
583: $controller_method = $object_called . '_' . $this->request->method;
584:
585:
586: $log_method = !(isset($this->methods[$controller_method]['log']) && $this->methods[$controller_method]['log'] === FALSE);
587:
588:
589: $use_key = !(isset($this->methods[$controller_method]['key']) && $this->methods[$controller_method]['key'] === FALSE);
590:
591:
592: if ($this->config->item('rest_enable_keys') && $use_key && $this->_allow === FALSE)
593: {
594: if ($this->config->item('rest_enable_logging') && $log_method)
595: {
596: $this->_log_request();
597: }
598:
599: $this->response([
600: $this->config->item('rest_status_field_name') => FALSE,
601: $this->config->item('rest_message_field_name') => sprintf($this->lang->line('text_rest_invalid_api_key'), $this->rest->key)
602: ], self::HTTP_FORBIDDEN);
603: }
604:
605:
606: if ($this->config->item('rest_enable_keys') && $use_key && empty($this->rest->key) === FALSE && $this->_check_access() === FALSE)
607: {
608: if ($this->config->item('rest_enable_logging') && $log_method)
609: {
610: $this->_log_request();
611: }
612:
613: $this->response([
614: $this->config->item('rest_status_field_name') => FALSE,
615: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_unauthorized')
616: ], self::HTTP_UNAUTHORIZED);
617: }
618:
619:
620: if (method_exists($this, $controller_method) === FALSE)
621: {
622: $this->response([
623: $this->config->item('rest_status_field_name') => FALSE,
624: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unknown_method')
625: ], self::HTTP_NOT_FOUND);
626: }
627:
628:
629: if ($this->config->item('rest_enable_keys') && empty($this->rest->key) === FALSE)
630: {
631:
632: if ($this->config->item('rest_enable_limits') && $this->_check_limit($controller_method) === FALSE)
633: {
634: $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_time_limit')];
635: $this->response($response, self::HTTP_UNAUTHORIZED);
636: }
637:
638:
639: $level = isset($this->methods[$controller_method]['level']) ? $this->methods[$controller_method]['level'] : 0;
640:
641:
642: $authorized = $level <= $this->rest->level;
643:
644:
645: if ($this->config->item('rest_enable_logging') && $log_method)
646: {
647: $this->_log_request($authorized);
648: }
649:
650:
651: $response = [$this->config->item('rest_status_field_name') => FALSE, $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_api_key_permissions')];
652: $authorized || $this->response($response, self::HTTP_UNAUTHORIZED);
653: }
654:
655:
656: elseif ($this->config->item('rest_enable_logging') && $log_method)
657: {
658: $this->_log_request($authorized = TRUE);
659: }
660:
661:
662: try
663: {
664: call_user_func_array([$this, $controller_method], $arguments);
665: }
666: catch (Exception $ex)
667: {
668:
669: $this->response([
670: $this->config->item('rest_status_field_name') => FALSE,
671: $this->config->item('rest_message_field_name') => [
672: 'classname' => get_class($ex),
673: 'message' => $ex->getMessage()
674: ]
675: ], self::HTTP_INTERNAL_SERVER_ERROR);
676: }
677: }
678:
679: 680: 681: 682: 683: 684: 685: 686: 687:
688: public function response($data = NULL, $http_code = NULL, $continue = FALSE)
689: {
690:
691: if ($http_code !== NULL)
692: {
693:
694: $http_code = (int) $http_code;
695: }
696:
697:
698: $output = NULL;
699:
700:
701: if ($data === NULL && $http_code === NULL)
702: {
703: $http_code = self::HTTP_NOT_FOUND;
704: }
705:
706:
707: elseif ($data !== NULL)
708: {
709:
710: if (method_exists($this->format, 'to_' . $this->response->format))
711: {
712:
713: $this->output->set_content_type($this->_supported_formats[$this->response->format], strtolower($this->config->item('charset')));
714: $output = $this->format->factory($data)->{'to_' . $this->response->format}();
715:
716:
717:
718: if ($this->response->format === 'array')
719: {
720: $output = $this->format->factory($output)->{'to_json'}();
721: }
722: }
723: else
724: {
725:
726: if (is_array($data) || is_object($data))
727: {
728: $data = $this->format->factory($data)->{'to_json'}();
729: }
730:
731:
732: $output = $data;
733: }
734: }
735:
736:
737:
738:
739: $http_code > 0 || $http_code = self::HTTP_OK;
740:
741: $this->output->set_status_header($http_code);
742:
743:
744: if ($this->config->item('rest_enable_logging') === TRUE)
745: {
746: $this->_log_response_code($http_code);
747: }
748:
749:
750: $this->output->set_output($output);
751:
752: if ($continue === FALSE)
753: {
754:
755: $this->output->_display();
756: exit;
757: }
758:
759:
760: }
761:
762: 763: 764: 765: 766: 767: 768: 769: 770: 771:
772: public function set_response($data = NULL, $http_code = NULL)
773: {
774: $this->response($data, $http_code, TRUE);
775: }
776:
777: 778: 779: 780: 781: 782:
783: protected function _detect_input_format()
784: {
785:
786: $content_type = $this->input->server('CONTENT_TYPE');
787:
788: if (empty($content_type) === FALSE)
789: {
790:
791: foreach ($this->_supported_formats as $key => $value)
792: {
793:
794:
795:
796:
797:
798: $content_type = (strpos($content_type, ';') !== FALSE ? current(explode(';', $content_type)) : $content_type);
799:
800:
801: if ($content_type === $value)
802: {
803: return $key;
804: }
805: }
806: }
807:
808: return NULL;
809: }
810:
811: 812: 813: 814: 815: 816:
817: protected function _detect_output_format()
818: {
819:
820: $pattern = '/\.(' . implode('|', array_keys($this->_supported_formats)) . ')($|\/)/';
821: $matches = [];
822:
823:
824: if (preg_match($pattern, $this->uri->uri_string(), $matches))
825: {
826: return $matches[1];
827: }
828:
829:
830: if (isset($this->_get_args['format']))
831: {
832: $format = strtolower($this->_get_args['format']);
833:
834: if (isset($this->_supported_formats[$format]) === TRUE)
835: {
836: return $format;
837: }
838: }
839:
840:
841: $http_accept = $this->input->server('HTTP_ACCEPT');
842:
843:
844: if ($this->config->item('rest_ignore_http_accept') === FALSE && $http_accept !== NULL)
845: {
846:
847: foreach (array_keys($this->_supported_formats) as $format)
848: {
849:
850: if (strpos($http_accept, $format) !== FALSE)
851: {
852: if ($format !== 'html' && $format !== 'xml')
853: {
854:
855: return $format;
856: }
857: elseif ($format === 'html' && strpos($http_accept, 'xml') === FALSE)
858: {
859:
860:
861: return $format;
862: }
863: else if ($format === 'xml' && strpos($http_accept, 'html') === FALSE)
864: {
865:
866: return $format;
867: }
868: }
869: }
870: }
871:
872:
873: if (empty($this->rest_format) === FALSE)
874: {
875: return $this->rest_format;
876: }
877:
878:
879: return $this->config->item('rest_default_format');
880: }
881:
882: 883: 884: 885: 886: 887:
888: protected function _detect_method()
889: {
890:
891: $method = NULL;
892:
893:
894: if ($this->config->item('enable_emulate_request') === TRUE)
895: {
896: $method = $this->input->post('_method');
897: if ($method === NULL)
898: {
899: $method = $this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE');
900: }
901:
902: $method = strtolower($method);
903: }
904:
905: if (empty($method))
906: {
907:
908: $method = $this->input->method();
909: }
910:
911: return in_array($method, $this->allowed_http_methods) && method_exists($this, '_parse_' . $method) ? $method : 'get';
912: }
913:
914: 915: 916: 917: 918: 919:
920: protected function _detect_api_key()
921: {
922:
923: $api_key_variable = $this->config->item('rest_key_name');
924:
925:
926: $key_name = 'HTTP_' . strtoupper(str_replace('-', '_', $api_key_variable));
927:
928: $this->rest->key = NULL;
929: $this->rest->level = NULL;
930: $this->rest->user_id = NULL;
931: $this->rest->ignore_limits = FALSE;
932:
933:
934: if (($key = isset($this->_args[$api_key_variable]) ? $this->_args[$api_key_variable] : $this->input->server($key_name)))
935: {
936: if (!($row = $this->rest->db->where($this->config->item('rest_key_column'), $key)->get($this->config->item('rest_keys_table'))->row()))
937: {
938: return FALSE;
939: }
940:
941: $this->rest->key = $row->{$this->config->item('rest_key_column')};
942:
943: isset($row->user_id) && $this->rest->user_id = $row->user_id;
944: isset($row->level) && $this->rest->level = $row->level;
945: isset($row->ignore_limits) && $this->rest->ignore_limits = $row->ignore_limits;
946:
947: $this->_apiuser = $row;
948:
949: 950: 951: 952:
953: if (empty($row->is_private_key) === FALSE)
954: {
955:
956: if (isset($row->ip_addresses))
957: {
958:
959: $list_ip_addresses = explode(',', $row->ip_addresses);
960: $found_address = FALSE;
961:
962: foreach ($list_ip_addresses as $ip_address)
963: {
964: if ($this->input->ip_address() === trim($ip_address))
965: {
966:
967: $found_address = TRUE;
968: break;
969: }
970: }
971:
972: return $found_address;
973: }
974: else
975: {
976:
977: return FALSE;
978: }
979: }
980:
981: return TRUE;
982: }
983:
984:
985: return FALSE;
986: }
987:
988: 989: 990: 991: 992: 993:
994: protected function _detect_lang()
995: {
996: $lang = $this->input->server('HTTP_ACCEPT_LANGUAGE');
997: if ($lang === NULL)
998: {
999: return NULL;
1000: }
1001:
1002:
1003: if (strpos($lang, ',') !== FALSE)
1004: {
1005: $langs = explode(',', $lang);
1006:
1007: $return_langs = [];
1008: foreach ($langs as $lang)
1009: {
1010:
1011: list($lang) = explode(';', $lang);
1012: $return_langs[] = trim($lang);
1013: }
1014:
1015: return $return_langs;
1016: }
1017:
1018:
1019: return $lang;
1020: }
1021:
1022: 1023: 1024: 1025: 1026: 1027: 1028:
1029: protected function _log_request($authorized = FALSE)
1030: {
1031:
1032: $is_inserted = $this->rest->db
1033: ->insert(
1034: $this->config->item('rest_logs_table'), [
1035: 'uri' => $this->uri->uri_string(),
1036: 'method' => $this->request->method,
1037: 'params' => $this->_args ? ($this->config->item('rest_logs_json_params') === TRUE ? json_encode($this->_args) : serialize($this->_args)) : NULL,
1038: 'api_key' => isset($this->rest->key) ? $this->rest->key : '',
1039: 'ip_address' => $this->input->ip_address(),
1040: 'time' => now(),
1041: 'authorized' => $authorized
1042: ]);
1043:
1044:
1045: $this->_insert_id = $this->rest->db->insert_id();
1046:
1047: return $is_inserted;
1048: }
1049:
1050: 1051: 1052: 1053: 1054: 1055: 1056:
1057: protected function _check_limit($controller_method)
1058: {
1059:
1060: if (empty($this->rest->ignore_limits) === FALSE)
1061: {
1062:
1063: return TRUE;
1064: }
1065:
1066: switch ($this->config->item('rest_limits_method'))
1067: {
1068: case 'API_KEY':
1069: $limited_uri = 'api-key:' . (isset($this->rest->key) ? $this->rest->key : '');
1070: $limited_method_name = isset($this->rest->key) ? $this->rest->key : '';
1071: break;
1072:
1073: case 'METHOD_NAME':
1074: $limited_uri = 'method-name:' . $controller_method;
1075: $limited_method_name = $controller_method;
1076: break;
1077:
1078: case 'ROUTED_URL':
1079: default:
1080: $limited_uri = $this->uri->ruri_string();
1081: if (strpos(strrev($limited_uri), strrev($this->response->format)) === 0)
1082: {
1083: $limited_uri = substr($limited_uri,0, -strlen($this->response->format) - 1);
1084: }
1085: $limited_uri = 'uri:' . $limited_uri . ':' . $this->request->method;
1086: $limited_method_name = $controller_method;
1087: break;
1088: }
1089:
1090: if (isset($this->methods[$limited_method_name]['limit']) === FALSE )
1091: {
1092:
1093: return TRUE;
1094: }
1095:
1096:
1097: $limit = $this->methods[$limited_method_name]['limit'];
1098:
1099: $time_limit = (isset($this->methods[$limited_method_name]['time']) ? $this->methods[$limited_method_name]['time'] : 3600);
1100:
1101:
1102: $result = $this->rest->db
1103: ->where('uri', $limited_uri)
1104: ->where('api_key', $this->rest->key)
1105: ->get($this->config->item('rest_limits_table'))
1106: ->row();
1107:
1108:
1109: if ($result === NULL)
1110: {
1111:
1112: $this->rest->db->insert($this->config->item('rest_limits_table'), [
1113: 'uri' => $limited_uri,
1114: 'api_key' => isset($this->rest->key) ? $this->rest->key : '',
1115: 'count' => 1,
1116: 'hour_started' => time()
1117: ]);
1118: }
1119:
1120:
1121: elseif ($result->hour_started < (time() - $time_limit))
1122: {
1123:
1124: $this->rest->db
1125: ->where('uri', $limited_uri)
1126: ->where('api_key', isset($this->rest->key) ? $this->rest->key : '')
1127: ->set('hour_started', time())
1128: ->set('count', 1)
1129: ->update($this->config->item('rest_limits_table'));
1130: }
1131:
1132:
1133: else
1134: {
1135:
1136: if ($result->count >= $limit)
1137: {
1138: return FALSE;
1139: }
1140:
1141:
1142: $this->rest->db
1143: ->where('uri', $limited_uri)
1144: ->where('api_key', $this->rest->key)
1145: ->set('count', 'count + 1', FALSE)
1146: ->update($this->config->item('rest_limits_table'));
1147: }
1148:
1149: return TRUE;
1150: }
1151:
1152: 1153: 1154: 1155: 1156: 1157:
1158: protected function _auth_override_check()
1159: {
1160:
1161: $auth_override_class_method = $this->config->item('auth_override_class_method');
1162:
1163:
1164: if (!empty($auth_override_class_method))
1165: {
1166:
1167: if (!empty($auth_override_class_method[$this->router->class]['*']))
1168: {
1169:
1170: if ($auth_override_class_method[$this->router->class]['*'] === 'none')
1171: {
1172: return TRUE;
1173: }
1174:
1175:
1176: if ($auth_override_class_method[$this->router->class]['*'] === 'basic')
1177: {
1178: $this->_prepare_basic_auth();
1179:
1180: return TRUE;
1181: }
1182:
1183:
1184: if ($auth_override_class_method[$this->router->class]['*'] === 'digest')
1185: {
1186: $this->_prepare_digest_auth();
1187:
1188: return TRUE;
1189: }
1190:
1191:
1192: if ($auth_override_class_method[$this->router->class]['*'] === 'whitelist')
1193: {
1194: $this->_check_whitelist_auth();
1195:
1196: return TRUE;
1197: }
1198: }
1199:
1200:
1201: if (!empty($auth_override_class_method[$this->router->class][$this->router->method]))
1202: {
1203:
1204: if ($auth_override_class_method[$this->router->class][$this->router->method] === 'none')
1205: {
1206: return TRUE;
1207: }
1208:
1209:
1210: if ($auth_override_class_method[$this->router->class][$this->router->method] === 'basic')
1211: {
1212: $this->_prepare_basic_auth();
1213:
1214: return TRUE;
1215: }
1216:
1217:
1218: if ($auth_override_class_method[$this->router->class][$this->router->method] === 'digest')
1219: {
1220: $this->_prepare_digest_auth();
1221:
1222: return TRUE;
1223: }
1224:
1225:
1226: if ($auth_override_class_method[$this->router->class][$this->router->method] === 'whitelist')
1227: {
1228: $this->_check_whitelist_auth();
1229:
1230: return TRUE;
1231: }
1232: }
1233: }
1234:
1235:
1236: $auth_override_class_method_http = $this->config->item('auth_override_class_method_http');
1237:
1238:
1239: if (!empty($auth_override_class_method_http))
1240: {
1241:
1242: if(!empty($auth_override_class_method_http[$this->router->class]['*'][$this->request->method]))
1243: {
1244:
1245: if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'none')
1246: {
1247: return TRUE;
1248: }
1249:
1250:
1251: if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'basic')
1252: {
1253: $this->_prepare_basic_auth();
1254:
1255: return TRUE;
1256: }
1257:
1258:
1259: if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'digest')
1260: {
1261: $this->_prepare_digest_auth();
1262:
1263: return TRUE;
1264: }
1265:
1266:
1267: if ($auth_override_class_method_http[$this->router->class]['*'][$this->request->method] === 'whitelist')
1268: {
1269: $this->_check_whitelist_auth();
1270:
1271: return TRUE;
1272: }
1273: }
1274:
1275:
1276: if(!empty($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method]))
1277: {
1278:
1279: if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'none')
1280: {
1281: return TRUE;
1282: }
1283:
1284:
1285: if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'basic')
1286: {
1287: $this->_prepare_basic_auth();
1288:
1289: return TRUE;
1290: }
1291:
1292:
1293: if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'digest')
1294: {
1295: $this->_prepare_digest_auth();
1296:
1297: return TRUE;
1298: }
1299:
1300:
1301: if ($auth_override_class_method_http[$this->router->class][$this->router->method][$this->request->method] === 'whitelist')
1302: {
1303: $this->_check_whitelist_auth();
1304:
1305: return TRUE;
1306: }
1307: }
1308: }
1309: return FALSE;
1310: }
1311:
1312: 1313: 1314: 1315: 1316: 1317:
1318: protected function _parse_get()
1319: {
1320:
1321: $this->_get_args = array_merge($this->_get_args, $this->_query_args);
1322: }
1323:
1324: 1325: 1326: 1327: 1328: 1329:
1330: protected function _parse_post()
1331: {
1332: $this->_post_args = $_POST;
1333:
1334: if ($this->request->format)
1335: {
1336: $this->request->body = $this->input->raw_input_stream;
1337: }
1338: }
1339:
1340: 1341: 1342: 1343: 1344: 1345:
1346: protected function _parse_put()
1347: {
1348: if ($this->request->format)
1349: {
1350: $this->request->body = $this->input->raw_input_stream;
1351: }
1352: else
1353: {
1354:
1355: if ($this->input->method() === 'put')
1356: {
1357: $this->_put_args = $this->input->input_stream();
1358: }
1359: }
1360: }
1361:
1362: 1363: 1364: 1365: 1366: 1367:
1368: protected function _parse_head()
1369: {
1370:
1371: parse_str(parse_url($this->input->server('REQUEST_URI'), PHP_URL_QUERY), $head);
1372:
1373:
1374: $this->_head_args = array_merge($this->_head_args, $head);
1375: }
1376:
1377: 1378: 1379: 1380: 1381: 1382:
1383: protected function _parse_options()
1384: {
1385:
1386: parse_str(parse_url($this->input->server('REQUEST_URI'), PHP_URL_QUERY), $options);
1387:
1388:
1389: $this->_options_args = array_merge($this->_options_args, $options);
1390: }
1391:
1392: 1393: 1394: 1395: 1396: 1397:
1398: protected function _parse_patch()
1399: {
1400:
1401: if ($this->request->format)
1402: {
1403: $this->request->body = $this->input->raw_input_stream;
1404: }
1405: else
1406: {
1407:
1408: if ($this->input->method() === 'patch')
1409: {
1410: $this->_patch_args = $this->input->input_stream();
1411: }
1412: }
1413: }
1414:
1415: 1416: 1417: 1418: 1419: 1420:
1421: protected function _parse_delete()
1422: {
1423:
1424: if ($this->input->method() === 'delete')
1425: {
1426: $this->_delete_args = $this->input->input_stream();
1427: }
1428: }
1429:
1430: 1431: 1432: 1433: 1434: 1435:
1436: protected function _parse_query()
1437: {
1438:
1439: $request_uri = NULL;
1440:
1441:
1442: if (is_cli())
1443: {
1444: $args = $this->input->server('argv');
1445: unset($args[0]);
1446:
1447:
1448: $request_uri = '/' . implode('/', $args) . '/';
1449:
1450:
1451: $_SERVER['REQUEST_URI'] = $request_uri;
1452: $_SERVER['PATH_INFO'] = $request_uri;
1453: $_SERVER['QUERY_STRING'] = $request_uri;
1454: }
1455: else
1456: {
1457: $request_uri = $this->input->server('REQUEST_URI');
1458: }
1459:
1460:
1461: parse_str(parse_url($request_uri, PHP_URL_QUERY), $this->_query_args);
1462: }
1463:
1464:
1465:
1466: 1467: 1468: 1469: 1470: 1471: 1472: 1473: 1474:
1475: public function get($key = NULL, $xss_clean = NULL)
1476: {
1477: if ($key === NULL)
1478: {
1479: return $this->_get_args;
1480: }
1481:
1482: return isset($this->_get_args[$key]) ? $this->_xss_clean($this->_get_args[$key], $xss_clean) : NULL;
1483: }
1484:
1485: 1486: 1487: 1488: 1489: 1490: 1491: 1492: 1493:
1494: public function options($key = NULL, $xss_clean = NULL)
1495: {
1496: if ($key === NULL)
1497: {
1498: return $this->_options_args;
1499: }
1500:
1501: return isset($this->_options_args[$key]) ? $this->_xss_clean($this->_options_args[$key], $xss_clean) : NULL;
1502: }
1503:
1504: 1505: 1506: 1507: 1508: 1509: 1510: 1511: 1512:
1513: public function head($key = NULL, $xss_clean = NULL)
1514: {
1515: if ($key === NULL)
1516: {
1517: return $this->head_args;
1518: }
1519:
1520: return isset($this->head_args[$key]) ? $this->_xss_clean($this->head_args[$key], $xss_clean) : NULL;
1521: }
1522:
1523: 1524: 1525: 1526: 1527: 1528: 1529: 1530: 1531:
1532: public function post($key = NULL, $xss_clean = NULL)
1533: {
1534: if ($key === NULL)
1535: {
1536: return $this->_post_args;
1537: }
1538:
1539: return isset($this->_post_args[$key]) ? $this->_xss_clean($this->_post_args[$key], $xss_clean) : NULL;
1540: }
1541:
1542: 1543: 1544: 1545: 1546: 1547: 1548: 1549: 1550:
1551: public function put($key = NULL, $xss_clean = NULL)
1552: {
1553: if ($key === NULL)
1554: {
1555: return $this->_put_args;
1556: }
1557:
1558: return isset($this->_put_args[$key]) ? $this->_xss_clean($this->_put_args[$key], $xss_clean) : NULL;
1559: }
1560:
1561: 1562: 1563: 1564: 1565: 1566: 1567: 1568: 1569:
1570: public function delete($key = NULL, $xss_clean = NULL)
1571: {
1572: if ($key === NULL)
1573: {
1574: return $this->_delete_args;
1575: }
1576:
1577: return isset($this->_delete_args[$key]) ? $this->_xss_clean($this->_delete_args[$key], $xss_clean) : NULL;
1578: }
1579:
1580: 1581: 1582: 1583: 1584: 1585: 1586: 1587: 1588:
1589: public function patch($key = NULL, $xss_clean = NULL)
1590: {
1591: if ($key === NULL)
1592: {
1593: return $this->_patch_args;
1594: }
1595:
1596: return isset($this->_patch_args[$key]) ? $this->_xss_clean($this->_patch_args[$key], $xss_clean) : NULL;
1597: }
1598:
1599: 1600: 1601: 1602: 1603: 1604: 1605: 1606: 1607:
1608: public function query($key = NULL, $xss_clean = NULL)
1609: {
1610: if ($key === NULL)
1611: {
1612: return $this->_query_args;
1613: }
1614:
1615: return isset($this->_query_args[$key]) ? $this->_xss_clean($this->_query_args[$key], $xss_clean) : NULL;
1616: }
1617:
1618: 1619: 1620: 1621: 1622: 1623: 1624: 1625: 1626:
1627: protected function _xss_clean($value, $xss_clean)
1628: {
1629: is_bool($xss_clean) || $xss_clean = $this->_enable_xss;
1630:
1631: return $xss_clean === TRUE ? $this->security->xss_clean($value) : $value;
1632: }
1633:
1634: 1635: 1636: 1637: 1638: 1639:
1640: public function validation_errors()
1641: {
1642: $string = strip_tags($this->form_validation->error_string());
1643:
1644: return explode(PHP_EOL, trim($string, PHP_EOL));
1645: }
1646:
1647:
1648:
1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656:
1657: protected function _perform_ldap_auth($username = '', $password = NULL)
1658: {
1659: if (empty($username))
1660: {
1661: log_message('debug', 'LDAP Auth: failure, empty username');
1662: return FALSE;
1663: }
1664:
1665: log_message('debug', 'LDAP Auth: Loading configuration');
1666:
1667: $this->config->load('ldap.php', TRUE);
1668:
1669: $ldap = [
1670: 'timeout' => $this->config->item('timeout', 'ldap'),
1671: 'host' => $this->config->item('server', 'ldap'),
1672: 'port' => $this->config->item('port', 'ldap'),
1673: 'rdn' => $this->config->item('binduser', 'ldap'),
1674: 'pass' => $this->config->item('bindpw', 'ldap'),
1675: 'basedn' => $this->config->item('basedn', 'ldap'),
1676: ];
1677:
1678: log_message('debug', 'LDAP Auth: Connect to ' . (isset($ldaphost) ? $ldaphost : '[ldap not configured]'));
1679:
1680:
1681: $ldapconn = ldap_connect($ldap['host'], $ldap['port']);
1682: if ($ldapconn)
1683: {
1684: log_message('debug', 'Setting timeout to ' . $ldap['timeout'] . ' seconds');
1685:
1686: ldap_set_option($ldapconn, LDAP_OPT_NETWORK_TIMEOUT, $ldap['timeout']);
1687:
1688: log_message('debug', 'LDAP Auth: Binding to ' . $ldap['host'] . ' with dn ' . $ldap['rdn']);
1689:
1690:
1691: $ldapbind = ldap_bind($ldapconn, $ldap['rdn'], $ldap['pass']);
1692:
1693:
1694: if ($ldapbind === FALSE)
1695: {
1696: log_message('error', 'LDAP Auth: bind was unsuccessful');
1697: return FALSE;
1698: }
1699:
1700: log_message('debug', 'LDAP Auth: bind successful');
1701: }
1702:
1703:
1704: if (($res_id = ldap_search($ldapconn, $ldap['basedn'], "uid=$username")) === FALSE)
1705: {
1706: log_message('error', 'LDAP Auth: User ' . $username . ' not found in search');
1707: return FALSE;
1708: }
1709:
1710: if (ldap_count_entries($ldapconn, $res_id) !== 1)
1711: {
1712: log_message('error', 'LDAP Auth: Failure, username ' . $username . 'found more than once');
1713: return FALSE;
1714: }
1715:
1716: if (($entry_id = ldap_first_entry($ldapconn, $res_id)) === FALSE)
1717: {
1718: log_message('error', 'LDAP Auth: Failure, entry of search result could not be fetched');
1719: return FALSE;
1720: }
1721:
1722: if (($user_dn = ldap_get_dn($ldapconn, $entry_id)) === FALSE)
1723: {
1724: log_message('error', 'LDAP Auth: Failure, user-dn could not be fetched');
1725: return FALSE;
1726: }
1727:
1728:
1729: if (($link_id = ldap_bind($ldapconn, $user_dn, $password)) === FALSE)
1730: {
1731: log_message('error', 'LDAP Auth: Failure, username/password did not match: ' . $user_dn);
1732: return FALSE;
1733: }
1734:
1735: log_message('debug', 'LDAP Auth: Success ' . $user_dn . ' authenticated successfully');
1736:
1737: $this->_user_ldap_dn = $user_dn;
1738:
1739: ldap_close($ldapconn);
1740:
1741: return TRUE;
1742: }
1743:
1744: 1745: 1746: 1747: 1748: 1749: 1750: 1751:
1752: protected function _perform_library_auth($username = '', $password = NULL)
1753: {
1754: if (empty($username))
1755: {
1756: log_message('error', 'Library Auth: Failure, empty username');
1757: return FALSE;
1758: }
1759:
1760: $auth_library_class = strtolower($this->config->item('auth_library_class'));
1761: $auth_library_function = strtolower($this->config->item('auth_library_function'));
1762:
1763: if (empty($auth_library_class))
1764: {
1765: log_message('debug', 'Library Auth: Failure, empty auth_library_class');
1766: return FALSE;
1767: }
1768:
1769: if (empty($auth_library_function))
1770: {
1771: log_message('debug', 'Library Auth: Failure, empty auth_library_function');
1772: return FALSE;
1773: }
1774:
1775: if (is_callable([$auth_library_class, $auth_library_function]) === FALSE)
1776: {
1777: $this->load->library($auth_library_class);
1778: }
1779:
1780: return $this->{$auth_library_class}->$auth_library_function($username, $password);
1781: }
1782:
1783: 1784: 1785: 1786: 1787: 1788: 1789: 1790:
1791: protected function _check_login($username = NULL, $password = FALSE)
1792: {
1793: if (empty($username))
1794: {
1795: return FALSE;
1796: }
1797:
1798: $auth_source = strtolower($this->config->item('auth_source'));
1799: $rest_auth = strtolower($this->config->item('rest_auth'));
1800: $valid_logins = $this->config->item('rest_valid_logins');
1801:
1802: if (!$this->config->item('auth_source') && $rest_auth === 'digest')
1803: {
1804:
1805: return md5($username . ':' . $this->config->item('rest_realm') . ':' . (isset($valid_logins[$username]) ? $valid_logins[$username] : ''));
1806: }
1807:
1808: if ($password === FALSE)
1809: {
1810: return FALSE;
1811: }
1812:
1813: if ($auth_source === 'ldap')
1814: {
1815: log_message('debug', "Performing LDAP authentication for $username");
1816:
1817: return $this->_perform_ldap_auth($username, $password);
1818: }
1819:
1820: if ($auth_source === 'library')
1821: {
1822: log_message('debug', "Performing Library authentication for $username");
1823:
1824: return $this->_perform_library_auth($username, $password);
1825: }
1826:
1827: if (array_key_exists($username, $valid_logins) === FALSE)
1828: {
1829: return FALSE;
1830: }
1831:
1832: if ($valid_logins[$username] !== $password)
1833: {
1834: return FALSE;
1835: }
1836:
1837: return TRUE;
1838: }
1839:
1840: 1841: 1842: 1843: 1844: 1845:
1846: protected function _check_php_session()
1847: {
1848:
1849: $key = $this->config->item('auth_source');
1850:
1851:
1852: if (!$this->session->userdata($key))
1853: {
1854:
1855: $this->response([
1856: $this->config->item('rest_status_field_name') => FALSE,
1857: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unauthorized')
1858: ], self::HTTP_UNAUTHORIZED);
1859: }
1860: }
1861:
1862: 1863: 1864: 1865: 1866: 1867:
1868: protected function _prepare_basic_auth()
1869: {
1870:
1871: if ($this->config->item('rest_ip_whitelist_enabled'))
1872: {
1873: $this->_check_whitelist_auth();
1874: }
1875:
1876:
1877: $username = $this->input->server('PHP_AUTH_USER');
1878: $http_auth = $this->input->server('HTTP_AUTHENTICATION');
1879:
1880: $password = NULL;
1881: if ($username !== NULL)
1882: {
1883: $password = $this->input->server('PHP_AUTH_PW');
1884: }
1885: elseif ($http_auth !== NULL)
1886: {
1887:
1888:
1889: if (strpos(strtolower($http_auth), 'basic') === 0)
1890: {
1891:
1892: list($username, $password) = explode(':', base64_decode(substr($this->input->server('HTTP_AUTHORIZATION'), 6)));
1893: }
1894: }
1895:
1896:
1897: if ($this->_check_login($username, $password) === FALSE)
1898: {
1899: $this->_force_login();
1900: }
1901: }
1902:
1903: 1904: 1905: 1906: 1907: 1908:
1909: protected function _prepare_digest_auth()
1910: {
1911:
1912: if ($this->config->item('rest_ip_whitelist_enabled'))
1913: {
1914: $this->_check_whitelist_auth();
1915: }
1916:
1917:
1918:
1919: $digest_string = $this->input->server('PHP_AUTH_DIGEST');
1920: if ($digest_string === NULL)
1921: {
1922: $digest_string = $this->input->server('HTTP_AUTHORIZATION');
1923: }
1924:
1925: $unique_id = uniqid();
1926:
1927:
1928:
1929: if (empty($digest_string))
1930: {
1931: $this->_force_login($unique_id);
1932: }
1933:
1934:
1935: $matches = [];
1936: preg_match_all('@(username|nonce|uri|nc|cnonce|qop|response)=[\'"]?([^\'",]+)@', $digest_string, $matches);
1937: $digest = (empty($matches[1]) || empty($matches[2])) ? [] : array_combine($matches[1], $matches[2]);
1938:
1939:
1940: $username = $this->_check_login($digest['username'], TRUE);
1941: if (array_key_exists('username', $digest) === FALSE || $username === FALSE)
1942: {
1943: $this->_force_login($unique_id);
1944: }
1945:
1946: $md5 = md5(strtoupper($this->request->method) . ':' . $digest['uri']);
1947: $valid_response = md5($username . ':' . $digest['nonce'] . ':' . $digest['nc'] . ':' . $digest['cnonce'] . ':' . $digest['qop'] . ':' . $md5);
1948:
1949:
1950: if (strcasecmp($digest['response'], $valid_response) !== 0)
1951: {
1952:
1953: $this->response([
1954: $this->config->item('rest_status_field_name') => FALSE,
1955: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_invalid_credentials')
1956: ], self::HTTP_UNAUTHORIZED);
1957: }
1958: }
1959:
1960: 1961: 1962: 1963: 1964: 1965:
1966: protected function _check_blacklist_auth()
1967: {
1968:
1969: $pattern = sprintf('/(?:,\s*|^)\Q%s\E(?=,\s*|$)/m', $this->input->ip_address());
1970:
1971:
1972: if (preg_match($pattern, $this->config->item('rest_ip_blacklist')))
1973: {
1974:
1975: $this->response([
1976: $this->config->item('rest_status_field_name') => FALSE,
1977: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ip_denied')
1978: ], self::HTTP_UNAUTHORIZED);
1979: }
1980: }
1981:
1982: 1983: 1984: 1985: 1986: 1987:
1988: protected function _check_whitelist_auth()
1989: {
1990: $whitelist = explode(',', $this->config->item('rest_ip_whitelist'));
1991:
1992: array_push($whitelist, '127.0.0.1', '0.0.0.0');
1993:
1994: foreach ($whitelist as &$ip)
1995: {
1996:
1997:
1998: $ip = trim($ip);
1999: }
2000:
2001: if (in_array($this->input->ip_address(), $whitelist) === FALSE)
2002: {
2003: $this->response([
2004: $this->config->item('rest_status_field_name') => FALSE,
2005: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_ip_unauthorized')
2006: ], self::HTTP_UNAUTHORIZED);
2007: }
2008: }
2009:
2010: 2011: 2012: 2013: 2014: 2015: 2016: 2017:
2018: protected function _force_login($nonce = '')
2019: {
2020: $rest_auth = $this->config->item('rest_auth');
2021: $rest_realm = $this->config->item('rest_realm');
2022: if (strtolower($rest_auth) === 'basic')
2023: {
2024:
2025: header('WWW-Authenticate: Basic realm="' . $rest_realm . '"');
2026: }
2027: elseif (strtolower($rest_auth) === 'digest')
2028: {
2029:
2030: header(
2031: 'WWW-Authenticate: Digest realm="' . $rest_realm
2032: . '", qop="auth", nonce="' . $nonce
2033: . '", opaque="' . md5($rest_realm) . '"');
2034: }
2035:
2036:
2037: $this->response([
2038: $this->config->item('rest_status_field_name') => FALSE,
2039: $this->config->item('rest_message_field_name') => $this->lang->line('text_rest_unauthorized')
2040: ], self::HTTP_UNAUTHORIZED);
2041: }
2042:
2043: 2044: 2045: 2046: 2047: 2048: 2049:
2050: protected function _log_access_time()
2051: {
2052: $payload['rtime'] = $this->_end_rtime - $this->_start_rtime;
2053:
2054: return $this->rest->db->update(
2055: $this->config->item('rest_logs_table'), $payload, [
2056: 'id' => $this->_insert_id
2057: ]);
2058: }
2059:
2060: 2061: 2062: 2063: 2064: 2065: 2066: 2067:
2068: protected function _log_response_code($http_code)
2069: {
2070: $payload['response_code'] = $http_code;
2071:
2072: return $this->rest->db->update(
2073: $this->config->item('rest_logs_table'), $payload, [
2074: 'id' => $this->_insert_id
2075: ]);
2076: }
2077:
2078: 2079: 2080: 2081: 2082: 2083:
2084: protected function _check_access()
2085: {
2086:
2087: if ($this->config->item('rest_enable_access') === FALSE)
2088: {
2089: return TRUE;
2090: }
2091:
2092:
2093: $controller = implode(
2094: '/', [
2095: $this->router->directory,
2096: $this->router->class
2097: ]);
2098:
2099:
2100: $controller = str_replace('//', '/', $controller);
2101:
2102:
2103: return $this->rest->db
2104: ->where('key', $this->rest->key)
2105: ->where('controller', $controller)
2106: ->get($this->config->item('rest_access_table'))
2107: ->num_rows() > 0;
2108: }
2109:
2110: }
2111: