View file incfiles/classes/core.php

File size: 18.77Kb
<?php

/*
////////////////////////////////////////////////////////////////////////////////
// JohnCMS                Mobile Content Management System                    //
// Project site:          http://johncms.com                                  //
// Support site:          http://gazenwagen.com                               //
////////////////////////////////////////////////////////////////////////////////
// Lead Developer:        Oleg Kasyanov   (AlkatraZ)  [email protected] //
// Development Team:      Eugene Ryabinin (john77)    [email protected]   //
//                        Dmitry Liseenko (FlySelf)   [email protected]     //
////////////////////////////////////////////////////////////////////////////////
*/

defined('_IN_JOHNCMS') or die('Restricted access');
class core {
    // Системные переменные
    public $system_build;                  // Версия системы
    public $ip;                            // IP адрес в LONG формате
    public $user_agent = 'Not Recognised'; // User Agent (Browser)
    public $system_settings = array ();    // Системные настройки
    public $system_time;                   // Системное время
    public $language_id;                   // Идентификатор языка
    public $language_iso;                  // Двухбуквенный ISO код языка
    public $language_phrases = array ();   // Массив с фразами выбранного языка
    public $regban = false;                // Запрет регистрации пользователей

    // Пользовательские переменные
    public $user_id = false;          // Идентификатор пользователя
    public $user_rights = 0;          // Права доступа
    public $user_data = array ();     // Все данные пользователя
    public $user_settings = array (); // Пользовательские настройки
    public $user_ban = array ();      // Бан

    // Параметры проверки на HTTP флуд
    private $flood_chk = 1;          // Включение - выключение функции IP антифлуда
    private $flood_interval = '120'; // Интервал времени в секундах
    private $flood_limit = '40';     // Число разрешенных запросов за интервал

    /*
    -----------------------------------------------------------------
    Конструктор класса, выполняем основную последовательность
    -----------------------------------------------------------------
    */
    function __construct() {
        // Получаем реальный адрес IP
        $this->ip = ip2long($this->ip_get());

        // Проверка адреса IP на флуд
        if ($this->flood_chk) {
            if ($this->ip_reqcount() > $this->flood_limit)
                die('Flood!!!');
        }

        // Удаляем слэши
        if (get_magic_quotes_gpc())
            $this->del_slashes();

        // Получаем User Agent
        $this->user_agent = $this->ua_get();
        
        // Стартуем сессию
        session_name('SESID');
        session_start();

        // Соединяемся с базой данных
        $this->db_connect();

        // Получаем системные настройки
        $this->system_settings();

        // Автоочистка системы
        $this->autoclean();

        // Авторизация пользователей
        $this->user_authorize();

        // Загружаем язык системы
        $this->language_phrases = $this->load_lng();
    }

    /*
    -----------------------------------------------------------------
    Подключаемся к базе данных
    -----------------------------------------------------------------
    */
    private function db_connect() {
        global $rootpath;
        require($rootpath . 'incfiles/db.php');
        $connect = @mysql_connect($db_host, $db_user, $db_pass) or die('Error: cannot connect to DB server');
        @mysql_select_db($db_name) or die('Error: cannot select DB');
        @mysql_query("SET NAMES 'utf8'", $connect);
        $this->system_build = isset($system_build) ? $system_build : false;
    }

    /*
    -----------------------------------------------------------------
    Получаем реальный адрес IP
    -----------------------------------------------------------------
    */
    private function ip_get() {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $this->ip_valid($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }  elseif ($_SERVER['REMOTE_ADDR']) {
            return $_SERVER['REMOTE_ADDR'];
        } else {
            die('Unknown IP');
        }
    }

    /*
    -----------------------------------------------------------------
    Получаем User Agent
    -----------------------------------------------------------------
    */
    private function ua_get(){
        return htmlentities(substr($_SERVER['HTTP_USER_AGENT'], 0, 150), ENT_QUOTES);
    }

    /*
    -----------------------------------------------------------------
    Счетчик числа обращений с заданного IP
    -----------------------------------------------------------------
    */
    private function ip_reqcount() {
        global $rootpath;
        $tmp = array ();
        $requests = 1;

        if (!file_exists($rootpath . 'files/cache/http_antiflood.dat'))
            $in = fopen($rootpath . 'files/cache/http_antiflood.dat', "w+");
        else
            $in = fopen($rootpath . 'files/cache/http_antiflood.dat', "r+");
        flock($in, LOCK_EX) or die("Cannot flock ANTIFLOOD file.");
        $now = time();

        while ($block = fread($in, 8)) {
            $arr = unpack("Lip/Ltime", $block);
            if (($now - $arr['time']) > $this->flood_interval) {
                continue;
            }
            if ($arr['ip'] == $this->ip) {
                $requests++;
            }
            $tmp[] = $arr;
        }
        fseek($in, 0);
        ftruncate($in, 0);

        for ($i = 0; $i < count($tmp); $i++) {
            fwrite($in, pack('LL', $tmp[$i]['ip'], $tmp[$i]['time']));
        }
        fwrite($in, pack('LL', $this->ip, $now));
        fclose($in);
        return $requests;
    }

    /*
    -----------------------------------------------------------------
    Валидация IP адреса
    -----------------------------------------------------------------
    */
    public function ip_valid($ip = '') {
        if (empty($ip))
            return false;
        $d = explode('.', $ip);

        for ($x = 0; $x < 4; $x++)
            if (!is_numeric($d[$x]) || ($d[$x] < 0) || ($d[$x] > 255))
                return false;

        return $ip;
    }

    /*
    -----------------------------------------------------------------
    Удаляем слэши из глобальных переменных
    -----------------------------------------------------------------
    */
    private function del_slashes() {
        $in = array (
            &$_GET,
            &$_POST,
            &$_COOKIE
        );

        while (list($k, $v) = each($in)) {
            foreach ($v as $key => $val) {
                if (!is_array($val)) {
                    $in[$k][$key] = stripslashes($val);
                    continue;
                }
                $in[] = &$in[$k][$key];
            }
        }
        unset($in);

        if (!empty($_FILES)) {
            foreach ($_FILES as $k => $v) {
                $_FILES[$k]['name'] = stripslashes((string)$v['name']);
            }
        }
    }

    /*
    -----------------------------------------------------------------
    Проверяем адрес IP на Бан
    -----------------------------------------------------------------
    */
    function ip_ban() {
        $req = mysql_query("SELECT `ban_type`, `link` FROM `cms_ban_ip` WHERE '" . $this->ip . "' BETWEEN `ip1` AND `ip2` LIMIT 1") or die('Error: table "cms_ban_ip"');

        if (mysql_num_rows($req)) {
            $res = mysql_fetch_array($req);
            switch ($res['ban_type']) {
                case 2:
                    if (!empty($res['link']))
                        header('Location: ' . $res['link']);
                    else
                        header('Location: http://johncms.com');
                    exit;
                    break;

                case 3:
                    $this->regban = true;
                    break;
                    default :
                    header("HTTP/1.0 404 Not Found");
                    exit;
            }
        }
    }

    /*
    -----------------------------------------------------------------
    Загружаем язык системы
    -----------------------------------------------------------------
    */
    public function load_lng($module = 'main') {
        $req = mysql_query("SELECT * FROM `cms_lng_phrases` WHERE `language_id` = '" . $this->language_id . "' AND `module` = '$module'");

        if (mysql_num_rows($req)) {
            $out = array ();
            while ($res = mysql_fetch_assoc($req)) {
                if (!empty($res['custom'])) {
                    $out[$res['keyword']] = $res['custom'];
                } else {
                    $out[$res['keyword']] = $res['default'];
                }
            }
            return $out;
        } else {
            return false;
        }
    }

    /*
    -----------------------------------------------------------------
    Получаем системные настройки
    -----------------------------------------------------------------
    */
    private function system_settings() {
        $req = mysql_query("SELECT * FROM `cms_settings`");
        while ($res = mysql_fetch_row($req)) {
            $out[$res[0]] = $res[1];
        }
        $this->language_id = $out['lng_id'];
        $this->language_iso = $out['lng_iso'];
        $this->system_time = time() + $out['timeshift'] * 3600;
        $this->system_settings = $out;
    }

    /*
    -----------------------------------------------------------------
    Авторизация пользователя и получение его данных из базы
    -----------------------------------------------------------------
    */
    private function user_authorize() {
        $user_id = false;
        $user_ps = false;

        if (isset($_SESSION['uid']) && isset($_SESSION['ups'])) {
            // Авторизация по сессии
            $user_id = abs(intval($_SESSION['uid']));
            $user_ps = $_SESSION['ups'];
        } elseif (isset($_COOKIE['cuid']) && isset($_COOKIE['cups'])) {
            // Авторизация по COOKIE
            $user_id = abs(intval(base64_decode(trim($_COOKIE['cuid']))));
            $_SESSION['uid'] = $user_id;
            $user_ps = md5(trim($_COOKIE['cups']));
            $_SESSION['ups'] = $user_ps;
        }

        if ($user_id && $user_ps) {
            $req = mysql_query("SELECT * FROM `users` WHERE `id` = '$user_id'");
            if (mysql_num_rows($req)) {
                $this->user_data = mysql_fetch_assoc($req);
                if ($user_ps === $this->user_data['password']) {
                    // Если авторизация прошла успешно
                    $this->user_id = $this->user_data['id'];         // ID пользователя
                    $this->user_rights = $this->user_data['rights']; // Права доступа
                    $this->user_settings = $this->user_settings();   // Пользовательские настройки
                    $this->user_ip();                                // Обработка истории IP адресов
                    $this->user_ban_check();                         // Проверка на Бан
                    if (!empty($this->user_data['set_language']))    // Язык
                        $this->language_id = $this->user_data['set_language'];
                } else {
                    // Если авторизация не прошла
                    $this->user_unset();
                }
            } else {
                // Если пользователь не существует
                $this->user_unset();
            }
        } else {
            // Для неавторизованных, загружаем настройки по-умолчанию
            $this->user_settings = $this->user_setings_default();
        }
    }

    /*
    -----------------------------------------------------------------
    Проверка пользователя на Бан
    -----------------------------------------------------------------
    */
    private function user_ban_check() {
        $req = mysql_query("SELECT * FROM `cms_ban_users` WHERE `user_id` = '" . $this->user_id . "' AND `ban_time` > '" . $this->system_time . "'");

        if (mysql_num_rows($req)) {
            $this->user_rights = 0;
            while ($res = mysql_fetch_row($req)) {
                $this->user_ban[$res[4]] = 1;
            }
        }
    }

    /*
    -----------------------------------------------------------------
    Фиксация истории IP адресов пользователя
    -----------------------------------------------------------------
    */
    private function user_ip() {
        if ($this->user_data['ip'] != $this->ip) {
            // Удаляем из истории текущий адрес (если есть)
            mysql_query("DELETE FROM `cms_users_iphistory` WHERE `user_id` = '" . $this->user_id . "' AND `ip` = '" . $this->ip . "' LIMIT 1");
            if (!empty($this->user_data['ip']) && $this->ip_valid(long2ip($this->user_data['ip']))) {
                // Вставляем в историю предыдущий адрес IP
                mysql_query("INSERT INTO `cms_users_iphistory` SET
                    `user_id` = '" . $this->user_id . "',
                    `ip` = '" . $this->user_data['ip'] . "',
                    `time` = '" . $this->user_data['lastdate'] . "'
                ");
            }
            // Обновляем текущий адрес в таблице `users`
            mysql_query("UPDATE `users` SET `ip` = '" . $this->ip . "' WHERE `id` = '" . $this->user_id . "'");
        }
    }

    /*
    -----------------------------------------------------------------
    Получение пользовательских настроек
    -----------------------------------------------------------------
    */
    private function user_settings() {
        if (!empty($this->user_data['set_user'])) {
            return unserialize($this->user_data['set_user']);
        } else {
            return $this->user_setings_default();
        }
    }

    /*
    -----------------------------------------------------------------
    Пользовательские настройки по умолчанию
    -----------------------------------------------------------------
    */
    private function user_setings_default() {
        $settings = array (
            'avatar' => 1,                               // Показывать аватары
            'digest' => 0,                               // Показывать Дайджест
            'field_h' => 3,                              // Высота текстового поля ввода
            'field_w' => 20,                             // Ширина текстового поля ввода
            'gzip' => 1,                                 // Отображать коэффициент сжатия
            'kmess' => 10,                               // Число сообщений на страницу
            'movings' => 1,                              // Отображать число перемещений по сайту
            'online' => 1,                               // Время, проведенное Онлайн
            'quick_go' => 1,                             // Быстрый переход
            'sdvig' => 0,                                // Временной сдвиг
            'skin' => $this->system_settings['skindef'], // Тема оформления
            'smileys' => 1,                              // Включить(1) выключить(0) смайлы
            'translit' => 0                              // Транслит
        );

        return $settings;
    }

    /*
    -----------------------------------------------------------------
    Уничтожаем данные авторизации юзера
    -----------------------------------------------------------------
    */
    private function user_unset() {
        $this->user_id = false;
        $this->user_rights = 0;
        $this->user_settings = $this->user_setings_default();
        $this->user_data = array ();
        unset($_SESSION['uid']);
        unset($_SESSION['ups']);
        setcookie('cuid', '');
        setcookie('cups', '');
    }

    /*
    -----------------------------------------------------------------
    Автоочистка системы
    -----------------------------------------------------------------
    */
    private function autoclean() {
        if (!isset($this->system_settings['clean_time']))
            mysql_query("INSERT INTO `cms_settings` SET `key` = 'clean_time', `val` = '0'");

        if ($this->system_settings['clean_time'] < $this->system_time - 86400) {
            // Очищаем таблицу статистики гостей (удаляем записи старше 1 дня)
            mysql_query("DELETE FROM `cms_guests` WHERE `time` < '" . ($this->system_time - 86400) . "'");
            mysql_query("OPTIMIZE TABLE `cms_guests`");
            // Очищаем таблицу истории IP адресов (удаляем записи старше 1 месяца)
            mysql_query("DELETE FROM `cms_users_iphistory` WHERE `time` < '" . ($this->system_time - 2592000) . "'");
            mysql_query("OPTIMIZE TABLE `cms_users_iphistory`");
            // Обновляем метку времени
            mysql_query("UPDATE `cms_settings` SET  `val` = '" . $this->system_time . "' WHERE `key` = 'clean_time' LIMIT 1");
        }
    }
}
?>