<commit_before><?php

defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * CodeIgniter Rest Controller
 * A fully RESTful server implementation for CodeIgniter using one library, one config file and one controller.
 *
 * @package         CodeIgniter
 * @subpackage      Libraries
 * @category        Libraries
 * @author          <NAME>, <NAME>
 * @license         MIT
 * @link            https://github.com/chriskacerguis/codeigniter-restserver
 * @version         3.0.0
 */
abstract class REST_Controller extends CI_Controller {
    /**
     * This defines the rest format.
     * Must be overridden it in a controller so that it is set.
     *
     * @var string|NULL
     */
    protected $rest_format = NULL;

    /**
     * Defines the list of method properties such as limit, log and level
     *
     * @var array
     */
    protected $methods = [];

    /**
     * List of allowed HTTP methods
     *
     * @var array
     */
    protected $allowed_http_methods = ['get', 'delete', 'post', 'put', 'options', 'patch', 'head'];

    /**
     * General request data and information.
     * Stores accept, language, body, headers, etc.
     *
     * @var object
     */
    protected $request = NULL;

    /**
     * What is gonna happen in output?
     *
     * @var object
     */
    protected $response = NULL;

    /**
     * Stores DB, keys, key level, etc
     *
     * @var object
     */
    protected $rest = NULL;

    /**
     * The arguments for the GET request method
     *
     * @var array
     */
    protected $_get_args = [];

    /**
     * The arguments for the POST request method
     *
     * @var array
     */
    protected $_post_args = [];

    /**
     * The insert_id of the log entry (if we have one)
     *
     * @var string
     */
    protected $_insert_id = '';

    /**
     * The arguments for the PUT request method
     *
     * @var array
     */
    protected $_put_args = [];

    /**
     * The arguments for the DELETE request method
     *
     * @var array
     */
    protected $_delete_args = [];

    /**
     * The arguments for the PATCH request method
     *
     * @var array
     */
    protected $_patch_args = [];

    /**
     * The arguments for the HEAD request method
     *
     * @var array
     */
    protected $_head_args = [];

    /**
     * The arguments for the OPTIONS request method
     *
     * @var array
     */
    protected $_options_args = [];

    /**
     * The arguments from GET, POST, PUT, DELETE request methods combined.
     *
     * @var array
     */
    protected $_args = [];

    /**
     * If the request is allowed based on the API key provided.
     *
     * @var bool
     */
    protected $_allow = TRUE;

    /**
     * Determines if output compression is enabled
     *
     * @var bool
     */
    protected $_zlib_oc = FALSE;

    /**
     * The LDAP Distinguished Name of the User post authentication
     *
     * @var string
     */
    protected $_user_ldap_dn = '';

    /**
     * The start of the response time from the server
     *
     * @var string
     */
    protected $_start_rtime = '';

    /**
     * The end of the response time from the server
     *
     * @var string
     */
    protected $_end_rtime = '';

    /**
     * List all supported methods, the first will be the default format
     *
     * @var array
     */
    protected $_supported_formats
        = [
            'json' => 'application/json',
            'xml' => 'application/xml',
            'jsonp' => 'application/javascript',
            'serialized' => 'application/vnd.php.serialized',
            'php' => 'text/plain',
            'html' => 'text/html',
            'csv' => 'application/csv'
        ];

    /**
     * Information about the current API user
     *
     * @var object
     */
    protected $_apiuser;

    /**
     * Enable XSS flag
     * Determines whether the XSS filter is always active when
     * GET, OPTIONS, HEAD, POST, PUT, DELETE and PATCH data is encountered.
     * Set automatically based on config setting.
     *
     * @var bool
     */
    protected $_enable_xss = FALSE;

    /**
     * Extend this function to apply additional checking early on in the process
     *
     * @access protected
     */
    protected function early_checks()
    {
    }

    /**
     * Constructor for the REST API
     *
     * @access public
     *
     * @param string $config Configuration filename minus the file extension
     * e.g: my_rest.php is passed as 'my_rest'
     */
    public function __construct($config = 'rest')
    {
        parent::__construct();

        // disable XML Entity (security vulnerability)
        libxml_disable_entity_loader(TRUE);

        // Check to see if PHP is equal to or greater than 5.4.x
        if (is_php('5.4') === FALSE)
        {
            // CodeIgniter 3 is recommended for v5.4 or above
            exit('Using PHP v' . PHP_VERSION . ', though PHP v5.4 or greater is required');
        }

        // Check to see if this is CI 3.x
        if (explode('.', CI_VERSION, 2)[0] < 3)
        {
            exit('REST Server requires CodeIgniter 3.x');
        }

        // Set the default value of global xss filtering. Same approach as CodeIgniter 3
        $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);

        // Start the timer for how long the request takes
        $this->_start_rtime = microtime(TRUE);

        // Lets grab the config and get ready to party
        $this->load->config($config);

        // This library is bundled with REST_Controller 2.5+, but will eventually be part of CodeIgniter itself
        $this->load->library('format');

        // init objects
        $this->response = new stdClass();
        $this->rest = new stdClass();

        $this->_zlib_oc = @ini_get('zlib.output_compression');

        // let's learn about the request
        $this->request = new stdClass();

        // Check to see if this IP is Blacklisted
        if ($this->config->item('rest_ip_blacklist_enabled'))
        {
            $this->_check_blacklist_auth();
        }

        // Is it over SSL?
        $this->request->ssl = is_https();

        // How is this request being made? POST, DELETE, GET, PUT?
        $this->request->method = $this->_detect_method();

        // Create argument container, if nonexistent
        if (!isset($this->{'_' . $this->request->method . '_args'}))
        {
            $this->{'_' . $this->request->method . '_args'} = [];
        }

        // Set up our GET variables
        $this->_get_args = array_merge($this->_get_args, $this->uri->ruri_to_assoc());

        // Try to find a format for the request (means we have a request body)
        $this->request->format = $this->_detect_input_format();

        // Some Methods cant have a body
        $this->request->body = NULL;

        $this->{'_parse_' . $this->request->method}();

        // Now we know all about our request, let's try and parse the body if it exists
        if ($this->request->format && $this->request->body)
        {
            $this->request->body = $this->format->factory($this->request->body, $this->request->format)->to_array();
            // Assign payload arguments to proper method container
            $this->{'_' . $this->request->method . '_args'} = $this->request->body;
        }

        // Merge both for one mega-args variable
        $this->_args = array_merge(
            $this->_get_args,
            $this->_options_args,
            $this->_patch_args,
            $this->_head_args,
            $this->_put_args,
            $this->_post_args,
            $this->_delete_args,
            $this->{'_' . $this->request->method . '_args'}
        );

        // Which format should the data be returned in?
        $this->response->format = $this->_detect_output_format();

        // Which format should the data be returned in?
        $this->response->lang = $this->_detect_lang();

        // Extend this function to apply additional checking early on in the process
        $this->early_checks();

        // Load DB if its enabled
        if (config_item('rest_database_group') && (config_item('rest_enable_keys') || config_item('rest_enable_logging')))
        {
            $this->rest->db = $this->load->database(config_item('rest_database_group'), TRUE);
        }

        // Use whatever database is in use (isset returns FALSE)
        elseif (property_exists($this, 'db'))
        {
            $this->rest->db = $this->db;
        }

        // Check if there is a specific auth type for the current class/method
        // _auth_override_check could exit so we need $this->rest->db initialized before
        $this->auth_override = $this->_auth_override_check();

        // Checking for keys? GET TO WorK!
        // Skip keys test for $config['auth_override_class_method']['class'['method'] = 'none'
        if (config_item('rest_enable_keys') && $this->auth_override !== TRUE)
        {
            $this->_allow = $this->_detect_api_key();
        }

        // only allow ajax requests
        if (!$this->input->is_ajax_request() && config_item('rest_ajax_only'))
        {
            $response = [config_item('rest_status_field_name') => FALSE, config_item('rest_message_field_name') => 'Only AJAX requests are accepted.'];
            $this->response($response, 406); // Set status to 406 NOT ACCEPTABLE
        }

        // When there is no specific override for the current class/method, use the default auth value set in the config
        if ($this->auth_override !== TRUE && !(config_item('rest_enable_keys') && $this->_allow === TRUE))
        {
            $rest_auth = strtolower($this->config->item('rest_auth'));
            switch ($rest_auth)
            {
                case 'basic':
                    $this->_prepare_basic_auth();
                    break;
                case 'digest':
                    $this->_prepare_digest_auth();
                    break;
                case 'session':
                    $this->_check_php_session();
                    break;
            }
            if ($this->config->item('rest_ip_whitelist_enabled'))
            {
                $this->_check_whitelist_auth();
            }
        }
    }

    /**
     * Destructor function
     *
     * @author <NAME>
     * @access public
     */
    public function __destruct()
    {
        // Record the "stop" time of the request
        $this->_end_rtime = microtime(TRUE);
        // CK: if, we are logging, log the access time here, as we are done!
        if (config_item('rest_enable_logging'))
        {
            $this->_log_access_time();
        }

    }

    /**
     * Requests are not made to methods directly, the request will be for
     * an "object". This simply maps the object and method to the correct
     * Controller method.
     *<commit_msg>Re-worked the __constructor function<commit_after><?php

defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * CodeIgniter Rest Controller
 * A fully RESTful server implementation for CodeIgniter using one library, one config file and one controller.
 *
 * @package         CodeIgniter
 * @subpackage      Libraries
 * @category        Libraries
 * @author          <NAME>, <NAME>
 * @license         MIT
 * @link            https://github.com/chriskacerguis/codeigniter-restserver
 * @version         3.0.0
 */
abstract class REST_Controller extends CI_Controller {
    /**
     * This defines the rest format.
     * Must be overridden it in a controller so that it is set.
     *
     * @var string|NULL
     */
    protected $rest_format = NULL;

    /**
     * Defines the list of method properties such as limit, log and level
     *
     * @var array
     */
    protected $methods = [];

    /**
     * List of allowed HTTP methods
     *
     * @var array
     */
    protected $allowed_http_methods = ['get', 'delete', 'post', 'put', 'options', 'patch', 'head'];

    /**
     * General request data and information.
     * Stores accept, language, body, headers, etc.
     *
     * @var object
     */
    protected $request = NULL;

    /**
     * What is gonna happen in output?
     *
     * @var object
     */
    protected $response = NULL;

    /**
     * Stores DB, keys, key level, etc
     *
     * @var object
     */
    protected $rest = NULL;

    /**
     * The arguments for the GET request method
     *
     * @var array
     */
    protected $_get_args = [];

    /**
     * The arguments for the POST request method
     *
     * @var array
     */
    protected $_post_args = [];

    /**
     * The insert_id of the log entry (if we have one)
     *
     * @var string
     */
    protected $_insert_id = '';

    /**
     * The arguments for the PUT request method
     *
     * @var array
     */
    protected $_put_args = [];

    /**
     * The arguments for the DELETE request method
     *
     * @var array
     */
    protected $_delete_args = [];

    /**
     * The arguments for the PATCH request method
     *
     * @var array
     */
    protected $_patch_args = [];

    /**
     * The arguments for the HEAD request method
     *
     * @var array
     */
    protected $_head_args = [];

    /**
     * The arguments for the OPTIONS request method
     *
     * @var array
     */
    protected $_options_args = [];

    /**
     * The arguments from GET, POST, PUT, DELETE request methods combined.
     *
     * @var array
     */
    protected $_args = [];

    /**
     * If the request is allowed based on the API key provided.
     *
     * @var bool
     */
    protected $_allow = TRUE;

    /**
     * Determines if output compression is enabled
     *
     * @var bool
     */
    protected $_zlib_oc = FALSE;

    /**
     * The LDAP Distinguished Name of the User post authentication
     *
     * @var string
     */
    protected $_user_ldap_dn = '';

    /**
     * The start of the response time from the server
     *
     * @var string
     */
    protected $_start_rtime = '';

    /**
     * The end of the response time from the server
     *
     * @var string
     */
    protected $_end_rtime = '';

    /**
     * List all supported methods, the first will be the default format
     *
     * @var array
     */
    protected $_supported_formats
        = [
            'json' => 'application/json',
            'xml' => 'application/xml',
            'jsonp' => 'application/javascript',
            'serialized' => 'application/vnd.php.serialized',
            'php' => 'text/plain',
            'html' => 'text/html',
            'csv' => 'application/csv'
        ];

    /**
     * Information about the current API user
     *
     * @var object
     */
    protected $_apiuser;

    /**
     * Enable XSS flag
     * Determines whether the XSS filter is always active when
     * GET, OPTIONS, HEAD, POST, PUT, DELETE and PATCH data is encountered.
     * Set automatically based on config setting.
     *
     * @var bool
     */
    protected $_enable_xss = FALSE;

    /**
     * Extend this function to apply additional checking early on in the process
     *
     * @access protected
     */
    protected function early_checks()
    {
    }

    /**
     * Constructor for the REST API
     *
     * @access public
     *
     * @param string $config Configuration filename minus the file extension
     * e.g: my_rest.php is passed as 'my_rest'
     */
    public function __construct($config = 'rest')
    {
        parent::__construct();

        // Disable XML Entity (security vulnerability)
        libxml_disable_entity_loader(TRUE);

        // Check to see if PHP is equal to or greater than 5.4.x
        if (is_php('5.4') === FALSE)
        {
            // CodeIgniter 3 is recommended for v5.4 or above
            exit('Using PHP v' . PHP_VERSION . ', though PHP v5.4 or greater is required');
        }

        // Check to see if this is CI 3.x
        if (explode('.', CI_VERSION, 2)[0] < 3)
        {
            exit('REST Server requires CodeIgniter 3.x');
        }

        // Set the default value of global xss filtering. Same approach as CodeIgniter 3
        $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);

        // Start the timer for how long the request takes
        $this->_start_rtime = microtime(TRUE);

        // Load the rest.php configuration file
        $this->load->config($config);

        // At present the library is bundled with REST_Controller 2.5+, but will eventually be part of CodeIgniter (no citation)
        $this->load->library('format');

        // Initialise the response, request and rest objects
        $this->request = new stdClass();
        $this->response = new stdClass();
        $this->rest = new stdClass();

        $this->_zlib_oc = @ini_get('zlib.output_compression');

        // Check to see if the current IP address is blacklisted
        if ($this->config->item('rest_ip_blacklist_enabled') === TRUE)
        {
            $this->_check_blacklist_auth();
        }

        // Store whether the the connection is HTTPS
        $this->request->ssl = is_https();

        // How is this request being made? GET, POST, PATCH, DELETE, INSERT, PUT, HEAD or OPTIONS
        $this->request->method = $this->_detect_method();

        // Create an argument container if it doesn't exist e.g. _get_args
        if (!isset($this->{'_' . $this->request->method . '_args'}))
        {
            $this->{'_' . $this->request->method . '_args'} = [];
        }

        // Set up the GET variables
        $this->_get_args = array_merge($this->_get_args, $this->uri->ruri_to_assoc());

        // Try to find a format for the request (means we have a request body)
        $this->request->format = $this->_detect_input_format();

        // Some method can't have a body
        $this->request->body = NULL;

        $this->{'_parse_' . $this->request->method}();

        // Now we know all about our request, let's try and parse the body if it exists
        if ($this->request->format && $this->request->body)
        {
            $this->request->body = $this->format->factory($this->request->body, $this->request->format)->to_array();
            // Assign payload arguments to proper method container
            $this->{'_' . $this->request->method . '_args'} = $this->request->body;
        }

        // Merge both for one mega-args variable
        $this->_args = array_merge(
            $this->_get_args,
            $this->_options_args,
            $this->_patch_args,
            $this->_head_args,
            $this->_put_args,
            $this->_post_args,
            $this->_delete_args,
            $this->{'_' . $this->request->method . '_args'}
        );

        // Which format should the data be returned in?
        $this->response->format = $this->_detect_output_format();

        // Which format should the data be returned in?
        $this->response->lang = $this->_detect_lang();

        // Extend this function to apply additional checking early on in the process
        $this->early_checks();

        // Load DB if its enabled
        if (config_item('rest_database_group') && (config_item('rest_enable_keys') || config_item('rest_enable_logging')))
        {
            $this->rest->db = $this->load->database(config_item('rest_database_group'), TRUE);
        }

        // Use whatever database is in use (isset returns FALSE)
        elseif (property_exists($this, 'db'))
        {
            $this->rest->db = $this->db;
        }

        // Check if there is a specific auth type for the current class/method
        // _auth_override_check could exit so we need $this->rest->db initialized before
        $this->auth_override = $this->_auth_override_check();

        // Checking for keys? GET TO WorK!
        // Skip keys test for $config['auth_override_class_method']['class'['method'] = 'none'
        if (config_item('rest_enable_keys') && $this->auth_override !== TRUE)
        {
            $this->_allow = $this->_detect_api_key();
        }

        // Only allow ajax requests
        if ($this->input->is_ajax_request() === FALSE && config_item('rest_ajax_only'))
        {
            // Display an error response
            $this->response(
                [
                    config_item('rest_status_field_name') => FALSE,
                    config_item('rest_message_field_name') => 'Only AJAX requests are acceptable'
                ], 406); // Set status to 406 NOT ACCEPTABLE
        }

        // When there is no specific override for the current class/method, use the default auth value set in the config
        if ($this->auth_override === FALSE && !(config_item('rest_enable_keys') && $this->_allow === TRUE))
        {
            $rest_auth = strtolower($this->config->item('rest_auth'));
            switch ($rest_auth)
            {
                case 'basic':
                    $this->_prepare_basic_auth();
                    break;
                case 'digest':
                    $this->_prepare_digest_auth();
                    break;
                case 'session':
                    $this->_check_php_session();
                    break;
            }
            if ($this->config->item('rest_ip_whitelist_enabled') === TRUE)
            {
                $this->_check_whitelist_auth();
            }
        }
    }

    /**
     * Destructor function
     *
     * @author <NAME>
     * @access public
     */
    public function __destruct()
    {
        // Record the "stop" time of the request
        $this->_end_rtime = microtime(TRUE);
        // CK: if, we are logging, log the access time here, as we are done!
        if (config_item('rest_enable_logging'))
        {
            $this->_log_access_time();
        }

    }

    /**
     * Requests are not made to methods directly, the request will be for
     * an "object". This simply maps the object and method to the correct
     * Controller method.
     *
{'fraction_non_alphanumeric': 0.12159338662790697, 'fraction_numerical': 0.0023619186046511626, 'mean_word_length': 1.872032350639186, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 229, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7236808', 'n_tokens_mistral': 6257, 'n_tokens_neox': 6013, 'n_words': 1847}