Welcome Guest, Not a member yet? Register   Sign In
Unable to load library when extending a core library
#1

[eluser]musonic[/eluser]
I've encountered a very strange problem. Firstly, I should point out that I'm using CI 2.0. I'm extending the Input class by creating a MY_Input class and placing it in my application/core folder. So far so good. The problem arises when I try and load a library that is in my application/libraries folder to use some additional functionality.
I've tried the normal
Code:
$this->load->library('csrf');
and then tried to access it using
Code:
$this->csrf->someMethod();
but I get this error:
Code:
Undefined property: MY_Input::$load
.
So, I try and get a CI instance and try it that way. Unfortunately, I simply get:
Code:
Fatal error: Call to undefined function get_instance()
Finally, I tried this:
Code:
$this->csrf =& load_class('csrf');
. But when I tried to use
Code:
$this->csrf
I was told it was undefined.
Could someone please help me work out what's going on? I'm wasting a lot of time on something that should just work!!!
#2

[eluser]WanWizard[/eluser]
What does your MY_Input look like?
#3

[eluser]musonic[/eluser]
Code:
class MY_Input extends CI_Input {
    
    public function __contruct()
    {
        parent::CI_Input(); log_message('debug', "MY_Input Class Initialized");
    }
    
    function _sanitize_globals()
    {
        // It would be "wrong" to unset any of these GLOBALS.
        $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
                            'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN');

        // Unset globals for securiy.
        // This is effectively the same as register_globals = off
        foreach (array($_GET, $_POST, $_COOKIE) as $global)
        {
            if ( ! is_array($global))
            {
                if ( ! in_array($global, $protected))
                {
                    global $$global;
                    $$global = NULL;
                }
            }
            else
            {
                foreach ($global as $key => $val)
                {
                    if ( ! in_array($key, $protected))
                    {
                        global $$key;
                        $$key = NULL;
                    }
                }
            }
        }

        // Is $_GET data allowed? If not we'll set the $_GET to an empty array
        if ($this->_allow_get_array == FALSE)
        {
            $_GET = array();
        }
        else
        {
            if (is_array($_GET) AND count($_GET) > 0)
            {
                foreach($_GET as $key => $val)
                {
                    $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
                }
            }
        }

        // Clean $_POST Data
        if (is_array($_POST) AND count($_POST) > 0)
        {
            foreach($_POST as $key => $val)
            {
                $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
            }
        }

        // Clean $_COOKIE Data
        if (is_array($_COOKIE) AND count($_COOKIE) > 0)
        {
            // Also get rid of specially treated cookies that might be set by a server
            // or silly application, that are of no use to a CI application anyway
            // but that when present will trip our 'Disallowed Key Characters' alarm
            // http://www.ietf.org/rfc/rfc2109.txt
            // note that the key names below are single quoted strings, and are not PHP variables
            unset($_COOKIE['$Version']);
            unset($_COOKIE['$Path']);
            unset($_COOKIE['$Domain']);

            foreach($_COOKIE as $key => $val)
            {
                $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
            }
        }

        // Sanitize PHP_SELF
        $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);


        // CSRF Protection check
        if ($this->_enable_csrf == TRUE)
        {
            $this->_validate_token();
//            $this->security->csrf_verify();
        }

        log_message('debug', "Global POST and COOKIE data sanitized");
    }
    
    /**
     * Validate Token
     *
     * Validates the token sent from POST
     *
     * @access    private
     * @return    void
     */
    private function _validate_token()
    {
        log_message('debug', 'My_Input::_validate_token() called');

        // We only load the library if we are actually using the token
        $this->load->library('csrf');

        // Form ID and token from the POST input
        $form_id = $this->post('form_id');
        $token = $this->post('token');

        // Validate token from POST
        if ( ! $this->csrf->validate_token($form_id, $token))
        {
            log_message('debug', 'My_Input::_validate_token() bad token');

            // Create a new token and set the error
            $this->csrf->create_token();
            $this->_error_array[] = $this->lang->line('csrf_bad_token');
        }

        // Token is fine. Save it for reuse in case other validation tests fail
        else
        {
            $this->csrf->save_token($form_id, $token);
        }
    }
}

I've basically just copied the _sanitize_globals function to change the way it handles csrf. I've been having problems with the csrf security in CI 2.0 because it fails if the form you are submitting fails validation tests and is then resubmitted. I'm trying to incorporate the way that csrf is handled in pyroCMS into the input class rather than the form_validation class which is how pyroCMS does it.
#4

[eluser]WanWizard[/eluser]
Can you please enclose the code in [ code ] tags? This is quite unreadable.

After that, change 'contruct' to 'construct', and things will work again...
#5

[eluser]musonic[/eluser]
Apologies for formatting. I've now edited. Also, thanks for pointing out the typo. However, unfortunately it hasn't solved the problem. From my log I can see that the function _validate_function() is being called and it is in this function that I try to load the library. The result is that I'm still getting an undefined property error:
Code:
Fatal error: Call to a member function library() on a non-object
#6

[eluser]musonic[/eluser]
So I've been doing more digging...
I tried loading the library using the function =& load_class() and passing it the correct parameters for it to find the file. This function is in the common.php class in the system/core folder.
Unfortunately, although that does load the library file, it brings with it another problem. Because the input class (which now includes the csrf library class) loads before the Base5 class it now can't use the function =& get_instance() because that function is part of the Base5 class.
To explain further, the csrf library class uses functions from the native CI session class. This is why we need a CI instance in the csrf library class. I can't think of a way around this problem. Hopefully someone else can!
#7

[eluser]InsiteFX[/eluser]
The library is pre-loaded buy the system!

InsiteFX
#8

[eluser]pickupman[/eluser]
You mentioned it, but it is not shown in your code where you have add the CI superobject.
Code:
class MY_Input extends CI_Input {
    
    var $CI;
    public function __contruct()
    {
        parent::__construct(); log_message('debug', "MY_Input Class Initialized");
        $this->CI =& get_instance();
    }

//Whenever using CI methods you will need to use $this->CI as $this context is only with the class you need the superobject in order use methods outside of the class like load().
// We only load the library if we are actually using the token
        $this->CI->load->library('csrf');
#9

[eluser]musonic[/eluser]
@InsiteFX - I assume you mean that the Input class is auto-loaded. That isn't the issue I'm having. I'm trying to load another library within the Input class.
@pickupman - in the example code I posted, I don't use the superobject. It is currently loaded within the csrf library I'm trying to load. I have tried to use the superobject in order to try to load the csrf library but as I tried to explain in my previous post because the Input class is loaded before the Base5 class the method get_instance() does not yet exist. This is why the code you suggest doesn't work.
#10

[eluser]pickupman[/eluser]
Applying syntax shown from the standard Input class, you should use:
Code:
$csrf =& load_class('csrf'); //May need to be load_class('Csrf');
$csrf->someMethod();


This ends up being standard PHP OOP syntax.




Theme © iAndrew 2016 - Forum software by © MyBB