Seditio Source
Root |
./othercms/PHPFusion 9.10.20/includes/defender.php
<?php
/*-------------------------------------------------------+
| PHPFusion Content Management System
| Copyright (C) PHP Fusion Inc
| https://phpfusion.com/
+--------------------------------------------------------+
| Filename: defender.php
| Author: Frederick MC Chan (Chan)
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/

use Defender\Validation;

/**
 * Class Defender
 */
class Defender {
    public static
$input_errors = [];
    private static
$debug = FALSE;
    private static
$defender_instance = NULL;

    private static
$input_name = '';
    private static
$input_error_text = [];
    private static
$page_hash = '';
    public
$ref = [];

   
// Declared by Form Sanitizer
   
public $field = [];
    public
$field_name = '';
    public
$field_value = '';
    public
$field_default = '';
    public
$field_config = [
       
'type'        => '',
       
'value'       => '',
       
//'default' => '',
       
'name'        => '',
       
//'id' => '',
       
'safemode'    => '',
       
'path'        => '',
       
'thumbnail_1' => '',
       
'thumbnail_2' => '',
    ];

   
/**
     * Generates and return class instance
     * Eliminates global usage in functions
     *
     * @return null|static
     */
   
public static function getInstance() {
        if (
self::$defender_instance === NULL) {
           
self::$defender_instance = new static();
        }

        return
self::$defender_instance;
    }

   
/**
     * Serialize an array securely
     *
     * @param array $array
     *
     * @return string
     */
   
public static function serialize(array $array = []) {
       
$return_default = '';
        if (
is_array($array)) {
            return
base64_encode(serialize($array));
        }

        return
$return_default;
    }

   
/**
     * @param string|array $value
     *
     * @return string
     */
   
public static function encode($value) {
        return
base64_encode(json_encode($value));
    }

   
/**
     * @param string $value
     *
     * @return mixed
     */
   
public static function decode($value) {
        return
json_decode(base64_decode($value), TRUE);
    }

   
/**
     * Read serialized array
     *
     * @param $string string serialized string
     *
     * @return array|mixed
     */
   
public static function unserialize($string) {

       
$return_default = [];
        if (!empty(
$string)) {
           
$array = unserialize(base64_decode($string));
            if (!empty(
$array)) {
                return
$array;
            }
        }

        return
$return_default;
    }

   
/**
     * @param array $array
     */
   
public static function add_field_session(array $array) {
       
$_SESSION['form_fields'][self::pageHash()][$array['input_name']] = $array;
    }

   
/**
     * Hash a token to prevent unauthorized access
     *
     * @return string
     */
   
public static function pageHash() {
        if (!
defined('SECRET_KEY')) {
           
$chars = ['abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ', '123456789'];
           
$count = [(strlen($chars[0]) - 1), (strlen($chars[1]) - 1)];
           
$key = '';
            for (
$i = 0; $i < 32; $i++) {
               
$type = mt_rand(0, 1);
               
$key .= substr($chars[$type], mt_rand(0, $count[$type]), 1);
            }

           
define('SECRET_KEY', $key);
        }

        if (empty(
self::$page_hash)) {
           
self::$page_hash = md5(SECRET_KEY);
        }

        return
self::$page_hash;
    }

    public static function
unset_field_session() {
       
session_remove('form_fields');
    }

   
/**
     * @param array $array
     *
     * @return array
     */
   
static function sanitize_array($array) {
        foreach (
$array as $name => $value) {
           
$array[stripinput($name)] = trim(stripinput($value));
        }

        return (array)
$array;
    }

   
/**
     * ID for Session
     * No $userName because it can be changed and tampered via Edit Profile.
     * Using IP address extends for guest
     *
     * @return mixed
     */
   
public static function set_sessionUserID() {
       
$userdata = fusion_get_userdata();
        return !empty(
$userdata['user_id']) && !isset($_POST['login']) ? (int)fusion_get_userdata('user_id') : str_replace('.', '-', USER_IP);
    }

   
/**
     * Checks whether an input was marked as invalid
     *
     * @return array
     */
   
public static function getInputErrors() {
        return
self::$input_errors;
    }

   
/**
     * Set and override default field error text
     *
     * @param string $input_name
     * @param string $text
     */
   
public static function setErrorText($input_name, $text) {
       
self::$input_error_text[$input_name] = $text;
    }

   
/**
     * Fetches the latest error text of this input
     * Important! Ensure your applications do not refresh screen for this error to show.
     * Usage fusion_safe(); for conditional redirect.
     *
     * @param string $input_name
     *
     * @return null
     */
   
public static function getErrorText($input_name) {
        if (
self::inputHasError($input_name)) {
            return isset(
self::$input_error_text[$input_name]) ? self::$input_error_text[$input_name] : NULL;
        }

        return
NULL;
    }

   
/**
     * @param string $input_name
     *
     * @return bool
     */
   
public static function inputHasError($input_name) {
        if (isset(
self::$input_errors[$input_name])) {
            return
TRUE;
        }

        return
FALSE;
    }

   
/**
     * @return array
     */
   
public static function get_inputError() {
        return
self::$input_errors;
    }

   
/**
     * Generate a key
     *
     * @param string $private_key
     *
     * @return string
     */
   
public static function get_encrypt_key($private_key) {
        return
openssl_random_pseudo_bytes(32, $private_key); // 256 bits
   
}

   
/**
     * Encrypts a string securely with a private key
     *
     * @param string $string      The text to encrypt
     * @param string $private_key For better security use \Defender::get_encrypt_key to generate your private key
     *
     * Does not support array encrypt.
     *
     * @return string
     */
   
public static function encrypt_string($string, $private_key = 'phpfusion') {
       
$ivlen = openssl_cipher_iv_length($cipher = 'AES-128-CBC');
       
$iv = openssl_random_pseudo_bytes(16, $ivlen); // 128 bits
       
$string = self::pkcs7_pad($string, 16);
       
$ciphertext_raw = openssl_encrypt($string, $cipher, $private_key, OPENSSL_RAW_DATA, $iv);
       
$hmac = hash_hmac('sha256', $ciphertext_raw, $private_key, TRUE);

        return
base64_encode($iv.$hmac.$ciphertext_raw);
    }

   
/**
     * @param string $data
     * @param int    $size
     *
     * @return string
     */
   
private static function pkcs7_pad($data, $size) {
       
$length = $size - strlen($data) % $size;
        return
$data.str_repeat(chr($length), $length);
    }

   
/**
     * Decrypts a string securely with a private key
     *
     * @param string $string      The string to decrypt
     * @param string $private_key For better security use \Defender::get_encrypt_key to generate your private key
     *
     * @return null|string
     */
   
public static function decrypt_string($string, $private_key = 'phpfusion') {
       
$c = base64_decode($string);
       
$ivlen = openssl_cipher_iv_length($cipher = 'AES-128-CBC');
       
$iv = substr($c, 0, $ivlen);
       
$hmac = substr($c, $ivlen, $sha2len = 32);
       
$ciphertext_raw = substr($c, $ivlen + $sha2len);
       
$string = openssl_decrypt($ciphertext_raw, $cipher, $private_key, OPENSSL_RAW_DATA, $iv);
       
$string = self::pkcs7_unpad($string);
       
$calcmac = hash_hmac('sha256', $ciphertext_raw, $private_key, TRUE);

        if (!
function_exists('hash_equals')) {
            function
hash_equals($str1, $str2) {
                if (
strlen($str1) != strlen($str2)) {
                    return
FALSE;
                } else {
                   
$res = $str1 ^ $str2;
                   
$ret = 0;
                    for (
$i = strlen($res) - 1; $i >= 0; $i--) {
                       
$ret |= ord($res[$i]);
                    }

                    return !
$ret;
                }
            }
        }
        if (
hash_equals($hmac, $calcmac)) {//PHP 5.6+ timing attack safe comparison
           
return $string;
        }

        return
NULL;
    }

   
/**
     * @param string $data
     *
     * @return false|string
     */
   
private static function pkcs7_unpad($data) {
        return
substr($data, 0, -ord($data[strlen($data) - 1]));
    }

   
/**
     * Return the current document field session or sessions
     * Use for debug purposes
     *
     * @param string $input_name
     *
     * @return mixed
     */
   
public function get_current_field_session($input_name = '') {
        if (
$input_name && isset($_SESSION['form_fields'][self::pageHash()][$input_name])) {
           
//return $_SESSION['form_fields'][self::pageHash()][$input_name];
           
return session_get(['form_fields', self::pageHash(), $input_name]);
        } else {
            if (
$input_name) {
                return
FALSE;
            } else {
               
//return $_SESSION['form_fields'];
               
return $_SESSION['form_fields'][self::pageHash()];

                return
session_get(['form_fields', self::pageHash()]);
            }
        }
    }

   
/**
     * Request whether safe to proceed at all times
     *
     * @return bool
     */
   
public static function safe() {
        if (!
defined('FUSION_NULL')) {
            return
TRUE;
        }

        return
FALSE;
    }

   
/**
     * @param array $array
     */
   
public function addHoneypot(array $array) {
       
$_SESSION['honeypots'][self::pageHash()][$array['honeypot']] = $array;
    }

   
/**
     * @param string $honeypot
     *
     * @return string
     */
   
public function getHoneypot($honeypot = '') {
        if (
$honeypot && isset($_SESSION['honeypots'][self::pageHash()][$honeypot])) {
            return
$_SESSION['honeypots'][self::pageHash()][$honeypot];
        } else {
            if (
$honeypot) {
                return
'This form contains no honeypots';
            } else {
                return
$_SESSION['honeypots'][self::pageHash()];
            }
        }
    }

   
/**
     * @param bool|FALSE $value
     */
   
public function debug($value = FALSE) {
       
self::$debug = $value;
    }

   
/**
     * Sanitize with input name
     *
     * @param string $key
     * @param string $default
     * @param bool   $input_name
     * @param bool   $is_multiLang
     *
     * @return string
     */
   
public function sanitizer($key, $default = '', $input_name = FALSE, $is_multiLang = FALSE) {
       
$value = $this->filterPostArray($key);
        return
$this->formSanitizer($value, $default, $input_name, $is_multiLang);
    }

   
/**
     * @param mixed $key
     *
     * @return string
     */
   
public function filterPostArray($key) {
       
$flag = FILTER_FLAG_NONE;
       
$input_key = $key;
        if (
is_array($key)) {
           
// always use key 0 for filter var
           
$input_key = $key[0];
           
$flag = FILTER_REQUIRE_ARRAY;
        }

       
$filtered = post($input_key, FILTER_DEFAULT, $flag);

        if (
is_array($key)) {
           
$input_ref = $key;
            unset(
$input_ref[0]);

           
// Get the value of the filtered post value using the $key array as map
           
return array_reduce(
               
$input_ref,
                function (
$value, $key) {

                    return (!empty(
$value[$key]) ? $value[$key] : '');
                },
               
$filtered
           
);
        }

        return (string)
$filtered;
    }

   
/**
     * Sanitize
     *
     * @param string|array $value
     * @param string       $default
     * @param bool|FALSE   $input_name
     * @param bool|FALSE   $is_multiLang
     *
     * @return string
     */
   
public function formSanitizer($value, $default = '', $input_name = FALSE, $is_multiLang = FALSE) {
       
$val = [];
       
$page_hash = self::pageHash();

        if (
$input_name) {

            if (
$is_multiLang) {
               
$language = array_keys(fusion_get_enabled_languages());
                foreach (
$language as $lang) {
                   
$iname = $input_name.'['.$lang.']';

                    if (
$this->field_config = $this->get_current_field_session($input_name)) {
                       
//$this->field_config = $_SESSION['form_fields'][$page_hash][$iname];
                       
$this->field_name = $iname;
                       
$this->field_value = $value[$lang];
                       
$this->field_default = $default;
                       
$val[$lang] = $this->validate();
                    }
                }
                if (!empty(
$this->field_config['required']) && (!$value[LANGUAGE])) {

                   
fusion_stop();
                   
$iname = $input_name.'['.LANGUAGE.']';
                   
self::setInputError($iname);

                    return
$default;

                } else {
                   
$val_ = [];

                    foreach (
$val as $lang => $value) {
                       
$val_[$lang] = $value;
                    }

                    return
serialize($val_);
                }
            } else {
               
// Make sure that the input was actually defined in code. AND there must be a value to worth the processing power expense!
               
if ($this->field_config = $this->get_current_field_session($input_name)) {

                   
$this->field_config = $_SESSION['form_fields'][$page_hash][$input_name];
                   
$this->field_name = $input_name;
                   
$this->field_value = $value;
                   
$this->field_default = $default;
                   
/*
                     * These two checks won't be neccesary after we add the options in all inputs
                     * NOTE: Please don't pass 'stripinput' as callback, before we reach a callback
                     * everything is checked and sanitized already. The callback should only check
                     * if certain conditions are met then return TRUE|FALSE and not do any alterations
                     * the value itself
                     */
                   
$callback = isset($this->field_config['callback_check']) ? $this->field_config['callback_check'] : FALSE;
                   
$regex = isset($this->field_config['regex']) ? $this->field_config['regex'] : FALSE;
                   
$secured = $this->validate();

                   
// If truly FALSE the check failed
                   
if ($secured === FALSE || ($this->field_config['required'] == 1 && $secured == '') ||
                        (
$secured != '' && $regex && !preg_match('@^'.$regex.'$@i', $secured)) || // regex will fail for an imploded array, maybe move this check
                       
(is_callable($callback) && !$callback($secured))
                    ) {

                       
fusion_stop();
                       
self::setInputError($input_name);

                       
// Add regex error message.
                       
if ($secured != '' && $regex && !preg_match('@^'.$regex.'$@i', $secured)) {
                           
addnotice('danger', sprintf(fusion_get_locale('regex_error'), $this->field_config['title']));
                        }
                       
// Add a notice
                       
if (self::$debug) {
                           
addnotice('warning', '<strong>'.$input_name.':</strong>'.($this->field_config['safemode'] ? ' is in SAFEMODE and the' : '').' check failed');
                        }

                       
// Return user's input for correction
                       
return $this->field_value;
                    } else {
                        if (
self::$debug) {
                           
addnotice('info', $input_name.' = '.(is_array($secured) ? 'array' : $secured));
                        }

                        return
$secured;
                    }
                } else {
                    return
$default;
                }
            }
        } else {
            if (
$value) {
                if (!
is_array($value)) {
                    if (
intval($value)) {
                        return
stripinput($value); // numbers
                   
} else {
                        return
stripinput(trim(preg_replace('/ +/i', ' ', $value)));
                    }
                } else {
                   
$secured = [];
                    foreach (
$value as $unsecured) {
                        if ((int)
$unsecured) {
                           
$secured[] = stripinput($unsecured); // numbers
                       
} else {
                           
$secured[] = stripinput(trim(preg_replace('/ +/i', ' ', $unsecured)));
                        }
                    }

                    return
implode($this->field_config['delimiter'], $secured);
                }
            } else {
                return
$default;
            }
        }

       
//set_error(E_USER_NOTICE, "The form sanitizer could not handle the request! (input: $input_name)", "", "");
   
}

   
/**
     * @return false|string|null
     */
   
public function validate() {
       
Validation::inputName($this->field_name);
       
Validation::inputDefault($this->field_default);
       
Validation::inputValue($this->field_value);
       
Validation::inputConfig($this->field_config);

       
$locale = fusion_get_locale(LOCALE.LOCALESET.'defender.php');
       
// Are there situations were inputs could have leading
        // or trailing spaces? If not then uncomment line below
        //$this->field_value = trim($this->field_value);
        // Don't bother processing and validating empty inputs
        //if ($this->field_value == '') return $this->field_value;
        /**
         * Keep this included in the constructor
         * This solution was needed to load the defender.php.php before
         * defining LOCALESET
         */
        // declare the validation rules and assign them
        // type of fields vs type of validator

        // execute sanitisation rules at point-blank precision using switch
       
try {
            if (!empty(
$this->field_config['type'])) {

                if (empty(
$this->field_value) && ($this->field_config['type'] !== 'number')) {
                    return
$this->field_default;
                }

                return
Validation::getValidated();

            } else {
               
self::stop();
               
addnotice('danger', sprintf($locale['df_406'], self::$input_name));
            }
        } catch (
Exception $e) {
           
self::stop();
           
addnotice('danger', $e->getMessage());
        }

        return
NULL;
    }

   
/**
     * Sends a system error declaration.
     *
     * @param string $notice
     *
     * @return null
     */
   
public static function stop($notice = '') {
       
//debug_print_backtrace();
       
if (!defined('FUSION_NULL')) {
           
define('FUSION_NULL', TRUE);
            if (
$notice) {
               
addnotice('danger', $notice);
               
define('STOP_REDIRECT', TRUE);
            }
           
//addNotice('danger', '<strong>'.fusion_get_locale('error_request', LOCALE.LOCALESET.'defender.php').'</strong>');
       
}
        return
NULL;
    }

   
/**
     * @param string $input_name
     */
   
public static function setInputError($input_name) {
       
self::$input_errors[$input_name] = TRUE;
    }

   
/**
     * @param string $key
     * @param string $default
     * @param false  $input_name
     *
     * @return array
     */
   
public function fileSanitizer($key, $default = '', $input_name = FALSE) {
       
$upload = (array)$this->formSanitizer($_FILES[$key], $default, $input_name);
        if (isset(
$upload['error']) && $upload['error'] == 0) {
            return
$upload;
        }

        return [];
    }

}

/**
 * Verify and Sanitize Inputs
 *
 * @param string $value
 * @param string $default
 * @param bool   $input_name
 * @param bool   $is_multiLang
 *
 * @return string|array
 */
function form_sanitizer($value, $default = '', $input_name = FALSE, $is_multiLang = FALSE) {
    return
Defender::getInstance()->formSanitizer($value, $default, $input_name, $is_multiLang);
}

/**
 * Verify and Sanitize Inputs with input_name
 * A more secured method
 *
 * @param mixed  $value input_name
 * @param string $default
 * @param bool   $input_name
 * @param bool   $is_multiLang
 *
 * @return string
 */
function sanitizer($value, $default = '', $input_name = FALSE, $is_multiLang = FALSE) {
    return
Defender::getInstance()->sanitizer($value, $default, $input_name, $is_multiLang);
}

/**
 * Sanitizes an array
 *
 * @param array $array
 *
 * @return array
 */
function sanitize_array($array = []) {
    return
Defender::sanitize_array($array);
}

/**
 * File sanitize by input_name
 *
 * @param string $value input_name
 * @param string $default
 * @param bool   $input_name
 *
 * @return array
 */
function file_sanitizer($value, $default = '', $input_name = FALSE) {
    return
Defender::getInstance()->fileSanitizer($value, $default, $input_name);
}

/**
 * Isset GET
 *
 * @param $key
 *
 * @return bool
 */
function check_get($key) {
    if (
is_array($key)) {
        return !empty(
array_reduce($key, function ($carry, $item) {
            return (!empty(
$carry[$item]) ? $carry[$item] : '');
        },
$_GET));
    }
    return isset(
$_GET[$key]);
}

/**
 * Isset POST
 *
 * @param $key
 *
 * @return bool
 */
function check_post($key) {
    if (
is_array($key)) {
        return !empty(
array_reduce($key, function ($carry, $item) {
            return (!empty(
$carry[$item]) ? $carry[$item] : '');
        },
$_POST));
    }
    return isset(
$_POST[$key]);
}

/**
 * @param mixed $key
 * @param int   $type
 * @param mixed $flags
 *
 * @return mixed
 */
function get($key = NULL, $type = FILTER_DEFAULT, $flags = FILTER_FLAG_NONE) {

    if (
is_array($key)) {
       
// always use key 0 for filter var
       
$input_key = $key[0];
       
$flag = FILTER_REQUIRE_ARRAY;

       
$filtered = get($input_key, FILTER_DEFAULT, $flag);


       
$input_ref = $key;
        unset(
$input_ref[0]);

       
// Get the value of the filtered post value using the $key array as map
       
return array_reduce(
           
$input_ref,
            function (
$value, $key) {

                return (!empty(
$value[$key]) ? $value[$key] : '');
            },
           
$filtered
       
);


        return (string)
stripinput($filtered);
    }

    if (
$flags == FILTER_VALIDATE_INT) {

        if (isset(
$_GET[$key]) && isnum($_GET[$key]) && ($_GET[$key] > PHP_INT_MAX)) {
            return (int)
$_GET[$key];
        }

        return
0;
    }

    if (
filter_has_var(INPUT_GET, $key)) {
       
$filtered_input = filter_input(INPUT_GET, $key, $type, $flags);
    } else {
       
$filtered_input = isset($_GET[$key]) ? filter_var($_GET[$key], $type, $flags) : NULL;
    }

    return
stripinput($filtered_input);
}

/**
 * Sanitizes $_POST by name
 *
 * @param mixed $key input_name
 * @param int   $type
 * @param mixed $flags
 *
 * @return mixed
 */
function post($key, $type = FILTER_DEFAULT, $flags = FILTER_FLAG_NONE) {
    if (
is_array($key)) {
       
// always use key 0 for filter var
       
$post_key = $key[0];
       
$flag = FILTER_REQUIRE_ARRAY;
       
$filtered = post($post_key, FILTER_DEFAULT, $flag);
       
$input_ref = $key;
        unset(
$input_ref[0]);

       
// Get the value of the filtered post value using the $key array as map
       
return array_reduce(
           
$input_ref,
            function (
$value, $key) {

                return (!empty(
$value[$key]) ? $value[$key] : '');
            },
           
$filtered
       
);


        return (string)
stripinput($filtered);
    }

    if (
$flags == FILTER_VALIDATE_INT) {

        if (isset(
$_POST[$key]) && isnum($_POST[$key]) && ($_POST[$key] > PHP_INT_MAX)) {

            return (int)
$_POST[$key];
        }
    }

    if (
filter_has_var(INPUT_POST, $key)) {
        return
filter_input(INPUT_POST, $key, $type, $flags);
    } else {
        return isset(
$_POST[$key]) ? filter_var($_POST[$key], $type, $flags) : NULL;
    }
}

/**
 * Sanitizes input
 *
 * @param mixed $key
 *
 * @return array
 */
function post_array($key) {
    return (array)
Defender::getInstance()->filterPostArray($key);
}

/**
 * Gets server array
 *
 * @param string $key
 * @param int    $type
 *
 * @return mixed
 */
function server($key, $type = FILTER_DEFAULT) {
    if (
filter_has_var(INPUT_SERVER, $key)) {
        return
filter_input(INPUT_SERVER, $key, $type);
    } else {
        return isset(
$_SERVER[$key]) ? filter_var($_SERVER[$key], $type) : NULL;
    }
}

/**
 * Checks if a file is uploaded during upload post event
 *
 * @param mixed $key input name
 *
 * @return bool
 */
function file_uploaded($key) {
    if (!empty(
$_FILES)) {
        if (
is_array($key)) {
           
$files =& $_FILES;
            foreach (
$key as $pkey) {
               
$files =& $files[$pkey];
            }

            return
is_uploaded_file($files['tmp_name']);
        }

        return
is_uploaded_file($_FILES[$key]['tmp_name']);
    }

    return
FALSE;
}

/**
 * @param string $key
 * @param int    $type
 *
 * @return mixed
 */
function environment($key, $type = FILTER_DEFAULT) {
    if (
filter_has_var(INPUT_ENV, $key)) {
        return
filter_input(INPUT_ENV, $key, $type);
    } else {
        return isset(
$_ENV[$key]) ? filter_var($_ENV[$key], $type) : NULL;
    }
}

/***
 * Sets a $_COOKIE
 *
 * @param string $key
 * @param int    $type
 *
 * @return string|string[]
 */
function cookie($key, $type = FILTER_DEFAULT) {
    if (
filter_has_var(INPUT_COOKIE, $key)) {
       
$filtered_input = filter_input(INPUT_COOKIE, $key, $type);
    } else {
       
$filtered_input = (isset($_COOKIE[$key]) ? filter_var($_COOKIE[$key], $type) : NULL);
    }

    return
stripinput($filtered_input);
}

/**
 * Remove a $_COOKIE
 *
 * @param string $key
 *
 * @return array
 */
function cookie_remove($key) {
    unset(
$_COOKIE[$key]);
    return
$_COOKIE;
}

/**
 * Cleans curent $_SESSION
 */
function session_clean() {
   
$_SESSION = [];
}

/**
 * Add a value to $_SESSION
 *
 * @param string $key
 * @param mixed  $value
 *
 * @return mixed
 */
function session_add($key, $value) {
   
//global $_SESSION;
   
if (is_array($key)) {
       
//  print_p($_SESSION);
       
$session =& $_SESSION;
        foreach (
$key as $pkey) {
           
$session =& $session[$pkey];
        }
       
$session = $value;

        return
$session;
    }

    return
$_SESSION[$key] = $value;
}

/**
 * Get session
 *
 * @param string|array $key
 *
 * @return mixed
 */
function session_get($key) {
    if (
is_array($key)) {
       
$session =& $_SESSION;
        foreach (
$key as $i) {
           
$session =& $session[$i];
        }

        return
$session;
    }

    return (isset(
$_SESSION[$key]) ? $_SESSION[$key] : NULL);
}

/**
 * @param string $key
 *
 * @return mixed
 */
function session_remove($key) {
    if (
is_array($key)) {
       
$temp = &$_SESSION;
       
$counter = 1;
        foreach (
$key as $nkey) {
            if (
$counter == count($key)) {
                unset(
$temp[$nkey]);
            }
           
$temp = &$temp[$nkey];
           
$counter++;
        }

        return
$temp;
    }

    unset(
$_SESSION[$key]);

    return
$_SESSION;
}

/**
 * Converts an array/string to string
 *
 * @param string|array $value
 *
 * @return string
 */
function fusion_encode($value) {
    return
Defender::encode($value);
}

/**
 * Converts string to array/string
 *
 * @param string $value
 *
 * @return mixed
 */
function fusion_decode($value) {
    return
Defender::decode($value);
}

/**
 * Checks if fusion is safe to proceed next step
 *
 * @return bool
 */
function fusion_safe() {
    return
Defender::getInstance()->safe();
}

/**
 * Declares FUSION_NULL constants to safeguard sensitive code execution.
 *
 * @param string $error_message The notification text. If present, will show a notice on page load.
 *
 * @return null
 */
function fusion_stop($error_message = "") {
    return
Defender::getInstance()->stop($error_message);
}

/**
 * Decrypt a string
 *
 * @param string $value
 * @param string $password
 *
 * @return null|string
 */
function fusion_decrypt($value, $password) {
    return
Defender::decrypt_string($value, $password);
}

/**
 * Encrypts a string
 *
 * @param string $value
 * @param string $password
 *
 * @return string
 */
function fusion_encrypt($value, $password) {
    return
Defender::encrypt_string($value, $password);
}

/**
 * Fetches field configurations
 *
 * @param $field_name
 *
 * @return array|false|mixed|null
 */
function get_fusion_field_config($field_name) {
    return
Defender::getInstance()->get_current_field_session($field_name);
}

/**
 * Sets field configurations
 *
 * @param $field_config
 */
function set_fusion_field_config($field_config) {
   
Defender::add_field_session($field_config);
}

require_once
__DIR__.'/defender/validation.php';
require_once
__DIR__.'/defender/token.php';
require_once
__DIR__.'/defender/mimecheck.php';