PHP: Illegal string-offset

后端 未结 2 1523
一整个雨季
一整个雨季 2020-12-06 22:26

My open-source project was working just fine, until I started to work on it after 6 month of break. Updated to latest XAMPP, and start getting tons of weird errors, one of w

相关标签:
2条回答
  • 2020-12-06 23:02

    I found my answer here. Apparently, the line

    return $this->$name[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true );
    

    should be like:

    return $this->{$name}[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true );
    

    due to the precedence.

    0 讨论(0)
  • 2020-12-06 23:14

    Introduction

    I know this has been answered but Illegal string offset ERROR is not the only issue i see here. I belive they are better ways to introduce the flexibility you want and also still make elements save without all that complexity and using of $GLOBALS.

    You can start by looking at :

    • Are global variables in PHP considered bad practice? If so, why?
    • PHP global in functions
    • Why global state is the devil, and how to avoid using it

    Quick Review

    $input = new Input();                          <-- You add to initiate a class 
    $server_name = $input->server("SERVER_NAME");
          ^                  ^           ^
          |                  |           |
        variable             |           |
                         Variable        |
                                      Variable 
    

    Am not sure what stops you from just using

        $_SERVER['SERVER_NAME'] = makeSave($_SERVER['SERVER_NAME']);
                                      ^
                                      |- I guess this is what you want to introduce 
    

    Assumption - You want fexibility

    Lest assume you want flexibility and also recursion then your class call can be as flexible as :

    print_r($input->SERVER_NAME);            |
    print_r($input['SERVER_NAME']);          |----- Would Produce same result 
    print_r($input->SERVER_NAME());          |
    

    If this is the kind of flexibility you want the i would consider you combine __get , __call and ArrayAccess altogether ...

    Lets Imagine

    $var = array();
    $var["name"] = "<b>" . $_SERVER['SERVER_NAME'] . "</b>";
    $var["example"]['xss'] = '<IMG SRC=javascript:alert("XSS")>';
    $var["example"]['sql'] = "x' AND email IS NULL; --";
    $var["example"]['filter'] = "Let's meet  4:30am Ât the \tcafé\n";
    
    $_SERVER['SERVER_NAME'] = $var ; // Just for example 
    

    Now back to your format

    $makeSave = new MakeSafe(MakeSafe::SAVE_XSS | MakeSafe::SAVE_FILTER);
    $input = new Input($_SERVER, $makeSafe);
    
    //You can 
    print_r($input->SERVER_NAME);
    
    //Or
    print_r($input['SERVER_NAME']);
    
    //Or
    print_r($input->SERVER_NAME());
    

    They would all output

    Array
    (
        [0] => &lt;b&gt;localhost&lt;/b&gt;
        [1] => Array
            (
                [0] => &lt;IMG SRC=javascript:alert(&quot;XSS&quot;)&gt;
                [1] => x&#039; AND email IS NULL; --
                [2] => Let&#039;s meet  4:30am &#195;&#130;t the &#9;caf&#195;&#169;&#10;
            )
    
    )
    

    See Live DEMO

    Your INPUT class modified

    class INPUT implements \ArrayAccess {
        private $request = array();
        private $makeSafe;
    
        public function __construct(array $array, MakeSafe $makeSafe) {
            $this->request = $array;
            $this->makeSave = $makeSafe;
        }
    
        function __get($offset) {
            return $this->offsetGet($offset);
        }
    
        function __call($offset, $value) {
            return $this->offsetGet($offset);
        }
    
        public function setRequest(array $array) {
            $this->request = $array;
        }
    
        public function offsetSet($offset, $value) {
            trigger_error("Error: SUPER GLOBAL data cannot be modified");
        }
    
        public function offsetExists($offset) {
            return isset($this->request[$offset]);
        }
    
        public function offsetUnset($offset) {
            unset($this->request[$offset]);
        }
    
        public function offsetGet($offset) {
            return isset($this->request[$offset]) ? $this->makeSave->parse($this->request[$offset]) : null;
        }
    }
    

    Make your Save method a class

    class MakeSafe {
        const SAVE_XSS = 1;
        const SAVE_SQL = 2;
        const SAVE_FILTER_HIGH = 4;
        const SAVE_FILTER_LOW = 8;
        const SAVE_FILTER = 16;
    
        private $options;
    
        function __construct($options) {
            $this->options = $options;
        }
    
        function escape($value) {
            if ($value = @mysql_real_escape_string($value))
                return $value;
            $return = '';
            for($i = 0; $i < strlen($value); ++ $i) {
                $char = $value[$i];
                $ord = ord($char);
                if ($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126)
                    $return .= $char;
                else
                    $return .= '\\x' . dechex($ord);
            }
            return $return;
        }
    
        function parse($mixed) {
            if (is_string($mixed)) {
                $this->options & self::SAVE_XSS and $mixed = htmlspecialchars($mixed, ENT_QUOTES, 'UTF-8');
                $this->options & self::SAVE_SQL and $mixed = $this->escape($mixed);
                $this->options & self::SAVE_FILTER_HIGH and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH);
                $this->options & self::SAVE_FILTER_LOW and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_LOW);
                $this->options & self::SAVE_FILTER and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_LOW);
                return $mixed;
            }
    
            if (is_array($mixed)) {
                $all = array();
                foreach ( $mixed as $data ) {
                    $all[] = $this->parse($data);
                }
                return $all;
            }
            return $mixed;
    
            return $this->final;
        }
    }
    

    Conclusion

    Has i said i know this has been answered but i hope this helps someone else not to write code like yours ...

    PS : This has also fixed your PHP Warning: Illegal string offset ERROR

    0 讨论(0)
提交回复
热议问题