diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..48253f3 --- /dev/null +++ b/.htaccess @@ -0,0 +1,53 @@ +AddDefaultCharset utf-8 + +RewriteBase / +Options -Indexes +FollowSymLinks +MultiViews + +RewriteEngine on +RewriteBase /acp/ +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !=/favicon.ico +RewriteRule ^acp /acp/index.php [L] + +RewriteBase / +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !=/favicon.ico +RewriteRule ^(?!acp).* index.php [L] + +ErrorDocument 403 /403.html +ErrorDocument 404 /404.html + +#***Раскодировать, если не загружаются большие файлы: +php_value max_execution_time 500 +php_value max_input_time 500 +php_value upload_max_filesize 30M +php_value post_max_size 30M + +#***Раскодировать, если белый экран: +#php_flag short_open_tag = On + +php_flag display_startup_errors on +php_flag display_errors on +php_flag html_errors on + + + + ExpiresActive On + #кэшировать флэш и изображения на одну неделю + ExpiresByType image/x-icon "access plus 7 days" + ExpiresByType image/jpeg "access plus 7 days" + ExpiresByType image/png "access plus 7 days" + ExpiresByType image/gif "access plus 7 days" + ExpiresByType application/x-shockwave-flash "access plus 7 days" + #кэшировать css, javascript и текстовые файлы на одну неделю + ExpiresByType text/css "access plus 7 days" + ExpiresByType text/javascript "access plus 7 days" + ExpiresByType application/javascript "access plus 7 days" + ExpiresByType application/x-javascript "access plus 7 days" + #кэшировать html и htm файлы на один день + ExpiresByType text/html "access plus 1 day" + #кэшировать xml файлы на десять минут + ExpiresByType application/xhtml+xml "access plus 10 minutes" + \ No newline at end of file diff --git a/403.html b/403.html new file mode 100644 index 0000000..307f27e --- /dev/null +++ b/403.html @@ -0,0 +1,58 @@ + + + + + Доступ запрещен + + + + + + + + +
+
+ У вас нет прав для просмотра данной страницы + Ошибка 403 Вы можете посетить другие страницы хостинга +
+ +
+ + \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..8505d19 --- /dev/null +++ b/404.html @@ -0,0 +1,59 @@ + + + + + Страница не найдена + + + + + + + + + +
+
+ К сожалению, страница не найдена + Ошибка 404 Вы можете посетить другие страницы хостинга +
+ +
+ + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..deb09b8 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# enginegp +EngineGP diff --git a/acp/index.php b/acp/index.php new file mode 100644 index 0000000..3a0ff36 --- /dev/null +++ b/acp/index.php @@ -0,0 +1,45 @@ +connect('127.0.0.1', 11211) or exit('Ошибка: #mc0, обновите страницу позже, если ошибка повторяется, обратитесь в тех.поддержку: EGPv3'); + + // Настройки + include(DATA.'config.php'); + include(DATA.'mysql.php'); + include(DATA.'params.php'); + include(DATA.'acpengine.php'); + + // Библиотеки + include(LIB.'sql.php'); + include(LIB.'html.php'); + include(LIB.'acpsystem.php'); + + $uip = sys::ip(); + + // Распределитель + include(ACP.'distributor.php'); + + // Выхлоп + echo $html->arr['all']; +?> \ No newline at end of file diff --git a/cron.php b/cron.php new file mode 100644 index 0000000..31efc7b --- /dev/null +++ b/cron.php @@ -0,0 +1,43 @@ +connect('127.0.0.1', 11211) OR exit('Ошибка: не удалось создать связь с Memcache.'.PHP_EOL); + + // Настройки + include(DATA.'config.php'); + + /*if($argv[1] != $cfg['cron_key']) + exit('error key.'.PHP_EOL); +*/ + $task = $argv[2]; + + include(DATA.'engine.php'); + include(DATA.'mysql.php'); + include(DATA.'params.php'); + + // Библиотеки + include(LIB.'sql.php'); + include(LIB.'html.php'); + include(LIB.'system.php'); + include(LIB.'cron.php'); +?> \ No newline at end of file diff --git a/enginegp.sql b/enginegp.sql new file mode 100644 index 0000000..5dfbdc5 --- /dev/null +++ b/enginegp.sql @@ -0,0 +1,2195 @@ +-- phpMyAdmin SQL Dump +-- version 4.6.6deb4 +-- https://www.phpmyadmin.net/ +-- +-- Хост: localhost:3306 +-- Время создания: Июн 28 2020 г., 16:19 +-- Версия сервера: 5.7.30 +-- Версия PHP: 5.6.40-29+0~20200514.35+debian9~1.gbpcc49a4 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- База данных: `enginegp` +-- + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `address` +-- + +CREATE TABLE `address` ( + `id` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `ip` char(16) NOT NULL, + `price` int(11) NOT NULL, + `buy` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `address_buy` +-- + +CREATE TABLE `address_buy` ( + `id` int(11) NOT NULL, + `aid` int(11) NOT NULL, + `server` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_crmp` +-- + +CREATE TABLE `admins_crmp` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_cs` +-- + +CREATE TABLE `admins_cs` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `type` char(3) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_csgo` +-- + +CREATE TABLE `admins_csgo` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_css` +-- + +CREATE TABLE `admins_css` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_cssold` +-- + +CREATE TABLE `admins_cssold` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_mc` +-- + +CREATE TABLE `admins_mc` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_mta` +-- + +CREATE TABLE `admins_mta` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `admins_samp` +-- + +CREATE TABLE `admins_samp` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `api` +-- + +CREATE TABLE `api` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `key` varchar(32) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `auth` +-- + +CREATE TABLE `auth` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `ip` char(15) NOT NULL, + `date` int(11) NOT NULL, + `browser` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `boost` +-- + +CREATE TABLE `boost` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `server` int(11) NOT NULL, + `site` varchar(20) NOT NULL, + `circles` int(11) NOT NULL, + `money` float NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `boost_rating` +-- + +CREATE TABLE `boost_rating` ( + `id` int(11) NOT NULL, + `boost` varchar(15) NOT NULL, + `rating` int(11) NOT NULL, + `user` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `cashback` +-- + +CREATE TABLE `cashback` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `purse` varchar(13) NOT NULL, + `money` float NOT NULL, + `date` int(11) NOT NULL, + `status` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `chat` +-- + +CREATE TABLE `chat` ( + `id` int(11) NOT NULL, + `userid` int(11) NOT NULL, + `date` datetime NOT NULL, + `msg` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control` +-- + +CREATE TABLE `control` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `address` varchar(15) NOT NULL, + `passwd` varchar(32) NOT NULL, + `sql_login` char(20) NOT NULL DEFAULT 'root', + `sql_passwd` char(32) NOT NULL DEFAULT '', + `sql_port` int(11) NOT NULL DEFAULT '3306', + `sql_ftp` char(20) NOT NULL DEFAULT 'ftp', + `time` int(11) NOT NULL, + `overdue` int(11) NOT NULL DEFAULT '0', + `block` int(11) NOT NULL DEFAULT '0', + `date` int(11) NOT NULL, + `status` varchar(10) NOT NULL DEFAULT '', + `install` tinyint(1) NOT NULL DEFAULT '0', + `fcpu` tinyint(1) NOT NULL DEFAULT '0', + `limit` int(11) NOT NULL, + `price` float NOT NULL DEFAULT '0', + `ram` int(11) NOT NULL DEFAULT '0', + `hdd` int(11) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_admins_cs` +-- + +CREATE TABLE `control_admins_cs` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `type` char(3) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_admins_csgo` +-- + +CREATE TABLE `control_admins_csgo` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_admins_css` +-- + +CREATE TABLE `control_admins_css` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_admins_cssold` +-- + +CREATE TABLE `control_admins_cssold` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL, + `value` varchar(50) NOT NULL, + `passwd` char(32) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL, + `time` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `info` varchar(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_boost` +-- + +CREATE TABLE `control_boost` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `server` int(11) NOT NULL, + `site` varchar(20) NOT NULL, + `circles` int(11) NOT NULL, + `money` float NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_copy` +-- + +CREATE TABLE `control_copy` ( + `id` int(11) NOT NULL, + `user` text, + `game` char(6) NOT NULL, + `server` int(11) NOT NULL, + `pack` varchar(100) NOT NULL, + `name` char(32) NOT NULL, + `info` varchar(100) NOT NULL, + `plugins` text NOT NULL, + `date` int(11) NOT NULL, + `status` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_crontab` +-- + +CREATE TABLE `control_crontab` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `task` char(7) NOT NULL DEFAULT '', + `cron` text, + `week` text, + `time` char(20) NOT NULL DEFAULT '', + `commands` text +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_firewall` +-- + +CREATE TABLE `control_firewall` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `sip` char(20) NOT NULL, + `dest` char(27) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_plugins_buy` +-- + +CREATE TABLE `control_plugins_buy` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `key` varchar(32) NOT NULL, + `server` int(11) NOT NULL, + `price` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_plugins_install` +-- + +CREATE TABLE `control_plugins_install` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `upd` int(11) NOT NULL DEFAULT '0', + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `control_servers` +-- + +CREATE TABLE `control_servers` ( + `id` int(11) NOT NULL, + `uid` int(11) NOT NULL DEFAULT '0', + `unit` int(11) NOT NULL, + `address` char(21) NOT NULL, + `game` char(6) NOT NULL, + `slots` int(11) NOT NULL, + `online` int(11) NOT NULL DEFAULT '0', + `players` text, + `status` char(10) NOT NULL, + `name` varchar(100) NOT NULL DEFAULT 'Новый сервер', + `pack` varchar(10) NOT NULL DEFAULT '', + `fps` int(11) NOT NULL DEFAULT '0', + `tickrate` int(11) NOT NULL DEFAULT '0', + `map` varchar(100) NOT NULL DEFAULT '', + `map_start` varchar(100) NOT NULL DEFAULT '', + `time_start` int(11) NOT NULL DEFAULT '0', + `ram_use` int(11) NOT NULL DEFAULT '0', + `cpu_use` int(11) NOT NULL DEFAULT '0', + `hdd_use` int(11) NOT NULL DEFAULT '0', + `core_use` int(11) NOT NULL DEFAULT '0', + `autorestart` int(11) NOT NULL DEFAULT '0', + `pingboost` int(11) NOT NULL DEFAULT '0', + `vac` int(11) NOT NULL DEFAULT '1', + `fastdl` int(11) NOT NULL DEFAULT '0', + `core_fix` int(11) NOT NULL DEFAULT '0', + `stop` tinyint(1) NOT NULL DEFAULT '0', + `ftp` int(11) NOT NULL DEFAULT '0', + `ftp_passwd` char(20) NOT NULL DEFAULT '' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `copy` +-- + +CREATE TABLE `copy` ( + `id` int(11) NOT NULL, + `user` text, + `game` char(6) NOT NULL, + `server` int(11) NOT NULL, + `pack` varchar(100) NOT NULL, + `name` char(32) NOT NULL, + `info` varchar(100) NOT NULL, + `plugins` text NOT NULL, + `date` int(11) NOT NULL, + `status` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `crontab` +-- + +CREATE TABLE `crontab` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `task` char(7) NOT NULL DEFAULT '', + `cron` text, + `week` text, + `time` char(20) NOT NULL DEFAULT '', + `commands` text +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `firewall` +-- + +CREATE TABLE `firewall` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `sip` char(20) NOT NULL, + `dest` char(27) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `graph` +-- + +CREATE TABLE `graph` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `key` char(32) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `graph_day` +-- + +CREATE TABLE `graph_day` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `online` int(11) NOT NULL, + `cpu` int(11) NOT NULL, + `ram` int(11) NOT NULL, + `hdd` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `graph_hour` +-- + +CREATE TABLE `graph_hour` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `online` int(11) NOT NULL, + `cpu` int(11) NOT NULL, + `ram` int(11) NOT NULL, + `hdd` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `help` +-- + +CREATE TABLE `help` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `type` varchar(10) NOT NULL, + `service` int(11) NOT NULL, + `status` int(11) NOT NULL, + `date` int(11) NOT NULL, + `time` int(11) NOT NULL, + `title` varchar(100) NOT NULL DEFAULT '', + `close` int(11) NOT NULL, + `notice` tinyint(1) NOT NULL DEFAULT '0', + `notice_admin` int(11) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `help_dialogs` +-- + +CREATE TABLE `help_dialogs` ( + `id` int(11) NOT NULL, + `help` int(11) NOT NULL, + `user` int(11) NOT NULL, + `text` varchar(1000) NOT NULL, + `img` varchar(1000) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `help_upload` +-- + +CREATE TABLE `help_upload` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `name` varchar(36) NOT NULL, + `time` int(11) NOT NULL, + `status` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `jobs` +-- + +CREATE TABLE `jobs` ( + `id` int(11) NOT NULL, + `name` varchar(500) NOT NULL, + `job` varchar(150) NOT NULL, + `desc` text NOT NULL, + `status` int(11) NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `jobs_app` +-- + +CREATE TABLE `jobs_app` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `text` text NOT NULL, + `contact` varchar(100) NOT NULL, + `job` int(11) NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `logs` +-- + +CREATE TABLE `logs` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `text` text NOT NULL, + `date` int(11) NOT NULL, + `type` char(10) NOT NULL, + `money` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `logs_sys` +-- + +CREATE TABLE `logs_sys` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `server` int(11) NOT NULL DEFAULT '0', + `control` int(11) NOT NULL DEFAULT '0', + `text` text NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `maps` +-- + +CREATE TABLE `maps` ( + `id` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `game` char(10) NOT NULL, + `name` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `news` +-- + +CREATE TABLE `news` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `text` text NOT NULL, + `full_text` text NOT NULL, + `tags` varchar(100) NOT NULL, + `views` int(11) NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Дамп данных таблицы `news` +-- + +INSERT INTO `news` (`id`, `name`, `text`, `full_text`, `tags`, `views`, `date`) VALUES +(1, 'Мы открылись!', 'Мы с удовольствием сообщаем, что сегодня всем поклонникам он-лайн игр стал доступен наш мультифункциональный сервис по аренде игровых серверов.\r\n\r\nВ результате профессиональной работы и тщательной технической подготовки был получен производительный и удобный для пользователей IT-продукт, который в самое ближайшее время составит серьёзную конкуренцию всем существующим в этой рыночной нише проектам.\r\n\r\nНаша команда в процессе разработки сервиса старалась учитывать все слабые и сильные стороны аналогичных предложений. Во главе угла ставились надёжное быстродействие хостинга и максимально доступные цены для пользователей. Предлагая вам лучшие условия аренды игровых серверов нового поколения, мы рассчитываем на долгосрочное сотрудничество и каждого заказчика рассматриваем как перспективного партнёра.\r\n\r\nС сегодняшнего дня великолепный мир захватывающих интерактивных игр стал более доступным и технически совершенным, обеспечивая новый уровень эмоциональной насыщенности не прерывающимся ни на минуту компьютерным баталиям.\r\n', 'Мы с удовольствием сообщаем, что сегодня всем поклонникам он-лайн игр стал доступен наш мультифункциональный сервис по аренде игровых серверов.\r\n\r\nВ результате профессиональной работы и тщательной технической подготовки был получен производительный и удобный для пользователей IT-продукт, который в самое ближайшее время составит серьёзную конкуренцию всем существующим в этой рыночной нише проектам.\r\n\r\nНаша команда в процессе разработки сервиса старалась учитывать все слабые и сильные стороны аналогичных предложений. Во главе угла ставились надёжное быстродействие хостинга и максимально доступные цены для пользователей. Предлагая вам лучшие условия аренды игровых серверов нового поколения, мы рассчитываем на долгосрочное сотрудничество и каждого заказчика рассматриваем как перспективного партнёра.\r\n\r\nС сегодняшнего дня великолепный мир захватывающих интерактивных игр стал более доступным и технически совершенным, обеспечивая новый уровень эмоциональной насыщенности не прерывающимся ни на минуту компьютерным баталиям.\r\n', '', 0, 1577869200); + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `notice` +-- + +CREATE TABLE `notice` ( + `id` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `server` int(11) NOT NULL DEFAULT '0', + `text` text NOT NULL, + `color` char(10) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `owners` +-- + +CREATE TABLE `owners` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `user` int(11) NOT NULL, + `rights` text NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `pages` +-- + +CREATE TABLE `pages` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL, + `file` varchar(32) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `panel` +-- + +CREATE TABLE `panel` ( + `address` char(21) NOT NULL, + `passwd` char(32) NOT NULL, + `path` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Дамп данных таблицы `panel` +-- + +INSERT INTO `panel` (`address`, `passwd`, `path`) VALUES +('IPADDR:22', 'ROOTPASSWORD', '/var/enginegp/'); + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins` +-- + +CREATE TABLE `plugins` ( + `id` int(11) NOT NULL, + `cat` int(11) NOT NULL, + `game` char(6) NOT NULL, + `name` varchar(50) NOT NULL, + `desc` text, + `info` text, + `images` text, + `status` int(11) NOT NULL, + `cfg` int(11) NOT NULL, + `upd` int(11) NOT NULL, + `sort` int(11) NOT NULL, + `incompatible` varchar(100) NOT NULL DEFAULT '', + `choice` varchar(100) NOT NULL DEFAULT '', + `required` varchar(100) NOT NULL DEFAULT '', + `packs` varchar(100) NOT NULL DEFAULT 'all', + `price` float NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_buy` +-- + +CREATE TABLE `plugins_buy` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `key` varchar(32) NOT NULL, + `server` int(11) NOT NULL, + `price` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_category` +-- + +CREATE TABLE `plugins_category` ( + `id` int(11) NOT NULL, + `game` char(6) NOT NULL, + `name` varchar(50) NOT NULL, + `sort` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_clear` +-- + +CREATE TABLE `plugins_clear` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `text` varchar(200) NOT NULL, + `file` varchar(100) NOT NULL, + `regex` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_config` +-- + +CREATE TABLE `plugins_config` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `file` varchar(100) NOT NULL, + `sort` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_delete` +-- + +CREATE TABLE `plugins_delete` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `file` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_delete_ins` +-- + +CREATE TABLE `plugins_delete_ins` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `install` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_install` +-- + +CREATE TABLE `plugins_install` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `upd` int(11) NOT NULL DEFAULT '0', + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_update` +-- + +CREATE TABLE `plugins_update` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `desc` text, + `info` text, + `images` text, + `status` int(11) NOT NULL, + `cfg` int(11) NOT NULL, + `upd` int(11) NOT NULL, + `incompatible` varchar(100) NOT NULL DEFAULT '', + `choice` varchar(100) NOT NULL DEFAULT '', + `required` varchar(100) NOT NULL DEFAULT '', + `packs` varchar(100) NOT NULL DEFAULT '', + `price` float NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_write` +-- + +CREATE TABLE `plugins_write` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `file` varchar(100) NOT NULL, + `top` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `plugins_write_del` +-- + +CREATE TABLE `plugins_write_del` ( + `id` int(11) NOT NULL, + `plugin` int(11) NOT NULL, + `update` int(11) NOT NULL, + `text` varchar(100) NOT NULL, + `file` varchar(100) NOT NULL, + `top` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `privileges` +-- + +CREATE TABLE `privileges` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `active` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `privileges_buy` +-- + +CREATE TABLE `privileges_buy` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `text` text NOT NULL, + `sql` text NOT NULL, + `price` float NOT NULL, + `key` varchar(32) NOT NULL, + `date` int(11) NOT NULL, + `mail` varchar(50) NOT NULL, + `status` tinyint(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `privileges_list` +-- + +CREATE TABLE `privileges_list` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `name` varchar(30) NOT NULL, + `flags` varchar(50) NOT NULL, + `immunity` int(11) NOT NULL DEFAULT '0', + `data` varchar(100) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `promo` +-- + +CREATE TABLE `promo` ( + `id` int(11) NOT NULL, + `cod` char(20) NOT NULL, + `value` char(4) NOT NULL, + `discount` tinyint(1) NOT NULL, + `data` text NOT NULL, + `hits` int(11) NOT NULL, + `use` int(11) NOT NULL, + `extend` tinyint(1) NOT NULL, + `tarif` int(11) NOT NULL, + `user` int(11) NOT NULL, + `server` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `promo_use` +-- + +CREATE TABLE `promo_use` ( + `id` int(11) NOT NULL, + `promo` int(11) NOT NULL, + `user` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `recovery` +-- + +CREATE TABLE `recovery` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `mail` char(50) NOT NULL, + `key` char(32) NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `security` +-- + +CREATE TABLE `security` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `address` char(20) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `servers` +-- + +CREATE TABLE `servers` ( + `id` int(11) NOT NULL, + `uid` int(11) NOT NULL DEFAULT '0', + `unit` int(11) NOT NULL DEFAULT '0', + `tarif` int(11) NOT NULL DEFAULT '0', + `user` int(11) NOT NULL DEFAULT '0', + `address` char(21) NOT NULL DEFAULT '', + `port` int(11) NOT NULL DEFAULT '0', + `game` char(6) NOT NULL DEFAULT '', + `slots` int(11) NOT NULL DEFAULT '0', + `slots_start` int(11) NOT NULL DEFAULT '0', + `online` int(11) NOT NULL DEFAULT '0', + `players` text, + `status` char(10) NOT NULL DEFAULT '', + `name` varchar(100) NOT NULL DEFAULT '', + `pack` varchar(50) NOT NULL DEFAULT '', + `plugins_use` tinyint(1) NOT NULL DEFAULT '0', + `console_use` tinyint(1) NOT NULL DEFAULT '0', + `stats_use` tinyint(1) NOT NULL DEFAULT '0', + `copy_use` tinyint(1) NOT NULL DEFAULT '0', + `web_use` tinyint(1) NOT NULL DEFAULT '0', + `ftp_use` tinyint(1) NOT NULL DEFAULT '0', + `ftp` tinyint(1) NOT NULL DEFAULT '0', + `ftp_root` tinyint(1) NOT NULL DEFAULT '0', + `ftp_passwd` char(20) NOT NULL DEFAULT '', + `ftp_on` tinyint(1) NOT NULL DEFAULT '0', + `fps` int(11) NOT NULL DEFAULT '0', + `tickrate` int(11) NOT NULL DEFAULT '0', + `ram` int(11) NOT NULL DEFAULT '0', + `ram_use` int(11) NOT NULL DEFAULT '0', + `ram_use_max` int(11) NOT NULL DEFAULT '0', + `ram_fix` tinyint(1) NOT NULL DEFAULT '0', + `map` varchar(100) NOT NULL DEFAULT '', + `map_start` varchar(100) NOT NULL DEFAULT '', + `vac` tinyint(1) NOT NULL DEFAULT '0', + `fastdl` int(11) NOT NULL DEFAULT '0', + `pingboost` int(11) NOT NULL DEFAULT '0', + `cpu` int(11) NOT NULL DEFAULT '0', + `cpu_use` int(11) NOT NULL DEFAULT '0', + `cpu_use_max` int(11) NOT NULL DEFAULT '0', + `core_fix` int(11) NOT NULL DEFAULT '0', + `core_fix_one` tinyint(1) NOT NULL DEFAULT '0', + `core_use` int(11) NOT NULL DEFAULT '0', + `hdd` int(11) NOT NULL DEFAULT '0', + `hdd_use` int(11) NOT NULL DEFAULT '0', + `time` int(11) NOT NULL DEFAULT '0', + `date` int(11) NOT NULL DEFAULT '0', + `overdue` int(11) NOT NULL DEFAULT '0', + `block` int(11) NOT NULL DEFAULT '0', + `test` tinyint(1) NOT NULL DEFAULT '0', + `stop` tinyint(1) NOT NULL DEFAULT '0', + `autostop` tinyint(1) NOT NULL DEFAULT '0', + `time_start` int(11) NOT NULL DEFAULT '0', + `reinstall` int(11) NOT NULL DEFAULT '0', + `update` int(11) NOT NULL DEFAULT '0', + `benefit` int(11) NOT NULL DEFAULT '0', + `autorestart` tinyint(1) NOT NULL DEFAULT '0', + `sms` tinyint(1) NOT NULL DEFAULT '0', + `mail` tinyint(1) NOT NULL DEFAULT '0', + `ddos` tinyint(1) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `signup` +-- + +CREATE TABLE `signup` ( + `id` int(11) NOT NULL, + `mail` char(50) NOT NULL, + `key` char(32) NOT NULL, + `data` text NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `tarifs` +-- + +CREATE TABLE `tarifs` ( + `id` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `game` char(8) NOT NULL, + `name` varchar(100) NOT NULL, + `slots_min` int(11) NOT NULL, + `slots_max` int(11) NOT NULL, + `port_min` int(11) NOT NULL, + `port_max` int(11) NOT NULL, + `hostname` varchar(100) NOT NULL, + `packs` text NOT NULL, + `path` varchar(100) NOT NULL, + `install` varchar(100) NOT NULL, + `update` varchar(100) NOT NULL, + `fps` varchar(100) NOT NULL, + `tickrate` varchar(100) NOT NULL, + `ram` varchar(100) NOT NULL, + `param_fix` tinyint(1) NOT NULL DEFAULT '0', + `time` varchar(100) NOT NULL, + `timext` varchar(100) NOT NULL, + `test` int(11) NOT NULL, + `tests` int(11) NOT NULL, + `discount` tinyint(1) NOT NULL, + `map` varchar(50) NOT NULL, + `ftp` tinyint(1) NOT NULL DEFAULT '0', + `plugins` tinyint(1) NOT NULL DEFAULT '0', + `console` tinyint(1) NOT NULL DEFAULT '0', + `stats` tinyint(1) NOT NULL DEFAULT '0', + `copy` tinyint(1) NOT NULL DEFAULT '0', + `web` tinyint(1) NOT NULL DEFAULT '0', + `plugins_install` text NOT NULL, + `hdd` int(11) NOT NULL, + `autostop` tinyint(1) NOT NULL, + `price` text, + `core_fix` varchar(100) NOT NULL DEFAULT '', + `ip` text, + `show` tinyint(1) NOT NULL, + `sort` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Дамп данных таблицы `tarifs` +-- + +INSERT INTO `tarifs` (`id`, `unit`, `game`, `name`, `slots_min`, `slots_max`, `port_min`, `port_max`, `hostname`, `packs`, `path`, `install`, `update`, `fps`, `tickrate`, `ram`, `param_fix`, `time`, `timext`, `test`, `tests`, `discount`, `map`, `ftp`, `plugins`, `console`, `stats`, `copy`, `web`, `plugins_install`, `hdd`, `autostop`, `price`, `core_fix`, `ip`, `show`, `sort`) VALUES +(1, 1, 'cs', 'Обычный', 10, 32, 27016, 27116, 'Новый игровой сервер', 'eyJzdGVhbSI6IlNURUFNIFtcdTA0MjdcdTA0MzhcdTA0NDFcdTA0NDJcdTA0NGJcdTA0MzkgXHUwNDQxXHUwNDM1XHUwNDQwXHUwNDMyXHUwNDM1XHUwNDQwXSIsInJlaGxkcyI6IlJlSExEUyAzLjcuMC54eHgtZGV2IiwiODMwOCI6IkJVSUxEIDgzMDgiLCI4MTk2IjoiQlVJTEQgODE5NiIsIjc4ODIiOiJCVUlMRCA3ODgyIiwiNzU1OSI6IkJVSUxEIDc1NTkiLCI2MTUzIjoiQlVJTEQgNjE1MyIsIjU3ODciOiJCVUlMRCA1Nzg3In0=', '/path/cs/', '/servers/cs/', '/path/update/cs/', '500:1000', '66:100', '512', 0, '15:30:90:180', '7:30:90:180', 0, 0, 1, 'de_dust2', 1, 0, 1, 0, 1, 0, '', 5000, 0, '25:35', '', '', 1, 1), +(2, 1, 'cssold', 'Обычный', 10, 64, 27117, 27217, 'Новый игровой сервер', 'eyJzdGVhbSI6IlN0ZWFtIFtcdTA0MjdcdTA0MzhcdTA0NDFcdTA0NDJcdTA0NGJcdTA0MzkgXHUwNDQxXHUwNDM1XHUwNDQwXHUwNDMyXHUwNDM1XHUwNDQwXSJ9', '/path/cssold/', '/servers/cssold/', '/path/update/cssold/', '500:1000', '66:100', '512', 0, '15:30:90:180', '7:30:90:180', 0, 0, 1, 'de_dust2', 1, 0, 1, 0, 1, 0, '', 15000, 0, 'eyI2Nl81MDAiOiIyNyIsIjEwMF81MDAiOiIzNSIsIjY2XzEwMDAiOiI0NSIsIjEwMF8xMDAwIjoiNTUifQ==', '', '', 1, 1), +(3, 1, 'css', 'Обычный', 10, 64, 27218, 27318, 'Новый игровой сервер', 'eyJzdGVhbSI6IlN0ZWFtIFtcdTA0MjdcdTA0MzhcdTA0NDFcdTA0NDJcdTA0NGJcdTA0MzkgXHUwNDQxXHUwNDM1XHUwNDQwXHUwNDMyXHUwNDM1XHUwNDQwXSJ9', '/path/css/', '/servers/css/', '/path/update/css/', '500:1000', '66:100', '512', 0, '15:30:90:180', '7:30:90:180', 0, 0, 1, 'de_dust2', 1, 0, 1, 0, 1, 0, '', 15000, 0, '27:35', '', '', 1, 1), +(4, 1, 'csgo', 'Обычный', 10, 64, 27319, 27419, 'Новый игровой сервер', 'eyJzdGVhbSI6IlN0ZWFtIFtcdTA0MjdcdTA0MzhcdTA0NDFcdTA0NDJcdTA0NGJcdTA0MzkgXHUwNDQxXHUwNDM1XHUwNDQwXHUwNDMyXHUwNDM1XHUwNDQwXSJ9', '/path/csgo/', '/servers/csgo/', '/path/update/csgo/', '500:1000', '64:128', '1024', 0, '15:30:90:180', '7:30:90:180', 0, 0, 1, 'de_dust2', 1, 0, 1, 0, 1, 0, '', 30000, 0, '40:55', '', '', 1, 1); + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `test` +-- + +CREATE TABLE `test` ( + `id` int(11) NOT NULL, + `name` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `tests` +-- + +CREATE TABLE `tests` ( + `id` int(11) NOT NULL, + `server` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `game` char(6) NOT NULL, + `user` int(11) NOT NULL, + `time` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `units` +-- + +CREATE TABLE `units` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL, + `address` char(21) NOT NULL, + `passwd` char(32) NOT NULL, + `sql_login` char(20) NOT NULL, + `sql_passwd` char(32) NOT NULL, + `sql_port` int(11) NOT NULL, + `sql_ftp` char(20) NOT NULL, + `cs` tinyint(1) NOT NULL DEFAULT '0', + `cssold` tinyint(1) NOT NULL DEFAULT '0', + `css` tinyint(1) NOT NULL DEFAULT '0', + `csgo` tinyint(1) NOT NULL DEFAULT '0', + `samp` tinyint(1) NOT NULL DEFAULT '0', + `crmp` tinyint(1) NOT NULL DEFAULT '0', + `mta` tinyint(1) NOT NULL DEFAULT '0', + `mc` tinyint(1) NOT NULL DEFAULT '0', + `ram` int(11) NOT NULL, + `test` int(11) NOT NULL, + `show` tinyint(1) NOT NULL, + `sort` int(11) NOT NULL, + `domain` varchar(40) NOT NULL DEFAULT '', + `ddos` tinyint(1) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `users` +-- + +CREATE TABLE `users` ( + `id` int(11) NOT NULL, + `login` char(15) NOT NULL, + `passwd` char(32) NOT NULL, + `name` char(32) NOT NULL, + `lastname` char(32) NOT NULL, + `patronymic` char(32) NOT NULL, + `mail` char(50) NOT NULL, + `new_mail` char(50) NOT NULL DEFAULT '', + `confirm_mail` char(32) NOT NULL DEFAULT '', + `phone` char(12) NOT NULL, + `confirm_phone` int(6) NOT NULL DEFAULT '0', + `contacts` varchar(100) NOT NULL, + `balance` float NOT NULL, + `wmr` char(13) NOT NULL DEFAULT '', + `group` char(7) NOT NULL, + `support_info` varchar(50) NOT NULL DEFAULT '', + `level` int(11) NOT NULL DEFAULT '0', + `ip` char(16) NOT NULL DEFAULT '', + `browser` char(20) NOT NULL DEFAULT '', + `time` int(11) NOT NULL DEFAULT '0', + `date` int(11) NOT NULL, + `part` int(11) NOT NULL DEFAULT '0', + `part_money` float NOT NULL DEFAULT '0', + `security_ip` tinyint(1) NOT NULL DEFAULT '0', + `security_code` tinyint(1) NOT NULL DEFAULT '0', + `notice_help` tinyint(1) NOT NULL DEFAULT '0', + `notice_news` tinyint(1) NOT NULL DEFAULT '1', + `help` tinyint(1) NOT NULL DEFAULT '0', + `rental` varchar(4) NOT NULL DEFAULT '0', + `extend` varchar(4) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Дамп данных таблицы `users` +-- + +INSERT INTO `users` (`id`, `login`, `passwd`, `name`, `lastname`, `patronymic`, `mail`, `new_mail`, `confirm_mail`, `phone`, `confirm_phone`, `contacts`, `balance`, `wmr`, `group`, `support_info`, `level`, `ip`, `browser`, `time`, `date`, `part`, `part_money`, `security_ip`, `security_code`, `notice_help`, `notice_news`, `help`, `rental`, `extend`) VALUES +(1, 'root', 'ENGINEGPHASH', 'Имя', 'Фамилия', 'Отчество', 'admin@enginegp.ru', '', '', '', 0, '', 10000, '', 'admin', '', 0, '127.0.0.1', 'Google Chrome', 1518459967, 1517667554, 0, 0, 0, 0, 0, 1, 0, '', ''); + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `web` +-- + +CREATE TABLE `web` ( + `id` int(11) NOT NULL, + `uid` int(11) NOT NULL DEFAULT '0', + `type` varchar(20) NOT NULL, + `desing` varchar(32) NOT NULL DEFAULT '', + `server` int(11) NOT NULL, + `user` int(11) NOT NULL, + `unit` int(11) NOT NULL, + `domain` varchar(40) NOT NULL DEFAULT '', + `passwd` varchar(32) NOT NULL DEFAULT '', + `config` text NOT NULL, + `login` varchar(32) NOT NULL DEFAULT '', + `update` int(11) NOT NULL DEFAULT '0', + `date` int(11) NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `wiki` +-- + +CREATE TABLE `wiki` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL, + `cat` int(11) NOT NULL, + `tags` varchar(100) NOT NULL, + `date` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `wiki_answer` +-- + +CREATE TABLE `wiki_answer` ( + `wiki` int(11) NOT NULL, + `cat` int(11) NOT NULL, + `text` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Структура таблицы `wiki_category` +-- + +CREATE TABLE `wiki_category` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL, + `sort` int(11) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Индексы сохранённых таблиц +-- + +-- +-- Индексы таблицы `address` +-- +ALTER TABLE `address` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `address_buy` +-- +ALTER TABLE `address_buy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_crmp` +-- +ALTER TABLE `admins_crmp` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_cs` +-- +ALTER TABLE `admins_cs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_csgo` +-- +ALTER TABLE `admins_csgo` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_css` +-- +ALTER TABLE `admins_css` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_cssold` +-- +ALTER TABLE `admins_cssold` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_mc` +-- +ALTER TABLE `admins_mc` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_mta` +-- +ALTER TABLE `admins_mta` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `admins_samp` +-- +ALTER TABLE `admins_samp` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `api` +-- +ALTER TABLE `api` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `auth` +-- +ALTER TABLE `auth` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `boost` +-- +ALTER TABLE `boost` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `boost_rating` +-- +ALTER TABLE `boost_rating` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `cashback` +-- +ALTER TABLE `cashback` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `chat` +-- +ALTER TABLE `chat` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control` +-- +ALTER TABLE `control` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_admins_cs` +-- +ALTER TABLE `control_admins_cs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_admins_csgo` +-- +ALTER TABLE `control_admins_csgo` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_admins_css` +-- +ALTER TABLE `control_admins_css` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_admins_cssold` +-- +ALTER TABLE `control_admins_cssold` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_boost` +-- +ALTER TABLE `control_boost` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_copy` +-- +ALTER TABLE `control_copy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_crontab` +-- +ALTER TABLE `control_crontab` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_firewall` +-- +ALTER TABLE `control_firewall` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_plugins_buy` +-- +ALTER TABLE `control_plugins_buy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_plugins_install` +-- +ALTER TABLE `control_plugins_install` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `control_servers` +-- +ALTER TABLE `control_servers` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `copy` +-- +ALTER TABLE `copy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `crontab` +-- +ALTER TABLE `crontab` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `firewall` +-- +ALTER TABLE `firewall` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `graph` +-- +ALTER TABLE `graph` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `graph_day` +-- +ALTER TABLE `graph_day` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `graph_hour` +-- +ALTER TABLE `graph_hour` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `help` +-- +ALTER TABLE `help` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `help_dialogs` +-- +ALTER TABLE `help_dialogs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `help_upload` +-- +ALTER TABLE `help_upload` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `jobs` +-- +ALTER TABLE `jobs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `jobs_app` +-- +ALTER TABLE `jobs_app` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `logs` +-- +ALTER TABLE `logs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `logs_sys` +-- +ALTER TABLE `logs_sys` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `maps` +-- +ALTER TABLE `maps` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `news` +-- +ALTER TABLE `news` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `notice` +-- +ALTER TABLE `notice` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `owners` +-- +ALTER TABLE `owners` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `pages` +-- +ALTER TABLE `pages` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `panel` +-- +ALTER TABLE `panel` + ADD PRIMARY KEY (`address`); + +-- +-- Индексы таблицы `plugins` +-- +ALTER TABLE `plugins` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_buy` +-- +ALTER TABLE `plugins_buy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_category` +-- +ALTER TABLE `plugins_category` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_clear` +-- +ALTER TABLE `plugins_clear` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_config` +-- +ALTER TABLE `plugins_config` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_delete` +-- +ALTER TABLE `plugins_delete` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_delete_ins` +-- +ALTER TABLE `plugins_delete_ins` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_install` +-- +ALTER TABLE `plugins_install` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_update` +-- +ALTER TABLE `plugins_update` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_write` +-- +ALTER TABLE `plugins_write` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `plugins_write_del` +-- +ALTER TABLE `plugins_write_del` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `privileges` +-- +ALTER TABLE `privileges` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `privileges_buy` +-- +ALTER TABLE `privileges_buy` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `privileges_list` +-- +ALTER TABLE `privileges_list` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `promo` +-- +ALTER TABLE `promo` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `promo_use` +-- +ALTER TABLE `promo_use` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `recovery` +-- +ALTER TABLE `recovery` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `security` +-- +ALTER TABLE `security` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `servers` +-- +ALTER TABLE `servers` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `signup` +-- +ALTER TABLE `signup` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `tarifs` +-- +ALTER TABLE `tarifs` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `test` +-- +ALTER TABLE `test` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `tests` +-- +ALTER TABLE `tests` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `units` +-- +ALTER TABLE `units` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `web` +-- +ALTER TABLE `web` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `wiki` +-- +ALTER TABLE `wiki` + ADD PRIMARY KEY (`id`); + +-- +-- Индексы таблицы `wiki_answer` +-- +ALTER TABLE `wiki_answer` + ADD PRIMARY KEY (`wiki`); + +-- +-- Индексы таблицы `wiki_category` +-- +ALTER TABLE `wiki_category` + ADD PRIMARY KEY (`id`); + +-- +-- AUTO_INCREMENT для сохранённых таблиц +-- + +-- +-- AUTO_INCREMENT для таблицы `address` +-- +ALTER TABLE `address` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `address_buy` +-- +ALTER TABLE `address_buy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_crmp` +-- +ALTER TABLE `admins_crmp` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_cs` +-- +ALTER TABLE `admins_cs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_csgo` +-- +ALTER TABLE `admins_csgo` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_css` +-- +ALTER TABLE `admins_css` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_cssold` +-- +ALTER TABLE `admins_cssold` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_mc` +-- +ALTER TABLE `admins_mc` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_mta` +-- +ALTER TABLE `admins_mta` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `admins_samp` +-- +ALTER TABLE `admins_samp` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `api` +-- +ALTER TABLE `api` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `auth` +-- +ALTER TABLE `auth` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9; +-- +-- AUTO_INCREMENT для таблицы `boost` +-- +ALTER TABLE `boost` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `boost_rating` +-- +ALTER TABLE `boost_rating` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `cashback` +-- +ALTER TABLE `cashback` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `chat` +-- +ALTER TABLE `chat` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; +-- +-- AUTO_INCREMENT для таблицы `control` +-- +ALTER TABLE `control` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_admins_cs` +-- +ALTER TABLE `control_admins_cs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_boost` +-- +ALTER TABLE `control_boost` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_copy` +-- +ALTER TABLE `control_copy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_crontab` +-- +ALTER TABLE `control_crontab` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_firewall` +-- +ALTER TABLE `control_firewall` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_plugins_buy` +-- +ALTER TABLE `control_plugins_buy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_plugins_install` +-- +ALTER TABLE `control_plugins_install` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `control_servers` +-- +ALTER TABLE `control_servers` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `copy` +-- +ALTER TABLE `copy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `crontab` +-- +ALTER TABLE `crontab` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `firewall` +-- +ALTER TABLE `firewall` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `graph` +-- +ALTER TABLE `graph` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `graph_day` +-- +ALTER TABLE `graph_day` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `graph_hour` +-- +ALTER TABLE `graph_hour` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `help` +-- +ALTER TABLE `help` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `help_dialogs` +-- +ALTER TABLE `help_dialogs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `help_upload` +-- +ALTER TABLE `help_upload` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `jobs` +-- +ALTER TABLE `jobs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `jobs_app` +-- +ALTER TABLE `jobs_app` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `logs` +-- +ALTER TABLE `logs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `logs_sys` +-- +ALTER TABLE `logs_sys` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `maps` +-- +ALTER TABLE `maps` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `news` +-- +ALTER TABLE `news` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; +-- +-- AUTO_INCREMENT для таблицы `notice` +-- +ALTER TABLE `notice` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `owners` +-- +ALTER TABLE `owners` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `pages` +-- +ALTER TABLE `pages` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins` +-- +ALTER TABLE `plugins` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_buy` +-- +ALTER TABLE `plugins_buy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_category` +-- +ALTER TABLE `plugins_category` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_clear` +-- +ALTER TABLE `plugins_clear` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_config` +-- +ALTER TABLE `plugins_config` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_delete` +-- +ALTER TABLE `plugins_delete` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_delete_ins` +-- +ALTER TABLE `plugins_delete_ins` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_install` +-- +ALTER TABLE `plugins_install` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_update` +-- +ALTER TABLE `plugins_update` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_write` +-- +ALTER TABLE `plugins_write` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `plugins_write_del` +-- +ALTER TABLE `plugins_write_del` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `privileges` +-- +ALTER TABLE `privileges` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `privileges_buy` +-- +ALTER TABLE `privileges_buy` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `privileges_list` +-- +ALTER TABLE `privileges_list` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `promo` +-- +ALTER TABLE `promo` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `promo_use` +-- +ALTER TABLE `promo_use` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `recovery` +-- +ALTER TABLE `recovery` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `security` +-- +ALTER TABLE `security` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `servers` +-- +ALTER TABLE `servers` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `signup` +-- +ALTER TABLE `signup` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `tarifs` +-- +ALTER TABLE `tarifs` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `test` +-- +ALTER TABLE `test` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `tests` +-- +ALTER TABLE `tests` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `units` +-- +ALTER TABLE `units` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `users` +-- +ALTER TABLE `users` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; +-- +-- AUTO_INCREMENT для таблицы `web` +-- +ALTER TABLE `web` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `wiki` +-- +ALTER TABLE `wiki` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `wiki_answer` +-- +ALTER TABLE `wiki_answer` + MODIFY `wiki` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT для таблицы `wiki_category` +-- +ALTER TABLE `wiki_category` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/fail.html b/fail.html new file mode 100644 index 0000000..a452102 --- /dev/null +++ b/fail.html @@ -0,0 +1,27 @@ + + + + EGPv3 - Ошибка при пополнении баланса + + + + + + + + + + +
+
+

Уважаемый клиент, к сожалению, произошла ошибка при пополнении

+ + +
+ + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..500901c Binary files /dev/null and b/favicon.ico differ diff --git a/files/pages/.htaccess b/files/pages/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/files/plugins/delete/.htaccess b/files/plugins/delete/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/files/plugins/install/.htaccess b/files/plugins/install/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/files/plugins/update/.htaccess b/files/plugins/update/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/index.php b/index.php new file mode 100644 index 0000000..911e99f --- /dev/null +++ b/index.php @@ -0,0 +1,62 @@ +connect('127.0.0.1', 11211) or exit('Ошибка: #mc0, обновите страницу позже, если ошибка повторяется, обратитесь в тех.поддержку: EGPv3'); + + // Настройки + include(DATA.'config.php'); + include(DATA.'engine.php'); + include(DATA.'mysql.php'); + include(DATA.'params.php'); + + // Библиотеки + include(LIB.'sql.php'); + include(LIB.'html.php'); + include(LIB.'system.php'); + + $uip = sys::ip(); + + /* if(!isset($_COOKIE['egp_device'])) + { + include(LIB.'megp.php'); + + $device = $megp->isMobile() ? 'mobile' : '!mobile'; + + sys::cookie('egp_device', $device, 14); + + if($device == 'mobile') + sys::back(); + } */ + + // Распределитель + if($device == '!mobile') + include(SYS.'distributor.php'); + /* else + include(SYS.'mdistributor.php'); */ + + // Выхлоп + echo $html->arr['all']; +?> \ No newline at end of file diff --git a/notice.wav b/notice.wav new file mode 100644 index 0000000..8754278 Binary files /dev/null and b/notice.wav differ diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..7703799 --- /dev/null +++ b/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Disallow: /acp +Disallow: /system +Disallow: /temp +Disallow: /template +Disallow: /upload \ No newline at end of file diff --git a/success.html b/success.html new file mode 100644 index 0000000..bfe7443 --- /dev/null +++ b/success.html @@ -0,0 +1,27 @@ + + + + EGPv3 - Успешное пополение баланса + + + + + + + + + + +
+
+

Уважаемый клиент, Вы успешо пополнили свой баланс

+ + +
+ + \ No newline at end of file diff --git a/system/acp/distributor.php b/system/acp/distributor.php new file mode 100644 index 0000000..2827342 --- /dev/null +++ b/system/acp/distributor.php @@ -0,0 +1,133 @@ +query('SELECT `id` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" AND `group`="admin" LIMIT 1'); + if($sql->num()) + { + $sql->query('SELECT `id`, `login`, `balance`, `group`, `time` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" LIMIT 1'); + $user = $sql->get(); + + // Обновление активности + if($user['time']+10 < $start_point) + $sql->query('UPDATE `users` set `time`="'.$start_point.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $auth = true; + } + } + } + + if(!$auth) + exit(header('Refresh: 0; URL=http://'.$cfg['url'].'/403')); + + // Подключение файла + if(in_array($route, $aRoute)) + include(ENG.$route.'.php'); + else{ + $route = 'index'; + include(ENG.'index.php'); + } + + // Обновление ссылок + if(isset($html->arr['main'])) + { + $html->upd( + array( + '[cur]', + '[acp]', + '[home]', + '[js]', + '[css]', + '[img]' + ), + + array( + $cfg['currency'], + $cfg['http'].'acp/', + $cfg['http'], + $cfg['http'].'template/acp/js/', + $cfg['http'].'template/acp/css/', + $cfg['http'].'template/acp/images/' + ), + 'main' + ); + } + + if(isset($html->arr['menu'])) + { + $html->upd( + array( + '[acp]', + '[home]', + '[js]', + '[css]', + '[img]' + ), + + array( + $cfg['http'].'acp/', + $cfg['http'], + $cfg['http'].'template/acp/js/', + $cfg['http'].'template/acp/css/', + $cfg['http'].'template/acp/images/' + ), + 'menu' + ); + } + + // Заготовка выхлопа + $html->get('all'); + + $html->set('acp', $cfg['http'].'acp/'); + $html->set('admin', $user['id']); + $html->set('home', $cfg['http']); + $html->set('js', $cfg['http'].'template/acp/js/'); + $html->set('css', $cfg['http'].'template/acp/css/'); + $html->set('img', $cfg['http'].'template/acp/images/'); + + if(isset($html->arr['menu'])) + { + $html->unit('section', true); + $html->set('info', $info); + $html->set('menu', $html->arr['menu']); + }else + $html->unit('section'); + + $html->unit('p_'.$route, true); + + unset($aRoute[array_search($route, $aRoute)]); + + foreach($aRoute as $route) + $html->unit('p_'.$route); + + $html->set('main', isset($html->arr['main']) ? $html->arr['main'] : '', true); + + $html->pack('all'); +?> \ No newline at end of file diff --git a/system/acp/engine/addons.php b/system/acp/engine/addons.php new file mode 100644 index 0000000..3033eee --- /dev/null +++ b/system/acp/engine/addons.php @@ -0,0 +1,38 @@ + Управление дополнениями'; + + $aSection = array( + 'index', + 'update', + 'addcat', + 'addpl', + 'cats', + 'updmp', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/addons'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `plugins_category`'); + $html->set('cats', $sql->num()); + + $sql->query('SELECT `id` FROM `plugins`'); + $html->set('plugins', $sql->num()); + + $html->pack('menu'); + + include(SEC.'addons/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/boost.php b/system/acp/engine/boost.php new file mode 100644 index 0000000..6b0200f --- /dev/null +++ b/system/acp/engine/boost.php @@ -0,0 +1,41 @@ + Статистика BOOST CS: 1.6'; + + $aSection = $aBoost['cs']['boost']; + + if($section == 'search') + include(SEC.'boost/search.php'); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/boost'); + + $boosts = ''; + + if($section != 'index') + $html->unit('s_index'); + else + $html->unit('s_index', true); + + foreach($aSection as $service) + { + if($section == $service) + $boosts .= '
  • '.$aBoost['cs'][$section]['site'].'
  • '; + else + $boosts .= '
  • '.$aBoost['cs'][$service]['site'].'
  • '; + } + + $html->set('boosts', $boosts); + + $html->pack('menu'); + + $inc = $section != 'index' ? 'service' : 'index'; + + include(SEC.'boost/'.$inc.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/cashback.php b/system/acp/engine/cashback.php new file mode 100644 index 0000000..4897040 --- /dev/null +++ b/system/acp/engine/cashback.php @@ -0,0 +1,61 @@ +get($nmc)) + sys::outjs(array('e' => $text['mcache']), $nmc); + + // Создание сессии + $mcache->set($nmc, 1, false, 10); + + if($id) + { + $sql->query('SELECT `user`, `money`, `purse`, `status` FROM `cashback` WHERE `id`="'.$id.'" LIMIT 1'); + $cb = $sql->get(); + + if(!$cb['status']) + sys::outjs(array('e' => 'Данная заявка уже была обработана'), $nmc); + + $purse = $cb['purse']{0} == 'R' ? 'webmoney' : 'qiwi'; + + // Запрос на шлюз + if($cfg['part_gateway'] == 'unitpay') + { + $sum = $cb['money']-($cb['money']/100*$cfg['part_output_proc']); + + $json = file_get_contents('https://unitpay.ru/api?method=massPayment¶ms[sum]='.$sum.'¶ms[purse]='.$cb['purse'].'¶ms[login]='.$cfg['unitpay_mail'].'¶ms[transactionId]='.$id.' ¶ms[secretKey]='.$cfg['unitpay_api'].'¶ms[paymentType]='.$purse); + + $array = json_decode($json, true); + + // Упешный вывод средств + if(is_array($array) AND isset($array['result']) AND in_array($array['result']['status'], array('success', 'not_completed '))) + { + $sql->query('UPDATE `cashback` set `status`="0" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `logs` set `user`="'.$cb['user'].'", `text`="'.sys::updtext(sys::text('logs', 'cashback'), + array('purse' => $purse, 'money' => $cb['money'])).'", `date`="'.$start_point.'", `type`="cashback", `money`="'.$cb['money'].'"'); + + sys::outjs(array('s' => 'Запрос на вывод средств был успешно выполнен'), $nmc); + } + + if(!is_array($array)) + sys::outjs(array('e' => 'Неудалось выполнить запрос'), $nmc); + + sys::outjs(array('e' => $array['error']['message']), $nmc); + } + + $sql->query('UPDATE `cashback` set `status`="0" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `logs` set `user`="'.$cb['user'].'", `text`="'.sys::updtext(sys::text('logs', 'cashback'), + array('purse' => $purse, 'money' => $cb['money'])).'", `date`="'.$start_point.'", `type`="cashback", `money`="'.$cb['money'].'"'); + + sys::outjs(array('s' => 'Запрос на вывод средств был успешно выполнен в ручном режиме'), $nmc); + } + + sys::outjs(array('e' => 'Не передан идентификатор заявки'), $nmc); +?> \ No newline at end of file diff --git a/system/acp/engine/control.php b/system/acp/engine/control.php new file mode 100644 index 0000000..a358684 --- /dev/null +++ b/system/acp/engine/control.php @@ -0,0 +1,37 @@ + Контроль'; + + $aSection = array( + 'index', + 'overdue', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $del = $cfg['server_delete']*86400; + $time = $start_point-$del; + + $html->get('menu', 'sections/control'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `control` WHERE `user`!="-1"'); + $html->set('all', $sql->num()); + + $sql->query('SELECT `id` FROM `control` WHERE `user`!="-1" AND `time`<"'.$start_point.'" AND `overdue`>"'.$time.'"'); + $html->set('overdue', $sql->num()); + + $html->pack('menu'); + + include(SEC.'control/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/hosting.php b/system/acp/engine/hosting.php new file mode 100644 index 0000000..1fd8008 --- /dev/null +++ b/system/acp/engine/hosting.php @@ -0,0 +1,9 @@ + Список вирт. хостингов'; + + $html->get('menu', 'sections/hosting'); + $html->pack('menu'); +?> \ No newline at end of file diff --git a/system/acp/engine/index.php b/system/acp/engine/index.php new file mode 100644 index 0000000..2acae96 --- /dev/null +++ b/system/acp/engine/index.php @@ -0,0 +1,91 @@ +arr['main'] = $mcache->get($mcache_name); + + $cbs = $sql->query('SELECT * FROM `cashback` WHERE `status`="1" ORDER BY `date` ASC'); + while($cb = $sql->get($cbs)) + { + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$cb['user'].'" LIMIT 1'); + $us = $sql->get(); + + $html->get('cashback'); + + $html->set('id', $cb['id']); + $html->set('user', $cb['user']); + $html->set('mail', $us['mail']); + $html->set('money', $cb['money'].' '.$cfg['currency']); + $html->set('cashback', ($cb['money']-($cb['money']/100*$cfg['part_output_proc'])).' '.$cfg['currency']); + $html->set('type', $cb['purse']{0} == 'R' ? 'WebMoney' : 'Qiwi'); + $html->set('purse', $cb['purse']); + $html->set('gateway', empty($cfg['part_gateway']) ? 'mm' : 'auto'); + $html->set('date', sys::today($cb['date'])); + + $html->pack('cashback'); + } + + $html->arr['cashback'] = isset($html->arr['cashback']) ? $html->arr['cashback'] : ''; + + if($html->arr['main'] == '') + { + $sql->query('SELECT `id` FROM `users`'); + $users = $sql->num(); + + $sql->query('SELECT `id`, `game`, `slots` FROM `servers`'); + $servers = $sql->num(); + + $aSlots = array('cs' => 0, 'cssold' => 0, 'css' => 0, 'csgo' => 0, 'samp' => 0, 'crmp' => 0, 'mta' => 0, 'mc' => 0); + $aServers = array('cs' => 0, 'cssold' => 0, 'css' => 0, 'csgo' => 0, 'samp' => 0, 'crmp' => 0, 'mta' => 0, 'mc' => 0); + + while($server = $sql->get()) + { + $aSlots[$server['game']] += $server['slots']; + $aServers[$server['game']] += 1; + } + + $sql->query('SELECT SUM(`money`) FROM `logs` WHERE `type`="replenish"'); + $replenish = $sql->get(); + + $sf_list = ''; + + $sql->query('SELECT `id`, `name`, `group`, `lastname`, `ip`, `browser`, `time` FROM `users` WHERE `group`!="user" ORDER BY `id` ASC LIMIT 20'); + while($staff = $sql->get()) + { + $online = $staff['time']+15 > $start_point ? 'text-green">Онлайн' : 'text-red">Офлайн'; + + $group = $staff['group'] == 'admin' ? 'text-red">Администратор' : '">Тех. Поддержка'; + + $sf_list .= ''; + $sf_list .= ''.$staff['id'].''; + $sf_list .= ''.$staff['lastname'].' '.$staff['name'].''; + $sf_list .= ''.$staff['ip'].''; + $sf_list .= ''.$staff['browser'].''; + $sf_list .= ''.sys::today($staff['time']).''; + $sf_list .= ''; + } + + $html->get('main'); + + $html->set('cashback', $html->arr['cashback']); + $html->set('users', $users); + $html->set('servers', $servers); + $html->set('replenish', $replenish['SUM(`money`)']); + $html->set('staff', $sf_list); + + foreach($aSlots as $game => $slots) + $html->set('slots_'.$game, $slots); + + foreach($aServers as $game => $num) + $html->set($game, $num); + + $html->pack('main'); + + $mcache->set($mcache_name, $html->arr['main'], false, 10); + }else + $html->arr['main'] = str_replace('[cashback]', $html->arr['cashback'], $html->arr['main']); +?> \ No newline at end of file diff --git a/system/acp/engine/jobs.php b/system/acp/engine/jobs.php new file mode 100644 index 0000000..61e2497 --- /dev/null +++ b/system/acp/engine/jobs.php @@ -0,0 +1,32 @@ + Вакансии'; + + $aSection = array( + 'index', + 'add', + 'request' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/jobs'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `jobs`'); + $html->set('jobs', $sql->num()); + $sql->query('SELECT `id` FROM `jobs_app`'); + $html->set('jobs_app', $sql->num()); + $html->pack('menu'); + + include(SEC.'jobs/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/letter.php b/system/acp/engine/letter.php new file mode 100644 index 0000000..0aa4635 --- /dev/null +++ b/system/acp/engine/letter.php @@ -0,0 +1,27 @@ + Рассылка новостей'; + + $aSection = array( + 'index', + 'send' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/letter'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $html->pack('menu'); + + include(SEC.'letter/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/logs.php b/system/acp/engine/logs.php new file mode 100644 index 0000000..09677d4 --- /dev/null +++ b/system/acp/engine/logs.php @@ -0,0 +1,33 @@ + Логи операций'; + + $aSection = array( + 'index', + 'buy', + 'extend', + 'boost', + 'cashout', + 'part', + 'search', + 'replenish' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/logs'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $html->pack('menu'); + + include(SEC.'logs/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/news.php b/system/acp/engine/news.php new file mode 100644 index 0000000..7444066 --- /dev/null +++ b/system/acp/engine/news.php @@ -0,0 +1,31 @@ + Управление новостями'; + + $aSection = array( + 'index', + 'add', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/news'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `news`'); + $html->set('news', $sql->num()); + + $html->pack('menu'); + + include(SEC.'news/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/notice.php b/system/acp/engine/notice.php new file mode 100644 index 0000000..f284ca6 --- /dev/null +++ b/system/acp/engine/notice.php @@ -0,0 +1,32 @@ + Управление уведомлениями'; + + $aSection = array( + 'index', + 'add', + 'end', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/notice'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `notice` WHERE `time`>"'.$start_point.'"'); + $html->set('active', $sql->num()); + + $html->pack('menu'); + + include(SEC.'notice/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/pages.php b/system/acp/engine/pages.php new file mode 100644 index 0000000..b39c89b --- /dev/null +++ b/system/acp/engine/pages.php @@ -0,0 +1,28 @@ + Управление старницами'; + + $aSection = array( + 'index', + 'add', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/pages'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $html->pack('menu'); + + include(SEC.'pages/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/promo.php b/system/acp/engine/promo.php new file mode 100644 index 0000000..3b8b9a8 --- /dev/null +++ b/system/acp/engine/promo.php @@ -0,0 +1,36 @@ + Управление акциями'; + + $aSection = array( + 'index', + 'add', + 'end', + 'stats', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/promo'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `promo` WHERE `time`>"'.$start_point.'"'); + $html->set('active', $sql->num()); + + $sql->query('SELECT `id` FROM `promo` WHERE `time`<"'.$start_point.'"'); + $html->set('end', $sql->num()); + + $html->pack('menu'); + + include(SEC.'promo/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/servers.php b/system/acp/engine/servers.php new file mode 100644 index 0000000..049c368 --- /dev/null +++ b/system/acp/engine/servers.php @@ -0,0 +1,69 @@ + Список серверов'; + + $aSection = array( + 'index', + 'cs', + 'cssold', + 'css', + 'csgo', + 'samp', + 'crmp', + 'mta', + 'mc', + 'overdue', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $del = $cfg['server_delete']*86400; + $time = $start_point-$del; + + $html->get('menu', 'sections/servers'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1"'); + $html->set('all', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="cs"'); + $html->set('cs', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="cssold"'); + $html->set('cssold', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="css"'); + $html->set('css', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="csgo"'); + $html->set('csgo', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="samp"'); + $html->set('samp', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="crmp"'); + $html->set('crmp', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="mta"'); + $html->set('mta', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `game`="mc"'); + $html->set('mc', $sql->num()); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`!="-1" AND `time`<"'.$start_point.'" AND `overdue`>"'.$time.'"'); + $html->set('overdue', $sql->num()); + + $html->pack('menu'); + + include(SEC.'servers/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/system.php b/system/acp/engine/system.php new file mode 100644 index 0000000..9e1a897 --- /dev/null +++ b/system/acp/engine/system.php @@ -0,0 +1,57 @@ +query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(isset($url['service']) AND in_array($url['service'], array('apache2', 'nginx', 'mysql', 'unit'))) + { + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с сервером')); + + if($url['service'] == 'unit') + $ssh->set('screen -dmS reboot reboot'); + else + $ssh->set('screen -dmS sr_'.$url['service'].' service '.$url['service'].' restart'); + + sys::outjs(array('s' => 'ok')); + } + + $aData = array( + 'cpu' => '0%', + 'ram' => '0%', + 'hdd' => '0%', + 'apache' => 'Перезагрузить', + 'nginx' => 'Перезагрузить', + 'mysql' => 'Перезагрузить', + 'uptime' => 'unknown', + 'ssh' => 'error' + ); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs($aData); + + $aData['ssh'] = ''; + + $stat_ram = $ssh->get('echo `cat /proc/meminfo | grep MemTotal | awk \'{print $2}\'; cat /proc/meminfo | grep MemFree | awk \'{print $2}\'; cat /proc/meminfo | grep Buffers | awk \'{print $2}\'; cat /proc/meminfo | grep Cached | grep -v SwapCached | awk \'{print $2}\'`'); + $aData['ram'] = ceil(sys::ram_load($stat_ram)).'%'; + + $aData['hdd'] = $ssh->get('df -P / | awk \'{print $5}\' | tail -1'); + + $time = ceil($ssh->get('cat /proc/uptime | awk \'{print $1}\'')); + $aData['uptime'] = sys::uptime_load($time); + + $aData['cpu'] = sys::cpu_load($ssh->get('echo "`ps -A -o pcpu | tail -n+2 | paste -sd+ | bc | awk \'{print $0}\'` `cat /proc/cpuinfo | grep processor | wc -l | awk \'{print $1}\'`"')).'%'; + + sys::outjs($aData); + } + + $html->get('index', 'sections/system'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/engine/tarifs.php b/system/acp/engine/tarifs.php new file mode 100644 index 0000000..284e0b9 --- /dev/null +++ b/system/acp/engine/tarifs.php @@ -0,0 +1,33 @@ + Управление тарифами'; + + $aSection = array( + 'index', + 'add', + 'copy', + 'stats', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/tarifs'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `tarifs`'); + $html->set('tarifs', $sql->num()); + + $html->pack('menu'); + + include(SEC.'tarifs/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/units.php b/system/acp/engine/units.php new file mode 100644 index 0000000..f1e932e --- /dev/null +++ b/system/acp/engine/units.php @@ -0,0 +1,33 @@ + Управление локациями'; + + $aSection = array( + 'index', + 'add', + 'loading', + 'stats', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/units'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `units`'); + $html->set('units', $sql->num()); + + $html->pack('menu'); + + include(SEC.'units/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/users.php b/system/acp/engine/users.php new file mode 100644 index 0000000..86cd61e --- /dev/null +++ b/system/acp/engine/users.php @@ -0,0 +1,44 @@ + Управление пользователями'; + + $aSection = array( + 'index', + 'online', + 'offline', + 'signup', + 'stats', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/users'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `users`'); + $all = $sql->num(); + + $sql->query('SELECT `id` FROM `users` WHERE `time`>"'.($start_point-180).'"'); + $online = $sql->num(); + + $html->set('all', $all); + $html->set('online', $online); + $html->set('offline', $all-$online); + + $sql->query('SELECT `id` FROM `signup`'); + $html->set('signup', $sql->num()); + + $html->pack('menu'); + + include(SEC.'users/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/web.php b/system/acp/engine/web.php new file mode 100644 index 0000000..6395ab4 --- /dev/null +++ b/system/acp/engine/web.php @@ -0,0 +1,62 @@ + Список бесплатных услуг'; + + $aSection = array( + 'index', + 'csbans', + 'csstats', + 'astats', + 'sourcebans', + 'mysql', + 'hosting' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/web'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $sql->query('SELECT `id` FROM `web`'); + $html->set('all', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="amxbans"'); + $html->set('amxbans', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="csbans"'); + $html->set('csbans', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="psychostats"'); + $html->set('psychostats', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="csstats"'); + $html->set('csstats', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="astats"'); + $html->set('astats', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="sourcebans"'); + $html->set('sourcebans', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="rankme"'); + $html->set('rankme', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="mysql"'); + $html->set('mysql', $sql->num()); + + $sql->query('SELECT `id` FROM `web` WHERE `type`="hosting"'); + $html->set('hosting', $sql->num()); + + $html->pack('menu'); + + include(SEC.'web/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/engine/wiki.php b/system/acp/engine/wiki.php new file mode 100644 index 0000000..3b7ebc9 --- /dev/null +++ b/system/acp/engine/wiki.php @@ -0,0 +1,31 @@ + Управление википедией'; + + $aSection = array( + 'addcat', + 'cat', + 'cats', + 'index', + 'add', + 'delete' + ); + + if(!in_array($section, $aSection)) + $section = 'index'; + + $html->get('menu', 'sections/wiki'); + + $html->unit('s_'.$section, true); + + unset($aSection[array_search($section, $aSection)]); + + foreach($aSection as $noactive) + $html->unit('s_'.$noactive); + + $html->pack('menu'); + + include(SEC.'wiki/'.$section.'.php'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/addcat.php b/system/acp/sections/addons/addcat.php new file mode 100644 index 0000000..ab7b2aa --- /dev/null +++ b/system/acp/sections/addons/addcat.php @@ -0,0 +1,45 @@ + 'Необходимо заполнить все поля')); + + foreach($aGames as $game) + { + if(!$aData[$game]) + continue; + + $sql->query('INSERT INTO `plugins_category` set ' + .'`game`="'.$game.'",' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`sort`="'.$aData['sort'].'"'); + } + + sys::outjs(array('s' => 'ok')); + } + + $html->get('addcat', 'sections/addons'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/addpl.php b/system/acp/sections/addons/addpl.php new file mode 100644 index 0000000..2ef23c2 --- /dev/null +++ b/system/acp/sections/addons/addpl.php @@ -0,0 +1,373 @@ +query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$game.'" ORDER BY `sort` ASC'); + while($cat = $sql->get()) + $cats .= ''; + + sys::out($cats); + } + } + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : ''; + $aData['game'] = isset($_POST['game']) ? trim($_POST['game']) : ''; + $aData['cat'] = isset($_POST['category']) ? ceil($_POST['category']) : 0; + $aData['status'] = isset($_POST['status']) ? ceil($_POST['status']) : 0; + $aData['packs'] = isset($_POST['packs']) ? trim($_POST['packs']) : ''; + $aData['desc'] = isset($_POST['desc']) ? trim($_POST['desc']) : ''; + $aData['info'] = isset($_POST['info']) ? trim($_POST['info']) : ''; + $aData['images'] = isset($_POST['images']) ? trim($_POST['images']) : ''; + $aData['incompatible'] = isset($_POST['incompatible']) ? trim($_POST['incompatible']) : ''; + $aData['choice'] = isset($_POST['choice']) ? trim($_POST['choice']) : ''; + $aData['required'] = isset($_POST['required']) ? trim($_POST['required']) : ''; + $aData['update'] = isset($_POST['update']) ? ceil($_POST['update']) : 0; + $aData['delete'] = isset($_POST['delete']) ? ceil($_POST['delete']) : 0; + $aData['aecfg'] = isset($_POST['aecfg']) ? $_POST['aecfg'] : 0; + $aData['sort'] = isset($_POST['sort']) ? ceil($_POST['sort']) : 0; + $aData['price'] = isset($_POST['price']) ? ceil($_POST['price']) : 0; + + $aData['config_files_file'] = isset($_POST['config_files_file']) ? $_POST['config_files_file'] : array(); + $aData['config_files_sort'] = isset($_POST['config_files_sort']) ? $_POST['config_files_sort'] : array(); + $aData['config_clear_file'] = isset($_POST['config_clear_file']) ? $_POST['config_clear_file'] : array(); + $aData['config_clear_text'] = isset($_POST['config_clear_text']) ? $_POST['config_clear_text'] : array(); + $aData['config_write_file'] = isset($_POST['config_write_file']) ? $_POST['config_write_file'] : array(); + $aData['config_write_text'] = isset($_POST['config_write_text']) ? $_POST['config_write_text'] : array(); + $aData['config_write_top'] = isset($_POST['config_write_top']) ? $_POST['config_write_top'] : array(); + $aData['config_write_del_file'] = isset($_POST['config_write_del_file']) ? $_POST['config_write_del_file'] : array(); + $aData['config_write_del_text'] = isset($_POST['config_write_del_text']) ? $_POST['config_write_del_text'] : array(); + $aData['config_write_del_top'] = isset($_POST['config_write_del_top']) ? $_POST['config_write_del_top'] : array(); + $aData['files_delete_file'] = isset($_POST['files_delete_file']) ? $_POST['files_delete_file'] : array(); + + $aData['cfg'] = 0; + + if($aData['name'] == '') + sys::outjs(array('e' => 'Необходимо указать название')); + + if(sys::strlen($aData['name']) > 50) + sys::outjs(array('e' => 'Длина названия не должна превышать 50 символов.')); + + if(!in_array($aData['game'], $aGames)) + sys::outjs(array('e' => 'Необходимо выбрать игру')); + + include(LIB.'zip.php'); + + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$aData['update'].'" LIMIT 1'); + if($sql->num()) + { + $sql->query('INSERT INTO `plugins_update` set `plugin`="0", `name`="'.htmlspecialchars($aData['name']).'", `status`="'.$aData['status'].'", `cfg`="0", `upd`="0"'); + + $id = $aData['update']; + $aData['update'] = $sql->id(); + }else{ + $sql->query('INSERT INTO `plugins` set `name`="'.htmlspecialchars($aData['name']).'", `cat`="'.$aData['cat'].'", `game`="'.$aData['game'].'", `status`="'.$aData['status'].'", `cfg`="0", `upd`="0", `sort`="'.$aData['sort'].'"'); + + $id = $sql->id(); + $aData['update'] = 0; + } + + $edit = array(); + + if(!$aData['update']) + { + if(!move_uploaded_file($_FILES['file']['tmp_name'], FILES.'plugins/install/'.$id.'.zip')) + { + $sql->query('DELETE FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('e' => 'Неудалось загрузить архив')); + } + + $zip = new ZipArchive; + + if($zip->open(FILES.'plugins/install/'.$id.'.zip') !== TRUE) + { + $sql->query('DELETE FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + + unlink(FILES.'plugins/install/'.$id.'.zip'); + + sys::outjs(array('e' => 'Неудалось открыть архив')); + } + + $count = $zip->numFiles; + + $rm = ''; + + for($i = 0; $i < $count; $i+=1) + { + $stat = $zip->statIndex($i); + + $check = count(explode('.', $stat['name'])); + + if($check < 2) + continue; + + $rm .= 'rm '.$stat['name'].';'.PHP_EOL; + + $type = explode('.', $stat['name']); + + if($aData['aecfg'] AND in_array(end($type), $types)) + $edit[] = $stat['name']; + } + + $file = fopen(FILES.'plugins/delete/'.$id.'.rm', "w"); + fputs($file, $rm); + fclose($file); + }else{ + if(!move_uploaded_file($_FILES['new_file']['tmp_name'], FILES.'plugins/install/u'.$aData['update'].'.zip')) + { + $sql->query('DELETE FROM `plugins_update` WHERE `id`="'.$aData['update'].'" LIMIT 1'); + + sys::outjs(array('e' => 'Неудалось загрузить архив')); + } + + if(!move_uploaded_file($_FILES['upd_file']['tmp_name'], FILES.'plugins/update/'.$aData['update'].'.zip')) + { + $sql->query('DELETE FROM `plugins_update` WHERE `id`="'.$aData['update'].'" LIMIT 1'); + + unlink(FILES.'plugins/install/u'.$aData['update'].'.zip'); + + sys::outjs(array('e' => 'Неудалось загрузить архив обновления')); + } + + $zip = new ZipArchive; + + if($zip->open(FILES.'plugins/install/u'.$aData['update'].'.zip') !== TRUE) + { + $sql->query('DELETE FROM `plugins_update` WHERE `id`="'.$aData['update'].'" LIMIT 1'); + + unlink(FILES.'plugins/install/u'.$aData['update'].'.zip'); + unlink(FILES.'plugins/update/'.$aData['update'].'.zip'); + + sys::outjs(array('e' => 'Неудалось открыть архив')); + } + + $count = $zip->numFiles; + + $rm = ''; + + for($i = 0; $i < $count; $i+=1) + { + $stat = $zip->statIndex($i); + + $check = count(explode('.', $stat['name'])); + + if($check < 2) + continue; + + $rm .= 'rm '.$stat['name'].';'.PHP_EOL; + + $type = explode('.', $stat['name']); + + if($aData['aecfg'] AND in_array(end($type), $types)) + $edit[] = $stat['name']; + } + + $file = fopen(FILES.'plugins/delete/u'.$aData['update'].'.rm', "w"); + fputs($file, $rm); + fclose($file); + } + + $aPacks = explode(':', $aData['packs']); + + $spacks = ''; + + foreach($aPacks as $packs) + $spacks .= trim($packs).':'; + + $spacks = isset($spacks{0}) ? substr($spacks, 0, -1) : ''; + + $aData['packs'] = $spacks == '' ? 'all' : $spacks; + + $aIncom = explode(':', $aData['incompatible']); + + $incoms = ''; + + foreach($aIncom as $incom) + { + $incom = trim($incom); + + if(!is_numeric($incom)) + continue; + + $incoms .= intval($incom).':'; + } + + $incoms = isset($incoms{0}) ? substr($incoms, 0, -1) : ''; + + $aData['incompatible'] = $incoms; + + $aChoice = explode(' ', $aData['choice']); + + $choice = ''; + + foreach($aChoice as $chpl) + { + $aChpl = explode(':', $chpl); + + foreach($aChpl as $idchpl) + { + $idchpl = trim($idchpl); + + if(!is_numeric($idchpl)) + continue; + + $choice .= intval($idchpl).':'; + } + + $choice .= ' '; + } + + $choice = isset($choice{0}) ? substr(trim($choice), 0, -1) : ''; + + $aData['choice'] = $choice; + + $aRequi = explode(':', $aData['required']); + + $requis = ''; + + foreach($aRequi as $requi) + { + $requi = trim($requi); + + if(!is_numeric($requi)) + continue; + + $requis .= intval($requi).':'; + } + + $requis = isset($requis{0}) ? substr($requis, 0, -1) : ''; + + $aData['required'] = $requis; + + if(!$aData['aecfg']) + { + $n = 0; + + foreach($aData['config_files_file'] as $i => $file) + { + if($file == '') + continue; + + $n+=1; + + $aData['config_files_sort'][$i] = $aData['config_files_sort'][$i] ? intval($aData['config_files_sort'][$i]) : $n; + + $sql->query('INSERT INTO `plugins_config` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `file`="'.$file.'", `sort`="'.$n.'"'); + } + + if($n) + $aData['cfg'] = 1; + }else{ + $n = 0; + + foreach($edit as $file) + { + $n+=1; + + $sql->query('INSERT INTO `plugins_config` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `file`="'.$file.'", `sort`="'.$n.'"'); + } + + if($n) + $aData['cfg'] = 1; + } + + foreach($aData['config_clear_file'] as $i => $file) + { + if($aData['config_clear_text'][$i] == '' || $file == '') + continue; + + $regex = (string) $aData['config_clear_regex'] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_clear_text'][$i])); + + $sql->query('INSERT INTO `plugins_clear` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `text`="'.$text.'", `file`="'.$file.'", `regex`="'.$regex.'"'); + } + + foreach($aData['config_write_file'] as $i => $file) + { + if($aData['config_write_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_text'][$i])); + + $sql->query('INSERT INTO `plugins_write` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + foreach($aData['config_write_del_file'] as $i => $file) + { + if($aData['config_write_del_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_del_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_del_text'][$i])); + + $sql->query('INSERT INTO `plugins_write_del` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + foreach($aData['files_delete_file'] as $file) + { + if($file == '') + continue; + + $sql->query('INSERT INTO `plugins_delete` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `file`="'.$file.'"'); + } + + if($aData['delete']) + $sql->query('INSERT INTO `plugins_delete_ins` set `plugin`="'.$id.'", `update`="'.$aData['update'].'", `file`="'.$aData['delete'].'"'); + + if($aData['update']) + { + $sql->query('UPDATE `plugins_update` set ' + .'`plugin`="'.$id.'",' + .'`desc`="'.htmlspecialchars($aData['desc']).'",' + .'`info`="'.htmlspecialchars($aData['info']).'",' + .'`images`="'.htmlspecialchars($aData['images']).'",' + .'`incompatible`="'.$aData['incompatible'].'",' + .'`choice`="'.$aData['choice'].'",' + .'`required`="'.$aData['required'].'",' + .'`cfg`="'.$aData['cfg'].'",' + .'`price`="'.$aData['price'].'",' + .'`packs`="'.$aData['packs'].'" WHERE `id`="'.$aData['update'].'"'); + + $sql->query('UPDATE `plugins` set `upd`="'.$aData['update'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('UPDATE `plugins_update` set `upd`="'.$aData['update'].'" WHERE `id`!="'.$aData['update'].'" AND `plugin`="'.$id.'" AND `upd`="0" ORDER BY `id` DESC LIMIT 1'); + }else + $sql->query('UPDATE `plugins` set' + .'`desc`="'.htmlspecialchars($aData['desc']).'",' + .'`info`="'.htmlspecialchars($aData['info']).'",' + .'`images`="'.htmlspecialchars($aData['images']).'",' + .'`incompatible`="'.$aData['incompatible'].'",' + .'`choice`="'.$aData['choice'].'",' + .'`required`="'.$aData['required'].'",' + .'`cfg`="'.$aData['cfg'].'",' + .'`price`="'.$aData['price'].'",' + .'`packs`="'.$aData['packs'].'" WHERE `id`="'.$id.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('addpl', 'sections/addons'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/cats.php b/system/acp/sections/addons/cats.php new file mode 100644 index 0000000..464071f --- /dev/null +++ b/system/acp/sections/addons/cats.php @@ -0,0 +1,26 @@ +query('SELECT `id`, `game`, `name`, `sort` FROM `plugins_category` ORDER BY `game` ASC'); + while($cat = $sql->get($cats)) + { + $sql->query('SELECT `name` FROM `plugins` WHERE `cat`="'.$cat['id'].'"'); + $plugins = $sql->num(); + + $list .= ''; + $list .= ''.$cat['id'].''; + $list .= ''.$cat['name'].''; + $list .= ''.strtoupper($cat['game']).''; + $list .= ''.$plugins.' шт.'; + $list .= ''.$cat['sort'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('cats', 'sections/addons'); + + $html->set('list', $list); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/delete.php b/system/acp/sections/addons/delete.php new file mode 100644 index 0000000..e57a3f4 --- /dev/null +++ b/system/acp/sections/addons/delete.php @@ -0,0 +1,60 @@ +query('DELETE FROM `plugins_config` WHERE `plugin`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_clear` WHERE `plugin`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_write` WHERE `plugin`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_write_del` WHERE `plugin`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_delete` WHERE `plugin`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_delete_ins` WHERE `plugin`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('SELECT `id` FROM `plugins_update` WHERE `plugin`="'.$plugin['plugin'].'"'); + while($update = $sql->get()) + { + unlink(FILES.'plugins/delete/u'.$update['id'].'.rm'); + unlink(FILES.'plugins/delete/'.$update['id'].'.rm'); + unlink(FILES.'plugins/install/u'.$update['id'].'.zip'); + unlink(FILES.'plugins/update/'.$update['id'].'.zip'); + } + + unlink(FILES.'plugins/delete/'.$id.'.rm'); + unlink(FILES.'plugins/install/'.$id.'.zip'); + + $sql->query('DELETE FROM `plugins_update` WHERE `id`="'.$id.'"'); + }elseif($url['type'] == 'update'){ + $sql->query('DELETE FROM `plugins_config` WHERE `update`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_clear` WHERE `update`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_write` WHERE `update`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_write_del` WHERE `update`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_delete` WHERE `update`="'.$id.'"'); + $sql->query('DELETE FROM `plugins_delete_ins` WHERE `update`="'.$id.'" LIMIT 1'); + + unlink(FILES.'plugins/delete/u'.$id.'.rm'); + unlink(FILES.'plugins/install/u'.$id.'.zip'); + unlink(FILES.'plugins/update/'.$id.'.zip'); + + $sql->query('DELETE FROM `plugins_update` WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('SELECT `id` FROM `plugins_update` WHERE `plugin`="'.$plugin['plugin'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $update = $sql->get(); + + $sql->query('UPDATE `plugins` set `upd`="'.$update['id'].'" WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + }else + $sql->query('UPDATE `plugins` set `upd`="0" WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + }else{ + $sql->query('SELECT `id` FROM `plugins` WHERE `cat`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + $sql->query('DELETE FROM `plugins_category` WHERE `id`="'.$id.'" LIMIT 1'); + } + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/index.php b/system/acp/sections/addons/index.php new file mode 100644 index 0000000..4a6ea8e --- /dev/null +++ b/system/acp/sections/addons/index.php @@ -0,0 +1,68 @@ + $sort); + } + + $list = ''; + + $sql->query('SELECT `id` FROM `plugins`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/addons'.$sort_page); + + $status = array(0 => 'Стабильный', 1 => 'Нестабильный', 2 => 'Тестируемый'); + + $plugins = $sql->query('SELECT `id`, `cat`, `game`, `name`, `status` FROM `plugins` '.$sort_sql.' LIMIT '.$aPage['num'].', 20'); + while($plugin = $sql->get($plugins)) + { + $sql->query('SELECT `name` FROM `plugins_category` WHERE `id`="'.$plugin['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $list .= ''; + $list .= ''.$plugin['id'].''; + $list .= ''.$plugin['name'].''; + $list .= ''.$cat['name'].''; + $list .= ''.$status[$plugin['status']].''; + $list .= ''.strtoupper($plugin['game']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/addons'); + + $html->set('sort_id', 'asc'); + $html->set('sort_cat', 'asc'); + $html->set('sort_game', 'asc'); + + if(isset($sort_icon)) + $html->set('sort_'.key($sort_icon), array_shift($sort_icon)); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/addons/plugin.php b/system/acp/sections/addons/plugin.php new file mode 100644 index 0000000..5502fd6 --- /dev/null +++ b/system/acp/sections/addons/plugin.php @@ -0,0 +1,337 @@ +query('SELECT * FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + $plugin = $sql->get(); + + $aGames = array( + 'cs' => 'Counter-Strike: 1.6', + 'cssold' => 'Counter-Strike: Source v34', + 'css' => 'Counter-Strike: Source', + 'csgo' => 'Counter-Strike: Global Offensive', + 'samp' => 'San Andreas Multiplayer', + 'crmp' => 'GTA: Criminal Russia', + 'mta' => 'Multi Theft Auto', + 'mc' => 'Minecraft' + ); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : $plugin['name']; + $aData['cat'] = isset($_POST['category']) ? sys::int($_POST['category']) : $plugin['cat']; + $aData['status'] = isset($_POST['status']) ? sys::int($_POST['status']) : $plugin['status']; + $aData['packs'] = isset($_POST['packs']) ? trim($_POST['packs']) : $plugin['packs']; + $aData['desc'] = isset($_POST['desc']) ? trim($_POST['desc']) : $plugin['desc']; + $aData['info'] = isset($_POST['info']) ? trim($_POST['info']) : $plugin['info']; + $aData['images'] = isset($_POST['images']) ? trim($_POST['images']) : $plugin['images']; + $aData['incompatible'] = isset($_POST['incompatible']) ? trim($_POST['incompatible']) : $plugin['incompatible']; + $aData['choice'] = isset($_POST['choice']) ? trim($_POST['choice']) : $plugin['choice']; + $aData['required'] = isset($_POST['required']) ? trim($_POST['required']) : $plugin['required']; + $aData['update'] = isset($_POST['update']) ? sys::int($_POST['update']) : $plugin['update']; + $aData['delete'] = isset($_POST['delete']) ? sys::int($_POST['delete']) : $plugin['delete']; + $aData['sort'] = isset($_POST['sort']) ? sys::int($_POST['sort']) : $plugin['sort']; + $aData['price'] = isset($_POST['price']) ? ceil($_POST['price']) : $plugin['price']; + + $aData['config_files_file'] = isset($_POST['config_files_file']) ? $_POST['config_files_file'] : array(); + $aData['config_files_sort'] = isset($_POST['config_files_sort']) ? $_POST['config_files_sort'] : array(); + $aData['config_clear_file'] = isset($_POST['config_clear_file']) ? $_POST['config_clear_file'] : array(); + $aData['config_clear_text'] = isset($_POST['config_clear_text']) ? $_POST['config_clear_text'] : array(); + $aData['config_write_file'] = isset($_POST['config_write_file']) ? $_POST['config_write_file'] : array(); + $aData['config_write_text'] = isset($_POST['config_write_text']) ? $_POST['config_write_text'] : array(); + $aData['config_write_top'] = isset($_POST['config_write_top']) ? $_POST['config_write_top'] : array(); + $aData['config_write_del_file'] = isset($_POST['config_write_del_file']) ? $_POST['config_write_del_file'] : array(); + $aData['config_write_del_text'] = isset($_POST['config_write_del_text']) ? $_POST['config_write_del_text'] : array(); + $aData['config_write_del_top'] = isset($_POST['config_write_del_top']) ? $_POST['config_write_del_top'] : array(); + $aData['files_delete_file'] = isset($_POST['files_delete_file']) ? $_POST['files_delete_file'] : array(); + + $aData['cfg'] = 0; + + if($aData['name'] == '') + sys::outjs(array('e' => 'Необходимо указать название')); + + $aPacks = explode(':', $aData['packs']); + + $spacks = ''; + + foreach($aPacks as $packs) + $spacks .= trim($packs).':'; + + $spacks = isset($spacks{0}) ? substr($spacks, 0, -1) : ''; + + $aData['packs'] = $spacks == '' ? 'all' : $spacks; + + $aIncom = explode(':', $aData['incompatible']); + + $incoms = ''; + + foreach($aIncom as $incom) + { + $incom = trim($incom); + + if(!is_numeric($incom)) + continue; + + $incoms .= intval($incom).':'; + } + + $incoms = isset($incoms{0}) ? substr($incoms, 0, -1) : ''; + + $aData['incompatible'] = $incoms; + + $aChoice = explode(' ', $aData['choice']); + + $choice = ''; + + foreach($aChoice as $chpl) + { + $aChpl = explode(':', $chpl); + + foreach($aChpl as $idchpl) + { + $idchpl = trim($idchpl); + + if(!is_numeric($idchpl)) + continue; + + $choice .= intval($idchpl).':'; + } + + $choice .= ' '; + } + + $choice = isset($choice{0}) ? substr(trim($choice), 0, -1) : ''; + + $aData['choice'] = $choice; + + $aRequi = explode(':', $aData['required']); + + $requis = ''; + + foreach($aRequi as $requi) + { + $requi = trim($requi); + + if(!is_numeric($requi)) + continue; + + $requis .= intval($requi).':'; + } + + $requis = isset($requis{0}) ? substr($requis, 0, -1) : ''; + + $aData['required'] = $requis; + + $n = 0; + + $sql->query('DELETE FROM `plugins_config` WHERE `plugin`="'.$id.'" AND `update`="0"'); + + foreach($aData['config_files_file'] as $i => $file) + { + if($file == '') + continue; + + $n+=1; + + $aData['config_files_sort'][$i] = $aData['config_files_sort'][$i] ? intval($aData['config_files_sort'][$i]) : $n; + + $sql->query('INSERT INTO `plugins_config` set `plugin`="'.$id.'", `update`="0", `file`="'.$file.'", `sort`="'.$n.'"'); + } + + if($n) + $aData['cfg'] = 1; + + $sql->query('DELETE FROM `plugins_clear` WHERE `plugin`="'.$id.'" AND `update`="0"'); + + foreach($aData['config_clear_file'] as $i => $file) + { + if($aData['config_clear_text'][$i] == '' || $file == '') + continue; + + $regex = (string) $aData['config_clear_regex'] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_clear_text'][$i])); + + $sql->query('INSERT INTO `plugins_clear` set `plugin`="'.$id.'", `update`="0", `text`="'.$text.'", `file`="'.$file.'", `regex`="'.$regex.'"'); + } + + $sql->query('DELETE FROM `plugins_write` WHERE `plugin`="'.$id.'" AND `update`="0"'); + + foreach($aData['config_write_file'] as $i => $file) + { + if($aData['config_write_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_text'][$i])); + + $sql->query('INSERT INTO `plugins_write` set `plugin`="'.$id.'", `update`="0", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + $sql->query('DELETE FROM `plugins_write_del` WHERE `plugin`="'.$id.'" AND `update`="0"'); + + foreach($aData['config_write_del_file'] as $i => $file) + { + if($aData['config_write_del_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_del_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_del_text'][$i])); + + $sql->query('INSERT INTO `plugins_write_del` set `plugin`="'.$id.'", `update`="0", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + $sql->query('DELETE FROM `plugins_delete` WHERE `plugin`="'.$id.'" AND `update`="0"'); + + foreach($aData['files_delete_file'] as $file) + { + if($file == '') + continue; + + $sql->query('INSERT INTO `plugins_delete` set `plugin`="'.$id.'", `update`="0", `file`="'.$file.'"'); + } + + if($aData['delete']) + { + $sql->query('DELETE FROM `plugins_delete_ins` WHERE `plugin`="'.$id.'" AND `update`="0" LIMIT 1'); + + $sql->query('INSERT INTO `plugins_delete_ins` set `plugin`="'.$id.'", `update`="0", `file`="'.$aData['delete'].'"'); + } + + $sql->query('UPDATE `plugins` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`cat`="'.$aData['cat'].'",' + .'`desc`="'.htmlspecialchars($aData['desc']).'",' + .'`info`="'.htmlspecialchars($aData['info']).'",' + .'`images`="'.htmlspecialchars($aData['images']).'",' + .'`incompatible`="'.$aData['incompatible'].'",' + .'`choice`="'.$aData['choice'].'",' + .'`status`="'.$aData['status'].'",' + .'`required`="'.$aData['required'].'",' + .'`cfg`="'.$aData['cfg'].'",' + .'`price`="'.$aData['price'].'",' + .'`packs`="'.$aData['packs'].'" WHERE `id`="'.$id.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('plugin', 'sections/addons'); + + $html->set('id', $plugin['id']); + $html->set('name', $plugin['name']); + $html->set('game', $aGames[$plugin['game']]); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + $html->set('info', htmlspecialchars_decode($plugin['info'])); + $html->set('images', htmlspecialchars_decode($plugin['images'])); + + $html->set('incompatible', $plugin['incompatible']); + $html->set('choice', $plugin['choice']); + $html->set('required', $plugin['required']); + $html->set('packs', $plugin['packs']); + $html->set('sort', $plugin['sort']); + $html->set('price', $plugin['price']); + + $status = ''; + + $html->set('status', str_replace('"'.$plugin['status'].'">', '"'.$plugin['status'].'" selected>', $status)); + + $cats = ''; + + $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$plugin['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get()) + $cats .= ''; + + $html->set('category', str_replace('"'.$plugin['cat'].'">', '"'.$plugin['cat'].'" selected>', $cats)); + + $config_files_all = ''; + $config_clear_all = ''; + $config_write_all = ''; + $config_write_del_all = ''; + $files_delete_all = ''; + + $sql->query('SELECT `id`, `file`, `sort` FROM `plugins_config` WHERE `plugin`="'.$id.'" AND `update`="0" ORDER BY `sort` ASC'); + while($data = $sql->get()) + { + $config_files_all .= ''; + $config_files_all .= ''; + $config_files_all .= ''; + $config_files_all .= 'Удалить'; + $config_files_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `regex` FROM `plugins_clear` WHERE `plugin`="'.$id.'" AND `update`="0" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $regex = $data['regex'] ? 'checked' : ''; + + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= 'Удалить'; + $config_clear_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `top` FROM `plugins_write` WHERE `plugin`="'.$id.'" AND `update`="0" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $top = $data['top'] ? 'checked' : ''; + + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= 'Удалить'; + $config_write_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `top` FROM `plugins_write_del` WHERE `plugin`="'.$id.'" AND `update`="0" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $top = $data['top'] ? 'checked' : ''; + + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= 'Удалить'; + $config_write_del_all .= ''; + } + + $sql->query('SELECT `id`, `file` FROM `plugins_delete` WHERE `plugin`="'.$id.'" AND `update`="0" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $files_delete_all .= ''; + $files_delete_all .= ''; + $files_delete_all .= 'Удалить'; + $files_delete_all .= ''; + } + + $html->set('config_files_all', $config_files_all); + $html->set('config_clear_all', $config_clear_all); + $html->set('config_write_all', $config_write_all); + $html->set('config_write_del_all', $config_write_del_all); + $html->set('files_delete_all', $files_delete_all); + + $update = ''; + + $status = array(0 => 'Стабильный', 1 => 'Нестабильный', 2 => 'Тестируемый'); + + $sql->query('SELECT `id`, `name`, `status` FROM `plugins_update` WHERE `plugin`="'.$id.'" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $update .= ''; + $update .= ''.$data['name'].''; + $update .= ''.$status[$data['status']].''; + $update .= 'Удалить'; + $update .= ''; + } + + $html->set('update', $update); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/search.php b/system/acp/sections/addons/search.php new file mode 100644 index 0000000..ab13ee8 --- /dev/null +++ b/system/acp/sections/addons/search.php @@ -0,0 +1,75 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if(substr($text, 0, 5) == 'game=') + { + $game = trim(substr($text, 5)); + + if(in_array($game, array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + $plugins = $sql->query('SELECT `id`, `cat`, `game`, `name`, `status` FROM `plugins` WHERE `game`="'.$game.'" ORDER BY `id` ASC'); + }elseif($text{0} == 'i' AND $text{1} == 'd') + $plugins = $sql->query('SELECT `id`, `cat`, `game`, `name`, `status` FROM `plugins` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`desc` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`info` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`packs` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $plugins = $sql->query('SELECT `id`, `cat`, `game`, `name`, `status` FROM `plugins` WHERE '.$like.' ORDER BY `id` ASC LIMIT 10'); + } + + if(!$sql->num($plugins)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + $status = array(0 => 'Стабильный', 2 => 'Нестабильный', 1 => 'Тестируемый'); + + while($plugin = $sql->get($plugins)) + { + $sql->query('SELECT `name` FROM `plugins_category` WHERE `id`="'.$plugin['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $list .= ''; + $list .= ''.$plugin['id'].''; + $list .= ''.$plugin['name'].''; + $list .= ''.$cat['name'].''; + $list .= ''.$status[$plugin['status']].''; + $list .= ''.strtoupper($plugin['game']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/update.php b/system/acp/sections/addons/update.php new file mode 100644 index 0000000..162a066 --- /dev/null +++ b/system/acp/sections/addons/update.php @@ -0,0 +1,322 @@ +query('SELECT * FROM `plugins_update` WHERE `id`="'.$id.'" LIMIT 1'); + $plugin = $sql->get(); + + $aGames = array( + 'cs' => 'Counter-Strike: 1.6', + 'cssold' => 'Counter-Strike: Source v34', + 'css' => 'Counter-Strike: Source', + 'csgo' => 'Counter-Strike: Global Offensive', + 'samp' => 'San Andreas Multiplayer', + 'crmp' => 'GTA: Criminal Russia', + 'mta' => 'Multi Theft Auto', + 'mc' => 'Minecraft' + ); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : $plugin['name']; + $aData['cat'] = isset($_POST['category']) ? sys::int($_POST['category']) : $plugin['cat']; + $aData['status'] = isset($_POST['status']) ? sys::int($_POST['status']) : $plugin['status']; + $aData['packs'] = isset($_POST['packs']) ? trim($_POST['packs']) : $plugin['packs']; + $aData['desc'] = isset($_POST['desc']) ? trim($_POST['desc']) : $plugin['desc']; + $aData['info'] = isset($_POST['info']) ? trim($_POST['info']) : $plugin['info']; + $aData['images'] = isset($_POST['images']) ? trim($_POST['images']) : $plugin['images']; + $aData['incompatible'] = isset($_POST['incompatible']) ? trim($_POST['incompatible']) : $plugin['incompatible']; + $aData['choice'] = isset($_POST['choice']) ? trim($_POST['choice']) : $plugin['choice']; + $aData['required'] = isset($_POST['required']) ? trim($_POST['required']) : $plugin['required']; + $aData['update'] = isset($_POST['update']) ? sys::int($_POST['update']) : $plugin['update']; + $aData['delete'] = isset($_POST['delete']) ? sys::int($_POST['delete']) : $plugin['delete']; + $aData['sort'] = isset($_POST['sort']) ? sys::int($_POST['sort']) : $plugin['sort']; + $aData['price'] = isset($_POST['price']) ? ceil($_POST['price']) : $plugin['price']; + + $aData['config_files_file'] = isset($_POST['config_files_file']) ? $_POST['config_files_file'] : array(); + $aData['config_files_sort'] = isset($_POST['config_files_sort']) ? $_POST['config_files_sort'] : array(); + $aData['config_clear_file'] = isset($_POST['config_clear_file']) ? $_POST['config_clear_file'] : array(); + $aData['config_clear_text'] = isset($_POST['config_clear_text']) ? $_POST['config_clear_text'] : array(); + $aData['config_write_file'] = isset($_POST['config_write_file']) ? $_POST['config_write_file'] : array(); + $aData['config_write_text'] = isset($_POST['config_write_text']) ? $_POST['config_write_text'] : array(); + $aData['config_write_top'] = isset($_POST['config_write_top']) ? $_POST['config_write_top'] : array(); + $aData['config_write_del_file'] = isset($_POST['config_write_del_file']) ? $_POST['config_write_del_file'] : array(); + $aData['config_write_del_text'] = isset($_POST['config_write_del_text']) ? $_POST['config_write_del_text'] : array(); + $aData['config_write_del_top'] = isset($_POST['config_write_del_top']) ? $_POST['config_write_del_top'] : array(); + $aData['files_delete_file'] = isset($_POST['files_delete_file']) ? $_POST['files_delete_file'] : array(); + + $aData['cfg'] = 0; + + if($aData['name'] == '') + sys::outjs(array('e' => 'Необходимо указать название')); + + $aPacks = explode(':', $aData['packs']); + + $spacks = ''; + + foreach($aPacks as $packs) + { + $packs = trim($packs); + + $spacks .= intval($packs).':'; + } + + $spacks = isset($spacks{0}) ? substr($spacks, 0, -1) : ''; + + $aData['packs'] = $spacks == '' ? $spacks : 'all'; + + $aIncom = explode(':', $aData['incompatible']); + + $incoms = ''; + + foreach($aIncom as $incom) + { + $incom = trim($incom); + + if(!is_numeric($incom)) + continue; + + $incoms .= intval($incom).':'; + } + + $incoms = isset($incoms{0}) ? substr($incoms, 0, -1) : ''; + + $aData['incompatible'] = $incoms; + + $aChoice = explode(' ', $aData['choice']); + + $choice = ''; + + foreach($aChoice as $chpl) + { + $aChpl = explode(':', $chpl); + + foreach($aChpl as $idchpl) + { + $idchpl = trim($idchpl); + + if(!is_numeric($idchpl)) + continue; + + $choice .= intval($idchpl).':'; + } + + $choice .= ' '; + } + + $choice = isset($choice{0}) ? substr(trim($choice), 0, -1) : ''; + + $aData['choice'] = $choice; + + $aRequi = explode(':', $aData['required']); + + $requis = ''; + + foreach($aRequi as $requi) + { + $requi = trim($requi); + + if(!is_numeric($requi)) + continue; + + $requis .= intval($requi).':'; + } + + $requis = isset($requis{0}) ? substr($requis, 0, -1) : ''; + + $aData['required'] = $requis; + + $n = 0; + + $sql->query('DELETE FROM `plugins_config` WHERE `update`="'.$id.'"'); + + foreach($aData['config_files_file'] as $i => $file) + { + if($file == '') + continue; + + $n+=1; + + $aData['config_files_sort'][$i] = $aData['config_files_sort'][$i] ? intval($aData['config_files_sort'][$i]) : $n; + + $sql->query('INSERT INTO `plugins_config` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `file`="'.$file.'", `sort`="'.$n.'"'); + } + + if($n) + $aData['cfg'] = 1; + + $sql->query('DELETE FROM `plugins_clear` WHERE `update`="'.$id.'"'); + + foreach($aData['config_clear_file'] as $i => $file) + { + if($aData['config_clear_text'][$i] == '' || $file == '') + continue; + + $regex = (string) $aData['config_clear_regex'] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_clear_text'][$i])); + + $sql->query('INSERT INTO `plugins_clear` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `text`="'.$text.'", `file`="'.$file.'", `regex`="'.$regex.'"'); + } + + $sql->query('DELETE FROM `plugins_write` WHERE `update`="'.$id.'"'); + + foreach($aData['config_write_file'] as $i => $file) + { + if($aData['config_write_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_text'][$i])); + + $sql->query('INSERT INTO `plugins_write` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + $sql->query('DELETE FROM `plugins_write_del` WHERE `update`="'.$id.'"'); + + foreach($aData['config_write_del_file'] as $i => $file) + { + if($aData['config_write_del_text'][$i] == '' || $file == '') + continue; + + $top = (string) $aData['config_write_del_top'][$i] == 'on' ? 1 : 0; + + $text = htmlspecialchars(trim($aData['config_write_del_text'][$i])); + + $sql->query('INSERT INTO `plugins_write_del` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `text`="'.$text.'", `file`="'.$file.'", `top`="'.$top.'"'); + } + + $sql->query('DELETE FROM `plugins_delete` WHERE `update`="'.$id.'"'); + + foreach($aData['files_delete_file'] as $file) + { + if($file == '') + continue; + + $sql->query('INSERT INTO `plugins_delete` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `file`="'.$file.'"'); + } + + if($aData['delete']) + { + $sql->query('DELETE FROM `plugins_delete_ins` WHERE `update`="'.$id.'" LIMIT 1'); + + $sql->query('INSERT INTO `plugins_delete_ins` set `plugin`="'.$plugin['plugin'].'", `update`="'.$id.'", `file`="'.$aData['delete'].'"'); + } + + $sql->query('UPDATE `plugins_update` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`desc`="'.htmlspecialchars($aData['desc']).'",' + .'`info`="'.htmlspecialchars($aData['info']).'",' + .'`images`="'.htmlspecialchars($aData['images']).'",' + .'`incompatible`="'.$aData['incompatible'].'",' + .'`choice`="'.$aData['choice'].'",' + .'`required`="'.$aData['required'].'",' + .'`status`="'.$aData['status'].'",' + .'`cfg`="'.$aData['cfg'].'",' + .'`price`="'.$aData['price'].'",' + .'`packs`="'.$aData['packs'].'" WHERE `id`="'.$id.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('update', 'sections/addons'); + + $html->set('id', $plugin['id']); + $html->set('plugin', $plugin['plugin']); + $html->set('name', $plugin['name']); + $html->set('game', $aGames[$plugin['game']]); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + $html->set('info', htmlspecialchars_decode($plugin['info'])); + $html->set('images', htmlspecialchars_decode($plugin['images'])); + + $html->set('incompatible', $plugin['incompatible']); + $html->set('choice', $plugin['choice']); + $html->set('required', $plugin['required']); + $html->set('packs', $plugin['packs']); + $html->set('sort', $plugin['sort']); + $html->set('price', $plugin['price']); + + $status = ''; + + $html->set('status', str_replace('"'.$plugin['status'].'">', '"'.$plugin['status'].'" selected>', $status)); + + $sql->query('SELECT `name` FROM `plugins_category` WHERE `id`="'.$plugin['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $html->set('category', $cat['name']); + + $config_files_all = ''; + $config_clear_all = ''; + $config_write_all = ''; + $config_write_del_all = ''; + $files_delete_all = ''; + + $sql->query('SELECT `id`, `file`, `sort` FROM `plugins_config` WHERE `update`="'.$id.'" ORDER BY `sort` ASC'); + while($data = $sql->get()) + { + $config_files_all .= ''; + $config_files_all .= ''; + $config_files_all .= ''; + $config_files_all .= 'Удалить'; + $config_files_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `regex` FROM `plugins_clear` WHERE `update`="'.$id.'" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $regex = $data['regex'] ? 'checked' : ''; + + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= ''; + $config_clear_all .= 'Удалить'; + $config_clear_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `top` FROM `plugins_write` WHERE `update`="'.$id.'" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $top = $data['top'] ? 'checked' : ''; + + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= ''; + $config_write_all .= 'Удалить'; + $config_write_all .= ''; + } + + $sql->query('SELECT `id`, `text`, `file`, `top` FROM `plugins_write_del` WHERE `update`="'.$id.'" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $top = $data['top'] ? 'checked' : ''; + + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= ''; + $config_write_del_all .= 'Удалить'; + $config_write_del_all .= ''; + } + + $sql->query('SELECT `id`, `file` FROM `plugins_delete` WHERE `update`="'.$id.'" ORDER BY `id` ASC'); + while($data = $sql->get()) + { + $files_delete_all .= ''; + $files_delete_all .= ''; + $files_delete_all .= 'Удалить'; + $files_delete_all .= ''; + } + + $html->set('config_files_all', $config_files_all); + $html->set('config_clear_all', $config_clear_all); + $html->set('config_write_all', $config_write_all); + $html->set('config_write_del_all', $config_write_del_all); + $html->set('files_delete_all', $files_delete_all); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/addons/updmp.php b/system/acp/sections/addons/updmp.php new file mode 100644 index 0000000..ea7cd11 --- /dev/null +++ b/system/acp/sections/addons/updmp.php @@ -0,0 +1,78 @@ +query('SELECT `name` FROM `maps` WHERE `unit`="'.$unit.'" AND `game`="'.$game.'" ORDER BY `id` ASC'); + + $all = 'Общее число карт: '.$sql->num().' шт.'.PHP_EOL; + + while($map = $sql->get()) + $maps .= $map['name'].PHP_EOL; + + $maps = $maps == '' ? 'В базе нет карт' : $all.$maps.$all; + + sys::out($maps); + } + + if($go) + { + $unit = isset($url['unit']) ? sys::int($url['unit']) : sys::outjs(array('e' => 'Необходимо выбрать локацию')); + $game = isset($url['game']) ? $url['game'] : sys::outjs(array('e' => 'Необходимо выбрать игру')); + + if(!$unit) + sys::outjs(array('e' => 'Необходимо выбрать локацию')); + + if(!in_array($game, array('cs', 'cssold', 'css', 'csgo'))) + sys::outjs(array('e' => 'Необходимо выбрать игру')); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `id`, `passwd`, `address` FROM `units` WHERE `id`="'.$unit.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена')); + + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с локацией')); + + $sql->query('DELETE FROM `maps` WHERE `unit`="'.$unit['id'].'" AND `game`="'.$game.'"'); + + $maps = $ssh->get('cd /path/maps/'.$game.' && ls | grep .bsp | grep -v .bsp.'); + + $aMaps = explode("\n", $maps); + + array_pop($aMaps); + + foreach($aMaps as $map) + { + $name = array_shift(explode('.', $map)); + + $sql->query('INSERT INTO `maps` set `unit`="'.$unit['id'].'", `game`="'.$game.'", `name`="'.$name.'"'); + } + + sys::outjs(array('s' => 'ok')); + } + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $html->get('updmp', 'sections/addons'); + + $html->set('units', $units); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/boost/index.php b/system/acp/sections/boost/index.php new file mode 100644 index 0000000..395f162 --- /dev/null +++ b/system/acp/sections/boost/index.php @@ -0,0 +1,81 @@ +query('SELECT `id` FROM `boost`'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/boost'); + + $sql->query('SELECT * FROM `boost` ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= 'Покупка кругов: '.$log['circles'].' шт. на сайте: '.$aBoost['cs'][$log['site']]['site'].', списана сумма: '.$log['money'].' '.$cfg['currency'].''; + $list .= 'USER_'.$log['user'].''; + $list .= 'SERVER_'.$log['server'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $month = date('n', $start_point)-1; + + if(!$month) + $month = 12; + + $aData = $mcache->get('data_boost_all'); + + if(!is_array($aData)) + { + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost`'); + $data = $sql->get(); + + $aData['all_num'] = (int) $data['SUM(`circles`)']; + $aData['all_sum'] = (int) $data['SUM(`money`)']; + + $now = $start_point-(date('d', $start_point)*86400); + + $old = $start_point-(params::$aDayMonth[$month]*86400); + + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost` WHERE `date`>="'.$old.'" AND date<"'.$now.'"'); + $data = $sql->get(); + + $aData['old_num'] = (int) $data['SUM(`circles`)']; + $aData['old_sum'] = (int) $data['SUM(`money`)']; + + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost` WHERE `date`>="'.$now.'"'); + $data = $sql->get(); + + $aData['now_num'] = (int) $data['SUM(`circles`)']; + $aData['now_sum'] = (int) $data['SUM(`money`)']; + + $mcache->set('data_boost_all', $aData, false, 60); + } + + $html->get('index', 'sections/boost'); + + $html->set('list', $list); + + $html->set('month_old', params::$aNameMonth[$month]); + $html->set('month_now', params::$aNameMonth[date('n', $start_point)]); + + $html->set('all_num', $aData['all_num']); + $html->set('all_sum', $aData['all_sum']); + $html->set('old_num', $aData['old_num']); + $html->set('old_sum', $aData['old_sum']); + $html->set('now_num', $aData['now_num']); + $html->set('now_sum', $aData['now_sum']); + + $html->set('cur', $cfg['currency']); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/boost/search.php b/system/acp/sections/boost/search.php new file mode 100644 index 0000000..8498976 --- /dev/null +++ b/system/acp/sections/boost/search.php @@ -0,0 +1,77 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + $check = explode('=', $text); + + if(in_array($check[0], array('server', 'user'))) + { + $val = trim($check[1]); + + switch($check[0]) + { + case 'server': + $sql->query('SELECT * FROM `boost` WHERE `server`="'.sys::int($val).'" ORDER BY `id` DESC'); + break; + + case 'user': + $sql->query('SELECT * FROM `boost` WHERE `user`="'.sys::int($val).'" ORDER BY `id` DESC'); + } + }elseif($text{0} == 'i' AND $text{1} == 'd') + $sql->query('SELECT * FROM `boost` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`site` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`circles` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`money` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $sql->query('SELECT * FROM `boost` WHERE '.$like.' ORDER BY `id` DESC LIMIT 40'); + } + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= 'Покупка кругов: '.$log['circles'].' шт. на сайте: '.$aBoost['cs'][$log['site']]['site'].', списана сумма: '.$log['money'].' '.$cfg['currency'].''; + $list .= 'USER_'.$log['user'].''; + $list .= 'SERVER_'.$log['server'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/boost/service.php b/system/acp/sections/boost/service.php new file mode 100644 index 0000000..d76e43e --- /dev/null +++ b/system/acp/sections/boost/service.php @@ -0,0 +1,81 @@ +query('SELECT `id` FROM `boost` WHERE `site`="'.$section.'"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/boost/section/'.$section); + + $sql->query('SELECT * FROM `boost` WHERE `site`="'.$section.'" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= 'Покупка кругов: '.$log['circles'].' шт. на сайте: '.$aBoost['cs'][$log['site']]['site'].', списана сумма: '.$log['money'].' '.$cfg['currency'].''; + $list .= 'USER_'.$log['user'].''; + $list .= 'SERVER_'.$log['server'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $month = date('n', $start_point)-1; + + if(!$month) + $month = 12; + + $aData = $mcache->get('data_boost_'.$section); + + if(!is_array($aData)) + { + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost` WHERE `site`="'.$section.'"'); + $data = $sql->get(); + + $aData['all_num'] = (int) $data['SUM(`circles`)']; + $aData['all_sum'] = (int) $data['SUM(`money`)']; + + $now = $start_point-(date('d', $start_point)*86400); + + $old = $start_point-(params::$aDayMonth[$month]*86400); + + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost` WHERE `site`="'.$section.'" AND `date`>="'.$old.'" AND date<"'.$now.'"'); + $data = $sql->get(); + + $aData['old_num'] = (int) $data['SUM(`circles`)']; + $aData['old_sum'] = (int) $data['SUM(`money`)']; + + $sql->query('SELECT SUM(`circles`), SUM(`money`) FROM `boost` WHERE `site`="'.$section.'" AND `date`>="'.$now.'"'); + $data = $sql->get(); + + $aData['now_num'] = (int) $data['SUM(`circles`)']; + $aData['now_sum'] = (int) $data['SUM(`money`)']; + + $mcache->set('data_boost_'.$section, $aData, false, 60); + } + + $html->get('index', 'sections/boost'); + + $html->set('list', $list); + + $html->set('month_old', params::$aNameMonth[$month]); + $html->set('month_now', params::$aNameMonth[date('n', $start_point)]); + + $html->set('all_num', $aData['all_num']); + $html->set('all_sum', $aData['all_sum']); + $html->set('old_num', $aData['old_num']); + $html->set('old_sum', $aData['old_sum']); + $html->set('now_num', $aData['now_num']); + $html->set('now_sum', $aData['now_sum']); + + $html->set('cur', $cfg['currency']); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/control/delete.php b/system/acp/sections/control/delete.php new file mode 100644 index 0000000..799b9fd --- /dev/null +++ b/system/acp/sections/control/delete.php @@ -0,0 +1,8 @@ +query('UPDATE `control` set `user`="-1", `status`="overdue", `time`="0", `overdue`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/control/index.php b/system/acp/sections/control/index.php new file mode 100644 index 0000000..6f34916 --- /dev/null +++ b/system/acp/sections/control/index.php @@ -0,0 +1,54 @@ + 'Работает', + 'reboot' => 'перезагружается', + 'error' => 'Не отвечает', + 'install' => 'Настраивается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $sql->query('SELECT `id` FROM `control` WHERE `user`!="-1"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/control'); + + $sql->query('SELECT `id`, `user`, `address`, `time`, `date`, `status`, `limit`, `price` FROM `control` WHERE `user`!="-1" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($ctrl = $sql->get()) + { + $list .= ''; + $list .= ''.$ctrl['id'].''; + $list .= ''.$ctrl['address'].''; + $list .= ''.date('d.m.Y - H:i:s', $ctrl['date']).''; + $list .= ''.$ctrl['limit'].' шт.'; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$ctrl['user'].''; + $list .= ''.$status[$ctrl['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $ctrl['time']).''; + $list .= ''.$ctrl['price'].' '.$cfg['currency'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/control'); + $html->set('list', $list); + $html->set('url_search', $url_search); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/control/overdue.php b/system/acp/sections/control/overdue.php new file mode 100644 index 0000000..13ce562 --- /dev/null +++ b/system/acp/sections/control/overdue.php @@ -0,0 +1,35 @@ +query('SELECT `id`, `user`, `address`, `overdue`, `date`, `status`, `limit`, `price` FROM `control` WHERE `user`!="-1" AND `time`<"'.$start_point.'" AND `overdue`>"'.$start_point.'" ORDER BY `id` ASC'); + while($ctrl = $sql->get()) + { + $list .= ''; + $list .= ''.$ctrl['id'].''; + $list .= ''.$ctrl['address'].''; + $list .= ''.date('d.m.Y - H:i:s', $ctrl['date']).''; + $list .= ''.$ctrl['limit'].' шт.'; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$ctrl['user'].''; + $list .= ''.$status[$ctrl['status']].''; + $list .= 'Удаление через: '.sys::date('min', $ctrl['overdue']+$cfg['control_delete']*86400).''; + $list .= ''.$ctrl['price'].' '.$cfg['currency'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/control'); + $html->set('list', $list); + $html->set('pages', ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/control/search.php b/system/acp/sections/control/search.php new file mode 100644 index 0000000..48907c9 --- /dev/null +++ b/system/acp/sections/control/search.php @@ -0,0 +1,103 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + $select = '`id`, `user`, `address`, `time`, `date`, `status`, `limit`, `price` FROM `control` WHERE `user`!="-1" AND'; + + $check = explode('=', $text); + + if(in_array($check[0], array('limit', 'price', 'user', 'status'))) + { + $val = trim($check[1]); + + switch($check[0]) + { + case 'limit': + $ctrls = $sql->query('SELECT '.$select.' `limit`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'price': + $ctrls = $sql->query('SELECT '.$select.' `price`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'ctrls': + $ctrl = $sql->query('SELECT '.$select.' `user`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'status': + if(in_array($val, array('working', 'error', 'reboot', 'overdue', 'blocked', 'install'))) + $ctrls = $sql->query('SELECT '.$select.' `status`="'.$val.'" ORDER BY `id` ASC'); + } + }elseif($text{0} == 'i' AND $text{1} == 'd') + $ctrls = $sql->query('SELECT '.$select.' `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`address` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $ctrls = $sql->query('SELECT '.$select.' ('.$like.') ORDER BY `id` ASC'); + } + + if(!$sql->num($ctrls)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $status = array( + 'working' => 'Работает', + 'reboot' => 'перезагружается', + 'error' => 'Не отвечает', + 'install' => 'Настраивается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $list = ''; + + while($ctrl = $sql->get($ctrls)) + { + $list .= ''; + $list .= ''.$ctrl['id'].''; + $list .= ''.$ctrl['address'].''; + $list .= ''.date('d.m.Y - H:i:s', $ctrl['date']).''; + $list .= ''.$ctrl['limit'].' шт.'; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$ctrl['user'].''; + $list .= ''.$status[$ctrl['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $ctrl['time']).''; + $list .= ''.$ctrl['price'].' '.$cfg['currency'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/control/server.php b/system/acp/sections/control/server.php new file mode 100644 index 0000000..2cc4d2c --- /dev/null +++ b/system/acp/sections/control/server.php @@ -0,0 +1,109 @@ +query('SELECT `time`, `overdue` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + if($ctrl['time'] > $start_point AND $ctrl['overdue']) + $sql->query('UPDATE `control` set `overdue`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('SELECT * FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + if($go) + { + if(isset($url['type']) AND in_array($url['type'], array('overdue', 'block', 'tarif'))) + { + if($url['type'] != 'tarif') + { + $time = isset($_POST['time']) ? trim($_POST['time']) : sys::outjs(array('e' => 'Необходимо указать дату.')); + + $date = sys::checkdate($time); + } + + switch($url['type']) + { + case 'overdue': + if($ctrl['time'] > $start_point) + sys::outjs(array('e' => 'Игровой сервер должен быть просрочен.')); + + $sql->query('UPDATE `control` set `overdue`="'.$date.'" WHERE `id`="'.$id.'" LIMIT 1'); + break; + + case 'block': + if($ctrl['status'] != ('off' || 'overdue')) + sys::outjs(array('e' => 'Игровой сервер должен быть выключен.')); + + if($date < $start_point) + $sql->query('UPDATE `control` set `status`="off", `block`="0" WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('UPDATE `control` set `status`="blocked", `block`="'.$date.'" WHERE `id`="'.$id.'" LIMIT 1'); + } + + sys::outjs(array('s' => 'ok')); + } + + $aData = array(); + + $aData['user'] = isset($_POST['user']) ? sys::int($_POST['user']) : $ctrl['user']; + $aData['address'] = isset($_POST['address']) ? trim($_POST['address']) : $ctrl['address']; + $aData['passwd'] = isset($_POST['passwd']) ? trim($_POST['passwd']) : $ctrl['passwd']; + $aData['time'] = isset($_POST['time']) ? trim($_POST['time']) : $ctrl['time']; + $aData['sql_passwd'] = isset($_POST['sql_passwd']) ? trim($_POST['sql_passwd']) : $ctrl['sql_passwd']; + $aData['sql_ftp'] = isset($_POST['sql_ftp']) ? trim($_POST['sql_ftp']) : $ctrl['sql_ftp']; + $aData['limit'] = isset($_POST['sql_ftp']) ? sys::int($_POST['limit']) : $ctrl['limit']; + $aData['price'] = isset($_POST['price']) ? sys::int($_POST['price']) : $ctrl['price']; + + include(LIB.'ssh.php'); + + if(sys::valid($aData['address'].':22', 'other', $aValid['address'])) + $aData['address'] = $ctrl['address']; + + if(sys::valid($aData['sql_passwd'], 'en')) + $aData['sql_passwd'] = $ctrl['sql_passwd']; + + if(sys::valid($aData['sql_ftp'], 'en')) + $aData['sql_ftp'] = $ctrl['sql_ftp']; + + if(!$ssh->auth($aData['passwd'], $aData['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с локацией')); + + if($ctrl['user'] != $aData['user']) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден.')); + } + + $aData['time'] = sys::checkdate($aData['time']); + + $sql->query('UPDATE `control` set ' + .'`user`="'.$aData['user'].'",' + .'`address`="'.$aData['address'].'",' + .'`passwd`="'.$aData['passwd'].'",' + .'`time`="'.$aData['time'].'",' + .'`sql_passwd`="'.$aData['sql_passwd'].'",' + .'`sql_ftp`="'.$aData['sql_ftp'].'",' + .'`limit`="'.$aData['limit'].'",' + .'`price`="'.$aData['price'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('server', 'sections/control'); + $html->set('id', $id); + $html->set('user', $ctrl['user']); + $html->set('address', $ctrl['address']); + $html->set('passwd', $ctrl['passwd']); + $html->set('sql_passwd', $ctrl['sql_passwd']); + $html->set('sql_ftp', $ctrl['sql_ftp']); + $html->set('limit', $ctrl['limit']); + $html->set('price', $ctrl['price']); + $html->set('time', date('d/m/Y H:i', $ctrl['time'])); + $html->set('date', date('d.m.Y - H:i:s', $ctrl['date'])); + $html->set('overdue', $ctrl['overdue'] == 0 ? 'Установить' : date('d/m/Y H:i', $ctrl['overdue'])); + $html->set('block', $ctrl['block'] == 0 ? 'Заблокировать' : date('d/m/Y H:i', $ctrl['block'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/jobs/add.php b/system/acp/sections/jobs/add.php new file mode 100644 index 0000000..736ee06 --- /dev/null +++ b/system/acp/sections/jobs/add.php @@ -0,0 +1,28 @@ + 'Необходимо заполнить все поля!')); + + $sql->query('INSERT INTO `jobs` set' + .'`name`="'.$aData['name'].'",' + .'`job`="'.$aData['job'].'",' + .'`desc`="'.$aData['desc'].'",' + .'`status`="'.$aData['status'].'",' + .'`date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('add', 'sections/jobs'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/jobs/edit.php b/system/acp/sections/jobs/edit.php new file mode 100644 index 0000000..f154941 --- /dev/null +++ b/system/acp/sections/jobs/edit.php @@ -0,0 +1,39 @@ +query('SELECT * FROM `jobs` WHERE `id`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + header('Location: '.$cfg['http'].'acp/jobs'); + $jobs = $sql->get(); + + if($go) + { + $aData = []; + + $data = ['name', 'job', 'desc', 'status']; + foreach($data as $idata) + $aData[$idata] = isset($_POST[$idata]) ? $_POST[$idata] : ''; + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля!')); + + $sql->query('UPDATE `jobs` set' + .'`name`="'.$aData['name'].'",' + .'`job`="'.$aData['job'].'",' + .'`desc`="'.$aData['desc'].'",' + .'`status`="'.$aData['status'].'",' + .'`date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('edit', 'sections/jobs'); + $status = $jobs['status'] ? '' : ''; + $html->set('status', $status); + + $data = ['id', 'name', 'job', 'desc']; + foreach($data as $idata) + $html->set($idata, $jobs[$idata]); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/jobs/index.php b/system/acp/sections/jobs/index.php new file mode 100644 index 0000000..b4f5052 --- /dev/null +++ b/system/acp/sections/jobs/index.php @@ -0,0 +1,38 @@ +query('SELECT * FROM `jobs` ORDER BY `id` ASC'); + while($jobs = $sql->get()) + { + $status = [ + '1' => 'Доступна', + '0' => 'Недоступна' + ]; + + $list .= ''; + $list .= ''.$jobs['id'].''; + $list .= ''.$jobs['name'].''; + $list .= ''.$jobs['job'].''; + $list .= ''.$jobs['desc'].''; + $list .= ''.$status[$jobs['status']].''; + $list .= ''.sys::today($jobs['date']).''; + $list .= '
    удалить
    '; + $list .= 'Изменить'; + $list .= ''; + } + + if(isset($url['del'])) + { + $sql->query('DELETE FROM `jobs` WHERE `id`="'.$url['del'].'" LIMIT 1'); + sys::outjs(array('s' => 'ok')); + } + + $html->get('index', 'sections/jobs'); + $html->set('list', $list); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/jobs/request.php b/system/acp/sections/jobs/request.php new file mode 100644 index 0000000..f4a61ae --- /dev/null +++ b/system/acp/sections/jobs/request.php @@ -0,0 +1,64 @@ +query('SELECT * FROM `jobs_app` WHERE `id`="'.$id.'" LIMIT 1'); + $jobs_app = $sql->get(); + + if($go) + { + $aData = []; + + $data = ['user', 'text', 'contact', 'job']; + foreach($data as $idata) + $aData[$idata] = isset($_POST[$idata]) ? $_POST[$idata] : ''; + + $sql->query('UPDATE `jobs_app` set' + .'`user`="'.$aData['user'].'",' + .'`text`="'.$aData['text'].'",' + .'`contact`="'.$aData['contact'].'",' + .'`job`="'.$aData['job'].'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('request_edit', 'sections/jobs'); + $data = ['id', 'user', 'text', 'contact', 'job']; + foreach($data as $idata) + $html->set($idata, $jobs_app[$idata]); + $html->pack('main'); + }else{ + $sql->query('SELECT * FROM `jobs_app` ORDER BY `id` ASC'); + while($jobs = $sql->get()) + { + $status = [ + '1' => 'Доступна', + '0' => 'Недоступна' + ]; + + $list .= ''; + $list .= ''.$jobs['id'].''; + $list .= 'user_'.$jobs['user'].''; + $list .= ''.sys::strlen($jobs['text']) > 0 ? ''.$jobs['text'].'' : 'Ответить'.''; + $list .= ''.$jobs['contact'].''; + $list .= 'job_'.$jobs['job'].''; + $list .= ''.sys::today($jobs['date']).''; + $list .= '
    удалить
    '; + $list .= 'Изменить'; + $list .= ''; + + if(isset($url['del'])) + { + $sql->query('DELETE FROM `jobs_app` WHERE `id`="'.$url['del'].'" LIMIT 1'); + sys::outjs(array('s' => 'ok')); + + } + } + + $html->get('request', 'sections/jobs'); + $html->set('list', $list); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/letter/index.php b/system/acp/sections/letter/index.php new file mode 100644 index 0000000..ca0486a --- /dev/null +++ b/system/acp/sections/letter/index.php @@ -0,0 +1,25 @@ + 'Пользователь', 'support' => 'Тех.поддержка', 'admin' => 'Администратор'); + $list = ''; + + $sql->query('SELECT `id`, `login`, `mail`, `group`, `name`, `lastname`, `patronymic`, `balance`, `time` FROM `users` WHERE `notice_news`="1" ORDER BY `id` ASC'); + while($us = $sql->get()) + { + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''.$us['mail'].''; + $list .= ''.$us['balance'].' '.$cfg['currency'].''; + $list .= ''.sys::today($us['time']).''; + $list .= ''; + } + + $html->get('index', 'sections/letter'); + + $html->set('list', $list); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/letter/send.php b/system/acp/sections/letter/send.php new file mode 100644 index 0000000..baecdc6 --- /dev/null +++ b/system/acp/sections/letter/send.php @@ -0,0 +1,54 @@ + 'Необходимо указать заголовок')); + $aData['text'] = isset($_POST['text']) ? trim($_POST['text']) : sys::outjs(array('e' => 'Необходимо указать сообщение')); + + $aData['users'] = isset($_POST['users']) ? $_POST['users'] : sys::outjs(array('e' => 'Необходимо указать получателей')); + + if($aData['title'] == '' || $aData['text'] == '') + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + if(!is_array($aData['users']) || !count($aData['users'])) + sys::outjs(array('e' => 'Необходимо указать минимум одного получателя')); + + $noletter = ''; + + include(LIB.'smtp.php'); + + foreach($aData['users'] as $id => $cheked) + { + if($cheked != 'on') + continue; + + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.sys::int($id).'" LIMIT 1'); + $us = $sql->get(); + + $tpl = file_get_contents(DATA.'mail.ini', "r"); + + $text = str_replace( + array('[name]', '[text]', '[http]', '[img]', '[css]'), + array($cfg['name'], $aData['text'], $cfg['http'], $cfg['http'].'template/images/', $cfg['http'].'template/css/'), + $tpl + ); + + $smtp = new smtp($cfg['smtp_login'], $cfg['smtp_passwd'], $cfg['smtp_url'], $cfg['smtp_mail'], 465); + + $headers = "MIME-Version: 1.0\r\n"; + $headers .= "Content-type: text/html; charset=utf-8\r\n"; + $headers .= "From: ".$cfg['smtp_name']." <".$cfg['smtp_mail'].">\r\n"; + + if(!$smtp->send($us['mail'], strip_tags($aData['title']), $text, $headers)) + $noletter .= '

    '.$us['mail'].'

    '; + } + + if($noletter == '') + $noletter = 'отправлено всем.'; + + sys::outjs(array('s' => $noletter)); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/buy.php b/system/acp/sections/logs/buy.php new file mode 100644 index 0000000..a1deb10 --- /dev/null +++ b/system/acp/sections/logs/buy.php @@ -0,0 +1,32 @@ +query('SELECT `id` FROM `logs` WHERE `type`="buy"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs'); + + $sql->query('SELECT `id`, `user`, `text`, `date`, `money` FROM `logs` WHERE `type`="buy" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $html->get('logs', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/cashout.php b/system/acp/sections/logs/cashout.php new file mode 100644 index 0000000..3287162 --- /dev/null +++ b/system/acp/sections/logs/cashout.php @@ -0,0 +1,32 @@ +query('SELECT `id` FROM `logs` WHERE `type`="cashout"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs/section/cashout'); + + $sql->query('SELECT `id`, `user`, `text`, `date`, `money` FROM `logs` WHERE `type`="cashout" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $html->get('logs', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/extend.php b/system/acp/sections/logs/extend.php new file mode 100644 index 0000000..1e3058b --- /dev/null +++ b/system/acp/sections/logs/extend.php @@ -0,0 +1,32 @@ +query('SELECT `id` FROM `logs` WHERE `type`="extend"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs/section/extend'); + + $sql->query('SELECT `id`, `user`, `text`, `date`, `money` FROM `logs` WHERE `type`="extend" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $html->get('logs', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/index.php b/system/acp/sections/logs/index.php new file mode 100644 index 0000000..93848d9 --- /dev/null +++ b/system/acp/sections/logs/index.php @@ -0,0 +1,40 @@ +query('SELECT `id` FROM `logs_sys`'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs'); + + $sql->query('SELECT `id`, `user`, `server`, `text`, `time` FROM `logs_sys` ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + + if(!$log['user']) + $list .= 'Система'; + else + $list .= 'USER_'.$log['user'].''; + + $list .= 'SERVER_'.$log['server'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['time']).''; + $list .= ''; + } + + $html->get('index', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/part.php b/system/acp/sections/logs/part.php new file mode 100644 index 0000000..db84692 --- /dev/null +++ b/system/acp/sections/logs/part.php @@ -0,0 +1,32 @@ +query('SELECT `id` FROM `logs` WHERE `type`="part"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs/section/part'); + + $sql->query('SELECT `id`, `user`, `text`, `date`, `money` FROM `logs` WHERE `type`="part" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $html->get('logs', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/replenish.php b/system/acp/sections/logs/replenish.php new file mode 100644 index 0000000..f51c67e --- /dev/null +++ b/system/acp/sections/logs/replenish.php @@ -0,0 +1,32 @@ +query('SELECT `id` FROM `logs` WHERE `type`="replenish"'); + + $aPage = sys::page($page, $sql->num(), 40); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/logs/section/replenish'); + + $sql->query('SELECT `id`, `user`, `text`, `date`, `money` FROM `logs` WHERE `type`="replenish" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 40'); + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $html->get('logs', 'sections/logs'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/search.php b/system/acp/sections/logs/search.php new file mode 100644 index 0000000..cc41b52 --- /dev/null +++ b/system/acp/sections/logs/search.php @@ -0,0 +1,80 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + $select = '`id`, `user`, `text`, `date`, `type`, `money` FROM `logs`'; + + $check = explode('=', $text); + + if(in_array($check[0], array('server', 'user'))) + { + $val = trim($check[1]); + + switch($check[0]) + { + case 'server': + $sql->query('SELECT '.$select.' WHERE `server`="'.sys::int($val).'" ORDER BY `id` DESC'); + break; + + case 'user': + $sql->query('SELECT '.$select.' WHERE `user`="'.sys::int($val).'" ORDER BY `id` DESC'); + } + }elseif($text{0} == 'i' AND $text{1} == 'd') + $sql->query('SELECT `id`, `user`, `text`, `date`, `type`, `money` FROM `logs` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`user` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`type` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`money` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`text` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $sql->query('SELECT '.$select.' WHERE '.$like.' ORDER BY `id` DESC LIMIT 40'); + } + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + $list .= 'USER_'.$log['user'].''; + $list .= ''.$log['money'].' '.$cur['currency'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['date']).''; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/logs/sysearch.php b/system/acp/sections/logs/sysearch.php new file mode 100644 index 0000000..a3e980a --- /dev/null +++ b/system/acp/sections/logs/sysearch.php @@ -0,0 +1,84 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + $select = '`id`, `user`, `server`, `text`, `time` FROM `logs_sys`'; + + $check = explode('=', $text); + + if(in_array($check[0], array('server', 'user'))) + { + $val = trim($check[1]); + + switch($check[0]) + { + case 'server': + $sql->query('SELECT '.$select.' WHERE `server`="'.sys::int($val).'" ORDER BY `id` DESC'); + break; + + case 'user': + $sql->query('SELECT '.$select.' WHERE `user`="'.sys::int($val).'" ORDER BY `id` DESC'); + } + }elseif($text{0} == 'i' AND $text{1} == 'd') + $sql->query('SELECT '.$select.' WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`user` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`server` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`text` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $sql->query('SELECT '.$select.' WHERE '.$like.' ORDER BY `id` DESC LIMIT 40'); + } + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($log = $sql->get()) + { + $list .= ''; + $list .= ''.$log['id'].''; + $list .= ''.$log['text'].''; + + if(!$log['user']) + $list .= 'Система'; + else + $list .= 'USER_'.$log['user'].''; + + $list .= 'SERVER_'.$log['server'].''; + $list .= ''.date('d.m.Y - H:i:s', $log['time']).''; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/news/add.php b/system/acp/sections/news/add.php new file mode 100644 index 0000000..b94d89a --- /dev/null +++ b/system/acp/sections/news/add.php @@ -0,0 +1,37 @@ + 'Необходимо заполнить все поля')); + + if(sys::strlen($aData['name']) > 50) + sys::outjs(array('e' => 'Заголовок не должен превышать 50 символов.')); + + if(sys::strlen($aData['tags']) > 100) + sys::outjs(array('e' => 'Теги не должен превышать 100 символов.')); + + $sql->query('INSERT INTO `news` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`text`="'.htmlspecialchars($aData['text']).'",' + .'`full_text`="'.htmlspecialchars($aData['full']).'",' + .'`tags`="'.htmlspecialchars($aData['tags']).'",' + .'`views`="0",' + .'`date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('add', 'sections/news'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/news/delete.php b/system/acp/sections/news/delete.php new file mode 100644 index 0000000..e2e8a1e --- /dev/null +++ b/system/acp/sections/news/delete.php @@ -0,0 +1,8 @@ +query('DELETE FROM `news` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/news/index.php b/system/acp/sections/news/index.php new file mode 100644 index 0000000..143b906 --- /dev/null +++ b/system/acp/sections/news/index.php @@ -0,0 +1,40 @@ +query('SELECT `id` FROM `news`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/news'); + + $sql->query('SELECT `id`, `name`, `tags`, `views`, `date` FROM `news` ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($news = $sql->get()) + { + $list .= ''; + $list .= ''.$news['id'].''; + $list .= ''.$news['name'].''; + $list .= ''.$news['tags'].''; + $list .= ''.$news['views'].''; + $list .= ''.date('d.m.Y - H:i:s', $news['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/news'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/news/news.php b/system/acp/sections/news/news.php new file mode 100644 index 0000000..f7cd248 --- /dev/null +++ b/system/acp/sections/news/news.php @@ -0,0 +1,44 @@ +query('SELECT `name`, `text`, `full_text`, `tags` FROM `news` WHERE `id`="'.$id.'" LIMIT 1'); + $news = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : htmlspecialchars_decode($news['name']); + $aData['text'] = isset($_POST['text']) ? sys::bbc(trim($_POST['text'])) : htmlspecialchars_decode($news['text']); + $aData['full'] = isset($_POST['full']) ? sys::bbc(trim($_POST['full'])) : htmlspecialchars_decode($news['full_text']); + $aData['tags'] = isset($_POST['tags']) ? trim($_POST['tags']) : htmlspecialchars_decode($news['tags']); + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + if(sys::strlen($aData['name']) > 50) + sys::outjs(array('e' => 'Заголовок не должен превышать 50 символов.')); + + if(sys::strlen($aData['tags']) > 100) + sys::outjs(array('e' => 'Теги не должен превышать 100 символов.')); + + $sql->query('UPDATE `news` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`text`="'.htmlspecialchars($aData['text']).'",' + .'`full_text`="'.htmlspecialchars($aData['full']).'",' + .'`tags`="'.htmlspecialchars($aData['tags']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('news', 'sections/news'); + + $html->set('id', $id); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['text'])); + $html->set('full', htmlspecialchars_decode($news['full_text'])); + $html->set('tags', htmlspecialchars_decode($news['tags'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/news/search.php b/system/acp/sections/news/search.php new file mode 100644 index 0000000..3e2928f --- /dev/null +++ b/system/acp/sections/news/search.php @@ -0,0 +1,64 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if($text{0} == 'i' AND $text{1} == 'd') + $sql->query('SELECT `id`, `name`, `tags`, `views`, `date` FROM `news` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`text` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`tags` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`full_text` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $sql->query('SELECT `id`, `name`, `tags`, `views`, `date` FROM `news` WHERE '.$like.' ORDER BY `id` ASC LIMIT 20'); + } + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($news = $sql->get()) + { + $list .= ''; + $list .= ''.$news['id'].''; + $list .= ''.$news['name'].''; + $list .= ''.$news['tags'].''; + $list .= ''.$news['views'].''; + $list .= ''.date('d.m.Y - H:i:s', $news['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/notice/add.php b/system/acp/sections/notice/add.php new file mode 100644 index 0000000..18dbc96 --- /dev/null +++ b/system/acp/sections/notice/add.php @@ -0,0 +1,55 @@ +query('SELECT `id` FROM `units` WHERE `id`="'.$aData['unit'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанная локация не найдена')); + + $aData['server'] = 0; + }elseif($aData['type'] == 'server'){ + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$aData['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный сервер не найден')); + + $aData['unit'] = 0; + }else + sys::outjs(array('e' => 'Выберете получателя уведомления')); + + $sql->query('INSERT INTO `notice` set ' + .'`unit`="'.$aData['unit'].'",' + .'`server`="'.$aData['server'].'",' + .'`text`="'.htmlspecialchars($aData['text']).'",' + .'`color`="'.$aData['color'].'",' + .'`time`="'.$aData['time'].'"'); + + sys::outjs(array('s' => 'ok')); + } + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $html->get('add', 'sections/notice'); + + $html->set('units', $units); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/notice/delete.php b/system/acp/sections/notice/delete.php new file mode 100644 index 0000000..0ebbeb6 --- /dev/null +++ b/system/acp/sections/notice/delete.php @@ -0,0 +1,8 @@ +query('DELETE FROM `notice` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/notice/end.php b/system/acp/sections/notice/end.php new file mode 100644 index 0000000..21a1da2 --- /dev/null +++ b/system/acp/sections/notice/end.php @@ -0,0 +1,52 @@ +query('SELECT `id` FROM `notice`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/notice'); + + $notices = $sql->query('SELECT `id`, `unit`, `server`, `text`, `time` FROM `notice` WHERE `time`<"'.$start_point.'" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($notice = $sql->get($notices)) + { + if($notice['unit']) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$notice['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $name = $unit['name']; + }else + $name = 'SERVER_'.$notice['server'].''; + + $list .= ''; + $list .= ''.$notice['id'].''; + $list .= 'Адресовано: '.$name.''; + $list .= 'Завершен: '.date('d.m.Y - H:i:s', $notice['time']).''; + $list .= 'Редактировать'; + $list .= 'Удалить'; + $list .= ''; + + $list .= ''; + $list .= ''.$notice['text'].''; + $list .= ''; + } + + $html->get('index', 'sections/notice'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/notice/index.php b/system/acp/sections/notice/index.php new file mode 100644 index 0000000..eadb806 --- /dev/null +++ b/system/acp/sections/notice/index.php @@ -0,0 +1,52 @@ +query('SELECT `id` FROM `notice`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/notice'); + + $notices = $sql->query('SELECT `id`, `unit`, `server`, `text`, `time` FROM `notice` WHERE `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($notice = $sql->get($notices)) + { + if($notice['unit']) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$notice['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $name = $unit['name']; + }else + $name = 'SERVER_'.$notice['server'].''; + + $list .= ''; + $list .= ''.$notice['id'].''; + $list .= 'Адресовано: '.$name.''; + $list .= 'Завершится: '.date('d.m.Y - H:i:s', $notice['time']).''; + $list .= 'Редактировать'; + $list .= 'Удалить'; + $list .= ''; + + $list .= ''; + $list .= ''.$notice['text'].''; + $list .= ''; + } + + $html->get('index', 'sections/notice'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/notice/notice.php b/system/acp/sections/notice/notice.php new file mode 100644 index 0000000..ccecf70 --- /dev/null +++ b/system/acp/sections/notice/notice.php @@ -0,0 +1,79 @@ +query('SELECT * FROM `notice` WHERE `id`="'.$id.'" LIMIT 1'); + $notice = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['text'] = isset($_POST['text']) ? trim($_POST['text']) : htmlspecialchars_decode($notice['text']); + $aData['color'] = isset($_POST['color']) ? trim($_POST['color']) : $notice['color']; + $aData['type'] = isset($_POST['type']) ? trim($_POST['type']) : $notice['type']; + $aData['unit'] = isset($_POST['unit']) ? sys::int($_POST['unit']) : $notice['unit']; + $aData['server'] = isset($_POST['server']) ? sys::int($_POST['server']) : $notice['server']; + $aData['time'] = isset($_POST['time']) ? trim($_POST['time']) : ''; + + $aData['time'] = sys::checkdate($aData['time']); + + if($aData['type'] == 'unit') + { + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$aData['unit'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанная локация не найдена')); + + $aData['server'] = 0; + }elseif($aData['type'] == 'server'){ + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$aData['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный сервер не найден')); + + $aData['unit'] = 0; + }else + sys::outjs(array('e' => 'Выберете получателя уведомления')); + + $sql->query('UPDATE `notice` set ' + .'`unit`="'.$aData['unit'].'",' + .'`server`="'.$aData['server'].'",' + .'`text`="'.htmlspecialchars($aData['text']).'",' + .'`color`="'.$aData['color'].'",' + .'`time`="'.$aData['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $html->get('notice', 'sections/notice'); + + $html->set('id', $notice['id']); + $html->set('text', htmlspecialchars_decode($notice['text'])); + $html->set('time', date('d/m/Y H:i', $notice['time'])); + + if($notice['unit']) + { + $html->set('type', ''); + $html->set('units', str_replace('"'.$notice['unit'].'"', '"'.$notice['unit'].'" selected', $units)); + $html->set('server', ''); + + $html->unit('unit'); + $html->unit('server', true); + }else{ + $html->set('type', ''); + $html->set('units', $units); + $html->set('server', $notice['server']); + + $html->unit('unit', true); + $html->unit('server'); + } + + $html->set('colors', str_replace('"'.$notice['color'].'"', '"'.$notice['color'].'" selected', '')); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/notice/search.php b/system/acp/sections/notice/search.php new file mode 100644 index 0000000..afed208 --- /dev/null +++ b/system/acp/sections/notice/search.php @@ -0,0 +1,75 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if($text{0} == 'i' AND $text{1} == 'd') + $notices = $sql->query('SELECT `id`, `unit`, `server`, `text`, `time` FROM `notice` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`unit` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`server` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`text` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $notices = $sql->query('SELECT `id`, `unit`, `server`, `text`, `time` FROM `notice` WHERE '.$like.' ORDER BY `id` ASC LIMIT 20'); + } + + if(!$sql->num($notices)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($notice = $sql->get($notices)) + { + if($notice['unit']) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$notice['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $name = $unit['name']; + }else + $name = 'SERVER_'.$notice['server'].''; + + $list .= ''; + $list .= ''.$notice['id'].''; + $list .= 'Адресовано: '.$name.''; + $list .= 'Завершится: '.date('d.m.Y - H:i:s', $notice['time']).''; + $list .= 'Редактировать'; + $list .= 'Удалить'; + $list .= ''; + + $list .= ''; + $list .= ''.$notice['text'].''; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/pages/add.php b/system/acp/sections/pages/add.php new file mode 100644 index 0000000..c610239 --- /dev/null +++ b/system/acp/sections/pages/add.php @@ -0,0 +1,31 @@ + 'Необходимо заполнить все поля')); + + $name = md5(time().rand(5, 100).rand(10, 20).rand(1, 20).rand(40, 80)); + + $file = fopen(FILES.'pages/'.$name, "w"); + + fputs($file, $aData['text']); + + fclose($file); + + $sql->query('INSERT INTO `pages` set `name`="'.htmlspecialchars($aData['name']).'", `file`="'.$name.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('add', 'sections/pages'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/pages/delete.php b/system/acp/sections/pages/delete.php new file mode 100644 index 0000000..1519c3d --- /dev/null +++ b/system/acp/sections/pages/delete.php @@ -0,0 +1,13 @@ +query('SELECT `file` FROM `pages` WHERE `id`="'.$id.'" LIMIT 1'); + $page = $sql->get(); + + unlink(FILES.'pages/'.$page['file']); + + $sql->query('DELETE FROM `pages` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/pages/index.php b/system/acp/sections/pages/index.php new file mode 100644 index 0000000..c914b7f --- /dev/null +++ b/system/acp/sections/pages/index.php @@ -0,0 +1,36 @@ +query('SELECT `id` FROM `pages`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/pages'); + + $sql->query('SELECT * FROM `pages` ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($page = $sql->get()) + { + $list .= ''; + $list .= ''.$page['id'].''; + $list .= ''.$page['name'].''; + $list .= ''.$page['file'].''; + $list .= 'Перейти'; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/pages'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/pages/page.php b/system/acp/sections/pages/page.php new file mode 100644 index 0000000..953fcb8 --- /dev/null +++ b/system/acp/sections/pages/page.php @@ -0,0 +1,37 @@ +query('SELECT `name`, `file` FROM `pages` WHERE `id`="'.$id.'" LIMIT 1'); + $page = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : $page['name']; + $aData['text'] = isset($_POST['text']) ? trim($_POST['text']) : file_get_contents(FILES.'pages/'.$page['file']); + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + $file = fopen(FILES.'pages/'.$page['file'], "w"); + + fputs($file, $aData['text']); + + fclose($file); + + $sql->query('UPDATE `pages` set `name`="'.htmlspecialchars($aData['name']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('page', 'sections/pages'); + + $html->set('id', $id); + $html->set('name', htmlspecialchars_decode($page['name'])); + + $html->set('text', htmlspecialchars(file_get_contents(FILES.'pages/'.$page['file']))); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/promo/add.php b/system/acp/sections/promo/add.php new file mode 100644 index 0000000..88357bd --- /dev/null +++ b/system/acp/sections/promo/add.php @@ -0,0 +1,88 @@ + 'Неправильный формат промо-кода')); + + if($aData['user']) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный пользователь не найден')); + }else + $aData['user'] = 0; + + if($aData['server']) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$aData['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный сервер не найден')); + }else + $aData['server'] = 0; + + if(!is_array($aData['tarifs']) || !count($aData['tarifs'])) + sys::outjs(array('e' => 'Необходимо указать минимум один тариф')); + + if($aData['discount']) + $proc = strpos($aData['value'], '%') ? '%' : ''; + + $aData['value'] = sys::int($aData['value']).$proc; + + foreach($aData['tarifs'] as $id => $on) + { + $sql->query('SELECT `id` FROM `promo` WHERE `cod`="'.$aData['cod'].'" AND `tarif`="'.$id.'" LIMIT 1'); + if($sql->num()) + continue; + + $sql->query('INSERT INTO `promo` set ' + .'`cod`="'.$aData['cod'].'",' + .'`value`="'.$aData['value'].'",' + .'`discount`="'.$aData['discount'].'",' + .'`data`="'.base64_encode('{'.$aData['data'].'}').'",' + .'`hits`="'.$aData['hits'].'",' + .'`use`="'.$aData['use'].'",' + .'`extend`="'.$aData['extend'].'",' + .'`tarif`="'.$id.'",' + .'`user`="'.$aData['user'].'",' + .'`server`="'.$aData['server'].'",' + .'`time`="'.$aData['time'].'"'); + } + + sys::outjs(array('s' => 'ok')); + } + + $tarifs = ''; + + $units = $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get($units)) + { + $sql->query('SELECT `id`, `name`, `game` FROM `tarifs` WHERE `unit`="'.$unit['id'].'" ORDER BY `id` ASC'); + while($tarif = $sql->get()) + $tarifs .= ''; + } + + $html->get('add', 'sections/promo'); + + $html->set('tarifs', $tarifs); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/promo/delete.php b/system/acp/sections/promo/delete.php new file mode 100644 index 0000000..e6fdd8b --- /dev/null +++ b/system/acp/sections/promo/delete.php @@ -0,0 +1,9 @@ +query('DELETE FROM `promo` WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `promo_use` WHERE `promo`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/promo/end.php b/system/acp/sections/promo/end.php new file mode 100644 index 0000000..5897704 --- /dev/null +++ b/system/acp/sections/promo/end.php @@ -0,0 +1,46 @@ +query('SELECT `id` FROM `promo`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/promo'); + + $promos = $sql->query('SELECT `id`, `cod`, `value`, `discount`, `use`, `extend`, `tarif`, `time` FROM `promo` WHERE `time`<"'.$start_point.'"ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($promo = $sql->get($promos)) + { + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$promo['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$promo['id'].''; + $list .= ''.$promo['cod'].''; + $list .= ''.$promo['value'].''; + $list .= '#'.$promo['tarif'].' '.$tarif['name'].''; + $list .= ''.($promo['discount'] ? 'Скидка' : 'Подарочные дни').''; + $list .= ''.($promo['extend'] ? 'Продление' : 'Аренда').''; + $list .= ''.$promo['use'].' шт.'; + $list .= 'Завершена'; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/promo'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/promo/index.php b/system/acp/sections/promo/index.php new file mode 100644 index 0000000..5acd8df --- /dev/null +++ b/system/acp/sections/promo/index.php @@ -0,0 +1,46 @@ +query('SELECT `id` FROM `promo`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/promo'); + + $promos = $sql->query('SELECT `id`, `cod`, `value`, `discount`, `use`, `extend`, `tarif`, `time` FROM `promo` WHERE `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($promo = $sql->get($promos)) + { + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$promo['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$promo['id'].''; + $list .= ''.$promo['cod'].''; + $list .= ''.$promo['value'].''; + $list .= '#'.$promo['tarif'].' '.$tarif['name'].''; + $list .= ''.($promo['discount'] ? 'Скидка' : 'Подарочные дни').''; + $list .= ''.($promo['extend'] ? 'Продление' : 'Аренда').''; + $list .= ''.$promo['use'].' шт.'; + $list .= ''.date('d.m.Y - H:i:s', $promo['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/promo'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/promo/promo.php b/system/acp/sections/promo/promo.php new file mode 100644 index 0000000..9c110aa --- /dev/null +++ b/system/acp/sections/promo/promo.php @@ -0,0 +1,92 @@ +query('SELECT * FROM `promo` WHERE `id`="'.$id.'" LIMIT 1'); + $promo = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['cod'] = isset($_POST['cod']) ? trim($_POST['cod']) : $promo['cod']; + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : $promo['value']; + $aData['discount'] = isset($_POST['discount']) ? sys::int($_POST['discount']) : $promo['discount']; + $aData['hits'] = isset($_POST['hits']) ? sys::int($_POST['hits']) : $promo['hits']; + $aData['use'] = isset($_POST['use']) ? sys::int($_POST['use']) : $promo['use']; + $aData['extend'] = isset($_POST['extend']) ? sys::int($_POST['extend']) : $promo['extend']; + $aData['user'] = isset($_POST['user']) ? sys::int($_POST['user']) : $promo['user']; + $aData['server'] = isset($_POST['server']) ? sys::int($_POST['server']) : $promo['server']; + $aData['time'] = isset($_POST['time']) ? trim($_POST['time']) : date('d/m/Y H:i', $promo['time']); + $aData['data'] = isset($_POST['data']) ? trim($_POST['data']) : $promo['data']; + + $aData['time'] = sys::checkdate($aData['time']); + + if(sys::valid($aData['cod'], 'promo')) + sys::outjs(array('e' => 'Неправильный формат промо-кода')); + + $sql->query('SELECT `id` FROM `promo` WHERE `id`!="'.$id.'" AND `cod`="'.$aData['cod'].'" AND `tarif`="'.$promo['tarif'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Указанный код используется в другой акции')); + + if($aData['user']) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный пользователь не найден')); + }else + $aData['user'] = 0; + + if($aData['server']) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$aData['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанный сервер не найден')); + }else + $aData['server'] = 0; + + if($aData['discount']) + $proc = strpos($aData['value'], '%') ? '%' : ''; + + $aData['value'] = sys::int($aData['value']).$proc; + + $sql->query('UPDATE `promo` set ' + .'`cod`="'.$aData['cod'].'",' + .'`value`="'.$aData['value'].'",' + .'`discount`="'.$aData['discount'].'",' + .'`data`="'.base64_encode('{'.$aData['data'].'}').'",' + .'`hits`="'.$aData['hits'].'",' + .'`use`="'.$aData['use'].'",' + .'`extend`="'.$aData['extend'].'",' + .'`user`="'.$aData['user'].'",' + .'`server`="'.$aData['server'].'",' + .'`time`="'.$aData['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $sql->query('SELECT `id`, `unit`, `name`, `game` FROM `tarifs` WHERE `id`="'.$promo['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $html->get('promo', 'sections/promo'); + + $html->set('id', $promo['id']); + $html->set('cod', $promo['cod']); + $html->set('value', $promo['value']); + $html->set('data', str_replace(array('{', '}'), '', base64_decode($promo['data']))); + $html->set('hits', $promo['hits']); + $html->set('use', $promo['use']); + $html->set('user', $promo['user']); + $html->set('server', $promo['server']); + $html->set('time', date('d/m/Y H:i', $promo['time'])); + + $html->set('discount', $promo['discount'] ? '' : ''); + $html->set('extend', $promo['extend'] ? '' : ''); + + $html->set('tarif', $unit['name'].' / #'.$tarif['id'].' '.$tarif['name'].' ('.strtoupper($tarif['game']).')'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/promo/search.php b/system/acp/sections/promo/search.php new file mode 100644 index 0000000..ccb5884 --- /dev/null +++ b/system/acp/sections/promo/search.php @@ -0,0 +1,68 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if($text{0} == 'i' AND $text{1} == 'd') + $promos = $sql->query('SELECT `id`, `cod`, `value`, `discount`, `use`, `extend`, `tarif`, `time` FROM `promo` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`cod` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`value` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $promos = $sql->query('SELECT `id`, `cod`, `value`, `discount`, `use`, `extend`, `tarif`, `time` FROM `promo` WHERE '.$like.' ORDER BY `id` ASC LIMIT 20'); + } + + if(!$sql->num($promos)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($promo = $sql->get($promos)) + { + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$promo['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$promo['id'].''; + $list .= ''.$promo['cod'].''; + $list .= ''.$promo['value'].''; + $list .= '#'.$promo['tarif'].' '.$tarif['name'].''; + $list .= ''.($promo['discount'] ? 'Скидка' : 'Подарочные дни').''; + $list .= ''.($promo['extend'] ? 'Продление' : 'Аренда').''; + $list .= ''.$promo['use'].' шт.'; + $list .= ''.date('d.m.Y - H:i:s', $promo['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/promo/stats.php b/system/acp/sections/promo/stats.php new file mode 100644 index 0000000..4502c00 --- /dev/null +++ b/system/acp/sections/promo/stats.php @@ -0,0 +1,38 @@ +query('DELETE FROM `promo_use` WHERE `id`="'.sys::int($url['delete']).'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $list = ''; + + $all_use = $sql->query('SELECT * FROM `promo_use` ORDER BY `id` ASC LIMIT 100'); + while($promo_use = $sql->get($all_use)) + { + $sql->query('SELECT `text` FROM `logs` WHERE `user`="'.$promo_use['user'].'" AND `date`="'.$promo_use['time'].'" LIMIT 1'); + $log = $sql->get(); + + $sql->query('SELECT `cod` FROM `promo` WHERE `id`="'.$promo_use['promo'].'" LIMIT 1'); + $promo = $sql->get(); + + $list .= ''; + $list .= ''.$promo_use['id'].''; + $list .= ''.$promo['cod'].''; + $list .= 'USER_'.$promo_use['user'].''; + $list .= ''.$log['text'].''; + $list .= ''.sys::today($promo_use['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('stats', 'sections/promo'); + + $html->set('list', $list); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/servers/crmp.php b/system/acp/sections/servers/crmp.php new file mode 100644 index 0000000..b6b1997 --- /dev/null +++ b/system/acp/sections/servers/crmp.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="crmp"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/crmp'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="crmp" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/cs.php b/system/acp/sections/servers/cs.php new file mode 100644 index 0000000..a14b882 --- /dev/null +++ b/system/acp/sections/servers/cs.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="cs"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/cs'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="cs" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/csgo.php b/system/acp/sections/servers/csgo.php new file mode 100644 index 0000000..f56ff6e --- /dev/null +++ b/system/acp/sections/servers/csgo.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="csgo"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/csgo'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="csgo" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/css.php b/system/acp/sections/servers/css.php new file mode 100644 index 0000000..05c7a7b --- /dev/null +++ b/system/acp/sections/servers/css.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="css"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/css'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="css" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/cssold.php b/system/acp/sections/servers/cssold.php new file mode 100644 index 0000000..219abb8 --- /dev/null +++ b/system/acp/sections/servers/cssold.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="cssold"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/cssold'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="cssold" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/delete.php b/system/acp/sections/servers/delete.php new file mode 100644 index 0000000..29625f6 --- /dev/null +++ b/system/acp/sections/servers/delete.php @@ -0,0 +1,8 @@ +query('UPDATE `servers` set `user`="-1", `status`="overdue", `time`="0", `overdue`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/servers/index.php b/system/acp/sections/servers/index.php new file mode 100644 index 0000000..cdbde17 --- /dev/null +++ b/system/acp/sections/servers/index.php @@ -0,0 +1,80 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/mc.php b/system/acp/sections/servers/mc.php new file mode 100644 index 0000000..9aed1dd --- /dev/null +++ b/system/acp/sections/servers/mc.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="mc"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/mc'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="mc" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/mta.php b/system/acp/sections/servers/mta.php new file mode 100644 index 0000000..f83c1b5 --- /dev/null +++ b/system/acp/sections/servers/mta.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="mta"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/mta'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="mta" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/overdue.php b/system/acp/sections/servers/overdue.php new file mode 100644 index 0000000..bc56d59 --- /dev/null +++ b/system/acp/sections/servers/overdue.php @@ -0,0 +1,43 @@ +query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `slots`, `name`, `overdue` FROM `servers` WHERE `user`!="-1" AND `time`<"'.$start_point.'" AND `overdue`>"'.$start_point.'" ORDER BY `id` ASC'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= 'Просрочен'; + $list .= 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + $html->set('list', $list); + $html->set('pages', ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/samp.php b/system/acp/sections/servers/samp.php new file mode 100644 index 0000000..8e2a8d4 --- /dev/null +++ b/system/acp/sections/servers/samp.php @@ -0,0 +1,77 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $select = 'WHERE `user`!="-1"'; + $url_search = ''; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + { + $select = 'WHERE `'.$url['search'].'`="'.sys::int($url[$url['search']]).'" AND `user`!="-1"'; + $url_search = '/search/'.$url['search'].'/'.$url['search'].'/'.$url[$url['search']]; + } + + $sql->query('SELECT `id` FROM `servers` '.$select.' AND `game`="samp"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/servers/section/samp'.$url_search); + + $servers = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` '.$select.' AND `game`="samp" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/servers'); + + $html->set('list', $list); + + $html->set('url_search', $url_search); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/servers/search.php b/system/acp/sections/servers/search.php new file mode 100644 index 0000000..d204690 --- /dev/null +++ b/system/acp/sections/servers/search.php @@ -0,0 +1,138 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + $select = '`id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time` FROM `servers` WHERE `user`!="-1" AND'; + + if(isset($url['search']) AND in_array($url['search'], array('unit', 'tarif'))) + $select .= ' `'.$url['search'].'`='.sys::int($url[$url['search']]).' AND'; + + $check = explode('=', $text); + + if(in_array($check[0], array('game', 'unit', 'core', 'tarif', 'user', 'status', 'slots'))) + { + $val = trim($check[1]); + + switch($check[0]) + { + case 'game': + if(in_array($val, array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + $servers = $sql->query('SELECT '.$select.' FROM `servers` WHERE `user`!="-1" AND `game`="'.$val.'" ORDER BY `id` ASC'); + break; + + case 'unit': + $servers = $sql->query('SELECT '.$select.' `unit`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'core': + $servers = $sql->query('SELECT '.$select.' `core_use`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'tarif': + $servers = $sql->query('SELECT '.$select.' `tarif`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'user': + $servers = $sql->query('SELECT '.$select.' `user`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + + case 'status': + if(in_array($val, array('working', 'start', 'change', 'restart', 'off', 'overdue', 'blocked', 'recovery', 'reinstall', 'update', 'install'))) + $servers = $sql->query('SELECT '.$select.' `status`="'.$val.'" ORDER BY `id` ASC'); + break; + + case 'slots': + $servers = $sql->query('SELECT '.$select.' `slots`="'.sys::int($val).'" ORDER BY `id` ASC'); + break; + } + }elseif($text{0} == 'i' AND $text{1} == 'd') + $servers = $sql->query('SELECT '.$select.' `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`game` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`slots` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`status` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`address` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`port` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $servers = $sql->query('SELECT '.$select.' ('.$like.') ORDER BY `id` ASC'); + } + + if(!$sql->num($servers)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $status = array( + 'working' => 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $list = ''; + + while($server = $sql->get($servers)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $list .= ''; + $list .= ''.$server['id'].''; + $list .= ''.$server['name'].''; + $list .= '#'.$server['unit'].' '.$unit['name'].''; + $list .= ''.$server['slots'].' шт.'; + $list .= ''.strtoupper($server['game']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= 'USER_'.$server['user'].''; + $list .= ''.$server['address'].''; + $list .= '#'.$server['tarif'].' '.$tarif['name'].''; + $list .= ''.$status[$server['status']].''; + $list .= ''.date('d.m.Y - H:i:s', $server['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/servers/server.php b/system/acp/sections/servers/server.php new file mode 100644 index 0000000..43b04b6 --- /dev/null +++ b/system/acp/sections/servers/server.php @@ -0,0 +1,282 @@ +query('SELECT `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if($server['time'] > $start_point AND $server['overdue']) + $sql->query('UPDATE `servers` set `overdue`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('SELECT * FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `slots_min`, `slots_max`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + if($go) + { + if(isset($url['type']) AND in_array($url['type'], array('overdue', 'block', 'tarif'))) + { + if($url['type'] != 'tarif') + { + $time = isset($_POST['time']) ? trim($_POST['time']) : sys::outjs(array('e' => 'Необходимо указать дату.')); + + $date = sys::checkdate($time); + } + + switch($url['type']) + { + case 'overdue': + if($server['time'] > $start_point) + sys::outjs(array('e' => 'Игровой сервер должен быть просрочен.')); + + $sql->query('UPDATE `servers` set `overdue`="'.$date.'" WHERE `id`="'.$id.'" LIMIT 1'); + break; + + case 'block': + if($server['status'] != ('off' || 'overdue')) + sys::outjs(array('e' => 'Игровой сервер должен быть выключен.')); + + if($date < $start_point) + $sql->query('UPDATE `servers` set `status`="off", `block`="0" WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('UPDATE `servers` set `status`="blocked", `block`="'.$date.'" WHERE `id`="'.$id.'" LIMIT 1'); + break; + + case 'tarif': + $tid = isset($url['tarif']) ? sys::int($url['tarif']) : sys::outjs(array('e' => 'Необходимо указать тариф.')); + + if($tid == $server['tarif']) + sys::outjs(array('s' => 'ok')); + + $sql->query('SELECT `id`, `slots_min`, `slots_max`, `packs`, `fps`, `tickrate`, `ram` FROM `tarifs` WHERE `id`="'.$tid.'" AND `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Укажите тариф из списка.')); + + $tarif = $sql->get(); + + if($server['slots'] < $tarif['slots_min'] || $server['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Данный тариф не совместим по слотам.')); + + if($server['fps']) + { + if(!in_array($server['fps'], explode(':', $tarif['fps']))) + sys::outjs(array('e' => 'Данный тариф не совместим по FPS.')); + } + + if($server['tickrate']) + { + if(!in_array($server['tickrate'], explode(':', $tarif['tickrate']))) + sys::outjs(array('e' => 'Данный тариф не совместим по TickRate.')); + } + + if($server['game'] == 'mc') + { + $ram = $server['ram']/$server['slots']; + + if(!in_array($ram, explode(':', $tarif['ram']))) + sys::outjs(array('e' => 'Данный тариф не совместим по RAM.')); + } + + if(!array_key_exists($server['pack'], sys::b64djs($tarif['packs']))) + sys::outjs(array('e' => 'На данном тарифном плане нет сборки игрового сервера.')); + + $sql->query('UPDATE `servers` set `tarif`="'.$tid.'" WHERE `id`="'.$id.'" LIMIT 1'); + break; + } + + sys::outjs(array('s' => 'ok')); + } + + $aData = array(); + + $aData['user'] = isset($_POST['user']) ? sys::int($_POST['user']) : $server['user']; + $aData['address'] = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + $aData['port'] = isset($_POST['port']) ? sys::int($_POST['port']) : $server['port']; + $aData['hdd'] = isset($_POST['hdd']) ? sys::int($_POST['hdd']) : $server['hdd']; + $aData['slots'] = isset($_POST['slots']) ? trim($_POST['slots']) : $server['slots']; + $aData['pack'] = isset($_POST['pack']) ? trim($_POST['pack']) : $server['pack']; + $aData['fps'] = isset($_POST['fps']) ? sys::int($_POST['fps']) : $server['fps']; + $aData['tickrate'] = isset($_POST['tickrate']) ? sys::int($_POST['tickrate']) : $server['tickrate']; + $aData['ram'] = isset($_POST['ram']) ? sys::int($_POST['ram']) : $server['ram']; + $aData['core_fix_one'] = isset($_POST['core_fix_one']) ? sys::int($_POST['core_fix_one']) : $server['core_fix_one']; + $aData['core_fix'] = isset($_POST['core_fix']) ? sys::int($_POST['core_fix']) : $server['core_fix']; + $aData['cpu_use_max'] = isset($_POST['cpu_use_max']) ? sys::int($_POST['cpu_use_max']) : $server['cpu_use_max']; + $aData['pingboost'] = isset($_POST['pingboost']) ? sys::int($_POST['pingboost']) : $server['pingboost']; + $aData['time'] = isset($_POST['time']) ? trim($_POST['time']) : $server['time']; + + $aData['ftp_use'] = isset($_POST['ftp_use']) ? $_POST['ftp_use'] : $server['ftp_use']; + $aData['ftp_root'] = isset($_POST['ftp_root']) ? sys::int($_POST['ftp_root']) : $server['ftp_root']; + $aData['plugins_use'] = isset($_POST['plugins_use']) ? $_POST['plugins_use'] : $server['plugins_use']; + $aData['console_use'] = isset($_POST['console_use']) ? $_POST['console_use'] : $server['console_use']; + $aData['stats_use'] = isset($_POST['stats_use']) ? $_POST['stats_use'] : $server['stats_use']; + $aData['copy_use'] = isset($_POST['copy_use']) ? $_POST['copy_use'] : $server['copy_use']; + $aData['web_use'] = isset($_POST['web_use']) ? $_POST['web_use'] : $server['web_use']; + + if($server['user'] != $aData['user']) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден.')); + else{ + $sql->query('SELECT `id` FROM `web` WHERE `user`!="'.$aData['user'].'" AND `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Невозможно установить пользователя владельцем данного сервера
    Из-за возможной несовместимости с бесплатными услугами.
    Удалите у данного сервера бесплатные услуги.')); + } + } + + if(sys::valid($aData['address'], 'other', $aValid['address'])) + $aData['address'] = $server['address']; + + $sql->query('SELECT `id` FROM `servers` WHERE `id`!="'.$id.'" AND `address`="'.$aData['address'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `id`!="'.$id.'" AND `address` LIKE \'%'.sys::first(explode(':', $unit['address'])).'\' AND `port`="'.$aData['port'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный порт занят другим сервером.')); + + $slots = explode(':', $aData['slots']); + + if(!isset($slots[0]) AND !isset($slots[1])) + sys::outjs(array('e' => 'Слоты указаны не правильно.')); + + if($slots[0] < 2 || $slots[1] < 2) + sys::outjs(array('e' => 'Слоты указаны не правильно.')); + + if($slots[0] > $tarif['slots_max'] || $slots[0] < $tarif['slots_min']) + sys::outjs(array('e' => 'Слоты указаны не правильно.')); + + $slots[1] = $slots[1] > $slots[0] ? $slots[0] : $slots[1]; + + $aPacks = sys::b64djs($tarif['packs']); + + if(!array_key_exists($aData['pack'], $aPacks)) + sys::outjs(array('e' => 'Указанная сборка не найдена.')); + + if($aData['core_fix_one']) + { + if($aData['core_fix']) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`!="'.$id.'" AND `unit`="'.$server['unit'].'" AND `core_fix`="'.$aData['core_fix'].'" AND `core_fix_one`="1"'); + if($sql->num()) + sys::outjs(array('e' => 'Указанное ядро занято другим сервером.')); + }else + $aData['core_fix_one'] = 0; + } + + if(!in_array($aData['pingboost'], array(1,2,3))) + $aData['pingboost'] = 0; + + $aData['time'] = sys::checkdate($aData['time']); + + foreach(array('ftp_use', 'plugins_use', 'console_use', 'stats_use', 'copy_use', 'web_use') as $section) + $aData[$section] = (string) $aData[$section] == 'on' ? '1' : '0'; + + $sql->query('UPDATE `servers` set ' + .'`user`="'.$aData['user'].'",' + .'`address`="'.$aData['address'].'",' + .'`port`="'.$aData['port'].'",' + .'`slots`="'.$slots[0].'",' + .'`slots_start`="'.$slots[1].'",' + .'`fps`="'.$aData['fps'].'",' + .'`tickrate`="'.$aData['tickrate'].'",' + .'`ram`="'.$aData['ram'].'",' + .'`core_fix`="'.$aData['core_fix'].'",' + .'`core_fix_one`="'.$aData['core_fix_one'].'",' + .'`cpu_use_max`="'.$aData['cpu_use_max'].'",' + .'`pingboost`="'.$aData['pingboost'].'",' + .'`time`="'.$aData['time'].'",' + .'`ftp_use`="'.$aData['ftp_use'].'",' + .'`ftp_root`="'.$aData['ftp_root'].'",' + .'`plugins_use`="'.$aData['plugins_use'].'",' + .'`console_use`="'.$aData['console_use'].'",' + .'`stats_use`="'.$aData['stats_use'].'",' + .'`copy_use`="'.$aData['copy_use'].'",' + .'`web_use`="'.$aData['web_use'].'",' + .'`pack`="'.$aData['pack'].'",' + .'`hdd`="'.$aData['hdd'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('UPDATE `web` set `user`="'.$aData['user'].'" WHERE `server`="'.$id.'"'); + + $mcache->delete('server_index_'.$id); + $mcache->delete('server_resources_'.$id); + $mcache->delete('server_status_'.$id); + + sys::outjs(array('s' => 'ok')); + } + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $packs = ''; + + $aPacks = sys::b64djs($tarif['packs']); + + foreach($aPacks as $name => $fullname) + $packs .= ''; + + $packs = str_replace('"'.$server['pack'].'"', '"'.$server['pack'].'" selected', $packs); + + $cfo = $server['core_fix_one'] ? '' : ''; + $pingboost = str_replace('="'.$server['pingboost'].'"', '="'.$server['pingboost'].'" selected', ''); + $ftp_root = $server['ftp_root'] ? '' : ''; + + $tarifs = ''; + + $sql->query('SELECT `id`, `name` FROM `tarifs` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `id`!="'.$server['tarif'].'"'); + while($tarif_list = $sql->get()) + $tarifs .= ''; + + $copys = $sql->query('SELECT `id`, `user` FROM `copy` WHERE `server`="'.$id.'" LIMIT 10'); + while($copy = $sql->get($copys)) + { + $aCP = explode('_', $copy['user']); + + if($aCP[0] != $aData['user']) + $sql->query('UPDATE `copy` set `user`="'.$aData['user'].'_'.$aCP[1].'" WHERE `id`="'.$copy['id'].' LIMIT 1'); + } + + $html->get('server', 'sections/servers'); + $html->set('id', $id); + $html->set('name', $server['name']); + $html->set('address', $server['address']); + $html->set('port', $server['port']); + $html->set('slots', $server['slots']); + $html->set('slots_start', $server['slots_start']); + $html->set('user', $server['user']); + $html->set('game', $server['game']); + $html->set('unit', $unit['name']); + $html->set('tarif', '#'.$server['tarif'].' '.$tarif['name']); + $html->set('hdd', $server['hdd']); + $html->set('fps', $server['fps']); + $html->set('tickrate', $server['tickrate']); + $html->set('ram', $server['ram']); + $html->set('ftp_on', $server['ftp_on'] ? 'Использовался' : 'Не использовался'); + $html->set('tarifs', $tarifs); + $html->set('pingboost', $pingboost); + $html->set('ftp_root', $ftp_root); + $html->set('core_fix', $server['core_fix']); + $html->set('cpu_use_max', $server['cpu_use_max']); + $html->set('cpu_limi', $cfg['cpu_use_max'][$server['game']]); + $html->set('core_fix_one', $cfo); + $html->set('packs', $packs); + $html->set('time', date('d/m/Y H:i', $server['time'])); + $html->set('date', date('d.m.Y - H:i:s', $server['date'])); + $html->set('overdue', $server['overdue'] == 0 ? 'Установить' : date('d/m/Y H:i', $server['overdue'])); + $html->set('block', $server['block'] == 0 ? 'Заблокировать' : date('d/m/Y H:i', $server['block'])); + + foreach(array('ftp_use', 'plugins_use', 'console_use', 'stats_use', 'copy_use', 'web_use') as $section) + { + if($server[$section]) + $html->unit($section, 1); + else + $html->unit($section); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/add.php b/system/acp/sections/tarifs/add.php new file mode 100644 index 0000000..a355e9f --- /dev/null +++ b/system/acp/sections/tarifs/add.php @@ -0,0 +1,416 @@ + 'Необходимо указать название')); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$aData['unit'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо указать локацию')); + + if(!in_array($aData['game'], array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + sys::outjs(array('e' => 'Необходимо указать игру')); + + $aSlots = explode('-', $aData['slots']); + + if(!isset($aSlots[0]) || !isset($aSlots[1])) + sys::outjs(array('e' => 'Необходимо указать слоты')); + + $aSlots[0] = trim($aSlots[0]); + $aSlots[1] = trim($aSlots[1]); + + $aData['slots_min'] = $aSlots[0] > 1 ? $aSlots[0] : sys::outjs(array('e' => 'Неправильно указаны слоты')); + $aData['slots_max'] = $aSlots[1] >= $aSlots[0] ? $aSlots[1] : sys::outjs(array('e' => 'Неправильно указаны слоты')); + + $aPorts = explode('-', $aData['posts']); + + if(!isset($aPorts[0]) || !isset($aPorts[1])) + sys::outjs(array('e' => 'Необходимо указать порты')); + + $aPorts[0] = trim($aPorts[0]); + $aPorts[1] = trim($aPorts[1]); + + $aData['port_min'] = $aPorts[0] > 1 ? $aPorts[0] : sys::outjs(array('e' => 'Неправильно указаны порты')); + $aData['port_max'] = $aPorts[1] >= $aPorts[0] ? $aPorts[1] : sys::outjs(array('e' => 'Неправильно указаны порты')); + + if($aData['hostname'] == '') + sys::outjs(array('e' => 'Необходимо указать название сервера')); + + if($aData['path'] == '') + sys::outjs(array('e' => 'Необходимо указать путь до сборок')); + + if($aData['install'] == '') + sys::outjs(array('e' => 'Необходимо указать путь для установки серверов')); + + if($aData['update'] == '') + sys::outjs(array('e' => 'Необходимо указать путь до обновления сборки')); + + if(substr($aData['path'], -1) != '/' || substr($aData['install'], -1) != '/' || substr($aData['update'], -1) != '/') + sys::outjs(array('e' => 'Пути должны заканчиваться символом "/"')); + + $int = array( + 'Тестов' => 'tests', + 'Положение' => 'sort', + 'Диск' => 'hdd' + ); + + foreach($int as $name => $input) + { + if($aData[$input] == '') + sys::outjs(array('e' => 'Необходимо указать поле "'.$name.'"')); + } + + $aPacks = explode(',', $aData['packs']); + + $packs = array(); + + foreach($aPacks as $pack) + { + $aPack = explode(':', trim($pack)); + + if(!isset($aPack[0]) || !isset($aPack[1])) + continue; + + $name = str_replace('"', '', $aPack[0]); + $fullname = str_replace('"', '', $aPack[1]); + + $packs[trim($name)] = trim($fullname); + } + + if(!count($packs)) + sys::outjs(array('e' => 'Необходимо указать минимум одну сборку')); + + $aData['packs'] = sys::b64js($packs); + + $aIp = explode(':', $aData['ip']); + + $ips = ''; + + foreach($aIp as $ip) + { + $ip = trim($ip); + + if(sys::valid($ip, 'ip')) + continue; + + $ips .= $ip.':'; + } + + $ips = isset($ips{0}) ? substr($ips, 0, -1) : ''; + + $aData['ip'] = $ips; + + $aPlugins = explode('","', $aData['plugins_install']); + + $plugins = array(); + + foreach($aPlugins as $plugin) + { + $aPlugin = explode(':', trim($plugin)); + + if(!isset($aPlugin[0]) || !isset($aPlugin[1])) + continue; + + $name = trim(str_replace('"', '', $aPlugin[0])); + + if(!isset($packs[$name])) + continue; + + $aList = explode(',', str_replace('"', '', $aPlugin[1])); + + $list = ''; + + foreach($aList as $pid) + { + $pid = trim($pid); + + if(!is_numeric($pid)) + continue; + + $list .= intval($pid).','; + } + + $list = isset($list{0}) ? substr($list, 0, -1) : ''; + + if($list == '') + continue; + + $plugins[$name] = $list; + } + + $aData['plugins_install'] = count($plugins) ? sys::b64js($plugins) : ''; + + $aCores = explode(',', $aData['core_fix']); + + $cores = ''; + + foreach($aCores as $core) + { + $core = trim($core); + + if(!is_numeric($core)) + continue; + + if($core < 1) + continue; + + $cores .= intval($core).','; + } + + $cores = isset($cores{0}) ? substr($cores, 0, -1) : ''; + + $aData['core_fix'] = $cores; + + $aTime = explode(':', $aData['time']); + + $times = ''; + + foreach($aTime as $time) + { + $time = trim($time); + + if(!is_numeric($time)) + continue; + + $times .= intval($time).':'; + } + + $times = isset($times{0}) ? substr($times, 0, -1) : ''; + + $aData['time'] = $times; + + $aTimext = explode(':', $aData['timext']); + + $timexts = ''; + + foreach($aTimext as $timext) + { + $timext = trim($timext); + + if(!is_numeric($timext)) + continue; + + $timexts .= intval($timext).':'; + } + + $timexts = isset($timexts{0}) ? substr($timexts, 0, -1) : ''; + + $aData['timext'] = $timexts; + + $aFps = explode(':', $aData['fps']); + + $sfps = ''; + + foreach($aFps as $fps) + { + $fps = trim($fps); + + if(!is_numeric($fps)) + continue; + + $sfps .= intval($fps).':'; + } + + $sfps = isset($sfps{0}) ? substr($sfps, 0, -1) : ''; + + $aData['fps'] = $sfps; + + $aTick = explode(':', $aData['tickrate']); + + $stick = ''; + + foreach($aTick as $tick) + { + $tick = trim($tick); + + if(!is_numeric($tick)) + continue; + + $stick .= intval($tick).':'; + } + + $stick = isset($stick{0}) ? substr($stick, 0, -1) : ''; + + $aData['tickrate'] = $stick; + + $aRam = explode(':', $aData['ram']); + + $sram = ''; + + foreach($aRam as $ram) + { + $ram = trim($ram); + + if(!is_numeric($ram)) + continue; + + $sram .= intval($ram).':'; + } + + $sram = isset($sram{0}) ? substr($sram, 0, -1) : ''; + + $aData['ram'] = $sram; + + $aPrice = explode(':', $aData['price']); + + $sprice = ''; + + foreach($aPrice as $price) + { + $price = trim($price); + + if(!is_numeric($price)) + continue; + + $sprice .= $price.':'; + } + + $sprice = isset($sprice{0}) ? substr($sprice, 0, -1) : ''; + + $aData['price'] = $sprice; + + switch($aData['game']) + { + case 'cs': + if(count(explode(':', $aData['fps'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + break; + + case 'cssold': + $afps = explode(':', $aData['fps']); + $atick = explode(':', $aData['tickrate']); + $aprice = explode(':', $aData['price']); + + if((count($afps)*count($atick)) != count($aprice)) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + $price = array(); + + $i = 0; + + foreach($afps as $fps) + { + foreach($atick as $tick) + { + $price[$tick.'_'.$fps] = $aprice[$i]; + + $i+=1; + } + } + + $aData['price'] = sys::b64js($price); + + break; + + case 'css': + case 'csgo': + if(count(explode(':', $aData['tickrate'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + break; + + case 'mc': + if(count(explode(':', $aData['ram'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + } + + $access = array('ftp', 'plugins', 'console', 'stats', 'copy', 'web'); + + foreach($access as $section) + $aData[$section] = (string) $aData[$section] == 'on' ? '1' : '0'; + + $sql->query('INSERT INTO `tarifs` set' + .'`unit`="'.$aData['unit'].'",' + .'`game`="'.$aData['game'].'",' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`slots_min`="'.$aData['slots_min'].'",' + .'`slots_max`="'.$aData['slots_max'].'",' + .'`port_min`="'.$aData['port_min'].'",' + .'`port_max`="'.$aData['port_max'].'",' + .'`hostname`="'.htmlspecialchars($aData['hostname']).'",' + .'`packs`="'.$aData['packs'].'",' + .'`path`="'.addslashes($aData['path']).'",' + .'`install`="'.addslashes($aData['install']).'",' + .'`update`="'.addslashes($aData['update']).'",' + .'`fps`="'.$aData['fps'].'",' + .'`tickrate`="'.$aData['tickrate'].'",' + .'`ram`="'.$aData['ram'].'",' + .'`param_fix`="'.$aData['param_fix'].'",' + .'`time`="'.$aData['time'].'",' + .'`timext`="'.$aData['timext'].'",' + .'`test`="'.$aData['test'].'",' + .'`tests`="'.$aData['tests'].'",' + .'`discount`="'.$aData['discount'].'",' + .'`map`="'.addslashes($aData['map']).'",' + .'`ftp`="'.$aData['ftp'].'",' + .'`plugins`="'.$aData['plugins'].'",' + .'`console`="'.$aData['console'].'",' + .'`stats`="'.$aData['stats'].'",' + .'`copy`="'.$aData['copy'].'",' + .'`web`="'.$aData['web'].'",' + .'`plugins_install`="'.$aData['plugins_install'].'",' + .'`hdd`="'.$aData['hdd'].'",' + .'`autostop`="'.$aData['autostop'].'",' + .'`price`="'.$aData['price'].'",' + .'`core_fix`="'.$aData['core_fix'].'",' + .'`ip`="'.$aData['ip'].'",' + .'`show`="'.$aData['show'].'",' + .'`sort`="'.$aData['sort'].'"'); + + sys::outjs(array('s' => 'ok')); + } + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $html->get('add', 'sections/tarifs'); + + $html->set('units', $units); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/copy.php b/system/acp/sections/tarifs/copy.php new file mode 100644 index 0000000..4e6398c --- /dev/null +++ b/system/acp/sections/tarifs/copy.php @@ -0,0 +1,84 @@ +query('SELECT * FROM `tarifs` WHERE `id`="'.$id.'" LIMIT 1'); + $tarif = $sql->get(); + + $games = '' + .'' + .''; + + $fix = $tarif['param_fix'] ? '' : ''; + $test = $tarif['test'] ? '' : ''; + $discount = $tarif['discount'] ? '' : ''; + $autostop = $tarif['autostop'] ? '' : ''; + $show = $tarif['show'] ? '' : ''; + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $games = str_replace('"'.$tarif['game'].'"', '"'.$tarif['game'].'" selected="select"', $games); + + $html->get('copy', 'sections/tarifs'); + + if($tarif['game'] == 'cssold') + { + $sprice = ''; + + $aPrice = sys::b64djs($tarif['price']); + + foreach($aPrice as $price) + $sprice .= $price.':'; + + $sprice = isset($sprice{0}) ? substr($sprice, 0, -1) : ''; + + $tarif['price'] = $sprice; + } + + foreach($tarif as $field => $val) + $html->set($field, $val); + + $html->set('units', $units); + $html->set('games', $games); + $html->set('param_fix', $fix); + $html->set('test', $test); + $html->set('discount', $discount); + $html->set('autostop', $autostop); + $html->set('show', $show); + + foreach(array('ftp', 'plugins', 'console', 'stats', 'copy', 'web') as $section) + { + if($tarif[$section]) + $html->unit($section, 1); + else + $html->unit($section); + } + + $packs = ''; + + $aPacks = sys::b64djs($tarif['packs']); + + foreach($aPacks as $name => $fullname) + $packs .= '"'.$name.'":"'.$fullname.'",'; + + $packs = isset($packs{0}) ? substr($packs, 0, -1) : ''; + + $html->set('packs', $packs); + + $plugins = ''; + + $aPlugins = sys::b64djs($tarif['plugins_install']); + + foreach($aPlugins as $pack => $list) + $plugins .= '"'.$pack.'":"'.$list.'",'; + + $plugins = isset($plugins{0}) ? substr($plugins, 0, -1) : ''; + + $html->set('plugins_install', $plugins); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/delete.php b/system/acp/sections/tarifs/delete.php new file mode 100644 index 0000000..f551f28 --- /dev/null +++ b/system/acp/sections/tarifs/delete.php @@ -0,0 +1,12 @@ +query('SELECT `id` FROM `servers` WHERE `tarif`="'.$id.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Нельзя удалить тариф с серверами.')); + + $sql->query('DELETE FROM `tarifs` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/index.php b/system/acp/sections/tarifs/index.php new file mode 100644 index 0000000..e30964b --- /dev/null +++ b/system/acp/sections/tarifs/index.php @@ -0,0 +1,68 @@ + $sort); + } + + $list = ''; + + $sql->query('SELECT `id` FROM `tarifs`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/tarif'.$sort_page); + + $tarifs = $sql->query('SELECT `id`, `unit`, `game`, `name`, `slots_min`, `slots_max`, `port_min`, `port_max` FROM `tarifs` '.$sort_sql.' LIMIT '.$aPage['num'].', 20'); + while($tarif = $sql->get($tarifs)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $list .= ''; + $list .= ''.$tarif['id'].''; + $list .= ''.$tarif['name'].''; + $list .= '#'.$tarif['unit'].' '.$unit['name'].''; + $list .= ''.$tarif['slots_min'].'-'.$tarif['slots_max'].''; + $list .= ''.$tarif['port_min'].'-'.$tarif['port_max'].''; + $list .= ''.strtoupper($tarif['game']).''; + $list .= 'Копировать'; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/tarifs'); + + $html->set('sort_id', 'asc'); + $html->set('sort_unit', 'asc'); + $html->set('sort_game', 'asc'); + + if(isset($sort_icon)) + $html->set('sort_'.key($sort_icon), array_shift($sort_icon)); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/search.php b/system/acp/sections/tarifs/search.php new file mode 100644 index 0000000..c7d5552 --- /dev/null +++ b/system/acp/sections/tarifs/search.php @@ -0,0 +1,76 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if(substr($text, 0, 5) == 'game=') + { + $game = trim(substr($text, 5)); + + if(in_array($game, array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + $tarifs = $sql->query('SELECT `id`, `unit`, `game`, `name`, `slots_min`, `slots_max`, `port_min`, `port_max` FROM `tarifs` WHERE `game`="'.$game.'" ORDER BY `id` ASC'); + }elseif($text{0} == 'i' AND $text{1} == 'd') + $tarifs = $sql->query('SELECT `id`, `unit`, `game`, `name`, `slots_min`, `slots_max`, `port_min`, `port_max` FROM `tarifs` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`game` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`slots_min` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`slots_max` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`port_min` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`port_max` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $tarifs = $sql->query('SELECT `id`, `unit`, `game`, `name`, `slots_min`, `slots_max`, `port_min`, `port_max` FROM `tarifs` WHERE '.$like.' ORDER BY `id` ASC LIMIT 10'); + } + + if(!$sql->num($tarifs)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($tarif = $sql->get($tarifs)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $list .= ''; + $list .= ''.$tarif['id'].''; + $list .= ''.$tarif['name'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$tarif['slots_min'].'-'.$tarif['slots_max'].''; + $list .= ''.$tarif['port_min'].'-'.$tarif['port_max'].''; + $list .= ''.strtoupper($tarif['game']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/stats.php b/system/acp/sections/tarifs/stats.php new file mode 100644 index 0000000..329dd2c --- /dev/null +++ b/system/acp/sections/tarifs/stats.php @@ -0,0 +1,71 @@ +query('SELECT `id`, `unit`, `game`, `name` FROM `tarifs` ORDER BY `id` ASC'); + while($tarif = $sql->get($tarifs)) + { + $servers = $sql->query('SELECT `id`, `user` FROM `servers` WHERE `tarif`="'.$tarif['id'].'"'); + $all_servers = $sql->num($servers); + + $money_all = 0; + $money_month = 0; + + $time = date('j', $start_point)*86400; + + while($server = $sql->get($servers)) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$server['user'].'" AND `group`="user" LIMIT 1'); + if(!$sql->num()) + continue; + + $sql->query('SELECT `money`, `date` FROM `logs` WHERE `user`="'.$server['user'].'" AND (`type`="buy" OR `type`="extend") AND `text` LIKE \'%(сервер: #'.$server['id'].')%\''); + while($logs = $sql->get()) + { + $money_all += $logs['money']; + + if($logs['date'] >= ($start_point-$time)) + $money_month += $logs['money']; + } + } + + if($money_all < 1) + continue; + + $all_money += $money_all; + $all_money_month += $money_month; + + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$tarif['id'].'" AND `time`<"'.$start_point.'"'); + $overdue_servers = $sql->num(); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $list .= ''; + $list .= ''.$tarif['id'].''; + $list .= ''.$tarif['name'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$all_servers.' шт./'.$overdue_servers.' шт.'; + $list .= ''.$money_all.' '.$cfg['currency'].''; + $list .= ''.$money_month.' '.$cfg['currency'].''; + $list .= ''.strtoupper($tarif['game']).''; + $list .= ''; + } + + $html->get('stats', 'sections/tarifs'); + + $html->set('list', $list); + + $html->set('month', mb_strtolower(params::$aNameMonth[sys::int(date('n', $start_point))], 'UTF-8')); + + $html->set('all_money', $all_money); + $html->set('all_money_month', $all_money_month); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/tarifs/tarif.php b/system/acp/sections/tarifs/tarif.php new file mode 100644 index 0000000..b6c7bf6 --- /dev/null +++ b/system/acp/sections/tarifs/tarif.php @@ -0,0 +1,485 @@ +query('SELECT * FROM `tarifs` WHERE `id`="'.$id.'" LIMIT 1'); + $tarif = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : $tarif['name']; + $aData['unit'] = isset($_POST['unit']) ? sys::int($_POST['unit']) : $tarif['unit']; + $aData['game'] = isset($_POST['game']) ? trim($_POST['game']) : $tarif['game']; + $aData['slots'] = isset($_POST['slots']) ? trim($_POST['slots']) : $tarif['slots']; + $aData['posts'] = isset($_POST['posts']) ? trim($_POST['posts']) : $tarif['posts']; + $aData['hostname'] = isset($_POST['hostname']) ? trim($_POST['hostname']) : $tarif['hostname']; + $aData['packs'] = isset($_POST['packs']) ? trim($_POST['packs']) : $tarif['packs']; + $aData['path'] = isset($_POST['path']) ? trim($_POST['path']) : $tarif['path']; + $aData['install'] = isset($_POST['install']) ? trim($_POST['install']) : $tarif['install']; + $aData['update'] = isset($_POST['update']) ? trim($_POST['update']) : $tarif['update']; + $aData['fps'] = isset($_POST['fps']) ? trim($_POST['fps']) : $tarif['fps']; + $aData['tickrate'] = isset($_POST['tickrate']) ? trim($_POST['tickrate']) : $tarif['tickrate']; + $aData['ram'] = isset($_POST['ram']) ? trim($_POST['ram']) : $tarif['ram']; + $aData['param_fix'] = isset($_POST['param_fix']) ? trim($_POST['param_fix']) : $tarif['param_fix']; + $aData['time'] = isset($_POST['time']) ? trim($_POST['time']) : $tarif['time']; + $aData['timext'] = isset($_POST['timext']) ? trim($_POST['timext']) : $tarif['timext']; + $aData['test'] = isset($_POST['test']) ? sys::int($_POST['test']) : $tarif['test']; + $aData['tests'] = isset($_POST['tests']) ? sys::int($_POST['tests']) : $tarif['tests']; + $aData['discount'] = isset($_POST['discount']) ? sys::int($_POST['discount']) : $tarif['discount']; + $aData['map'] = isset($_POST['map']) ? trim($_POST['map']) : $tarif['map']; + $aData['ftp'] = isset($_POST['ftp']) ? $_POST['ftp'] : $tarif['ftp']; + $aData['plugins'] = isset($_POST['plugins']) ? $_POST['plugins'] : $tarif['plugins']; + $aData['console'] = isset($_POST['console']) ? $_POST['console'] : $tarif['console']; + $aData['stats'] = isset($_POST['stats']) ? $_POST['stats'] : $tarif['stats']; + $aData['copy'] = isset($_POST['copy']) ? $_POST['copy'] : $tarif['copy']; + $aData['web'] = isset($_POST['web']) ? $_POST['web'] : $tarif['web']; + $aData['plugins_install'] = isset($_POST['plugins_install']) ? trim($_POST['plugins_install']) : $tarif['plugins_install']; + $aData['hdd'] = isset($_POST['hdd']) ? sys::int($_POST['hdd']) : $tarif['hdd']; + $aData['autostop'] = isset($_POST['autostop']) ? sys::int($_POST['autostop']) : $tarif['autostop']; + $aData['price'] = isset($_POST['price']) ? trim($_POST['price']) : $tarif['price']; + $aData['core_fix'] = isset($_POST['core_fix']) ? trim($_POST['core_fix']) : $tarif['core_fix']; + $aData['ip'] = isset($_POST['ip']) ? trim($_POST['ip']) : $tarif['ip']; + $aData['show'] = isset($_POST['show']) ? sys::int($_POST['show']) : $tarif['show']; + $aData['sort'] = isset($_POST['sort']) ? sys::int($_POST['sort']) : $tarif['sort']; + + if($aData['name'] == '') + sys::outjs(array('e' => 'Необходимо указать название')); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$aData['unit'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо указать локацию')); + + if(!in_array($aData['game'], array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + sys::outjs(array('e' => 'Необходимо указать игру')); + + $aSlots = explode('-', $aData['slots']); + + if(!isset($aSlots[0]) || !isset($aSlots[1])) + sys::outjs(array('e' => 'Необходимо указать слоты')); + + $aSlots[0] = trim($aSlots[0]); + $aSlots[1] = trim($aSlots[1]); + + $aData['slots_min'] = $aSlots[0] > 1 ? $aSlots[0] : sys::outjs(array('e' => 'Неправильно указаны слоты')); + $aData['slots_max'] = $aSlots[1] >= $aSlots[0] ? $aSlots[1] : sys::outjs(array('e' => 'Неправильно указаны слоты')); + + $aPorts = explode('-', $aData['posts']); + + if(!isset($aPorts[0]) || !isset($aPorts[1])) + sys::outjs(array('e' => 'Необходимо указать порты')); + + $aPorts[0] = trim($aPorts[0]); + $aPorts[1] = trim($aPorts[1]); + + $aData['port_min'] = $aPorts[0] > 1 ? $aPorts[0] : sys::outjs(array('e' => 'Неправильно указаны порты')); + $aData['port_max'] = $aPorts[1] >= $aPorts[0] ? $aPorts[1] : sys::outjs(array('e' => 'Неправильно указаны порты')); + + if($aData['hostname'] == '') + sys::outjs(array('e' => 'Необходимо указать название сервера')); + + if($aData['path'] == '') + sys::outjs(array('e' => 'Необходимо указать путь до сборок')); + + if($aData['install'] == '') + sys::outjs(array('e' => 'Необходимо указать путь для установки серверов')); + + if($aData['update'] == '' AND !in_array($aData['game'], array('css', 'csgo'))) + sys::outjs(array('e' => 'Необходимо указать путь до обновления сборки')); + + if(substr($aData['path'], -1) != '/' || substr($aData['install'], -1) != '/' || (substr($aData['update'], -1) != '/' AND !in_array($aData['game'], array('css', 'csgo')))) + sys::outjs(array('e' => 'Пути должны заканчиваться символом "/"')); + + $int = array( + 'Тестов' => 'tests', + 'Положение' => 'sort', + 'Диск' => 'hdd' + ); + + foreach($int as $name => $input) + { + if($aData[$input] == '') + sys::outjs(array('e' => 'Необходимо указать поле "'.$name.'"')); + } + + $aPacks = explode(',', $aData['packs']); + + $packs = array(); + + foreach($aPacks as $pack) + { + $aPack = explode(':', trim($pack)); + + if(!isset($aPack[0]) || !isset($aPack[1])) + continue; + + $name = str_replace('"', '', $aPack[0]); + $fullname = str_replace('"', '', $aPack[1]); + + $packs[trim($name)] = trim($fullname); + } + + if(!count($packs)) + sys::outjs(array('e' => 'Необходимо указать минимум одну сборку')); + + $aData['packs'] = sys::b64js($packs); + + $aIp = explode(':', $aData['ip']); + + $ips = ''; + + foreach($aIp as $ip) + { + $ip = trim($ip); + + if(sys::valid($ip, 'ip')) + continue; + + $ips .= $ip.':'; + } + + $ips = isset($ips{0}) ? substr($ips, 0, -1) : ''; + + $aData['ip'] = $ips; + + $aPlugins = explode('","', $aData['plugins_install']); + + $plugins = array(); + + foreach($aPlugins as $plugin) + { + $aPlugin = explode(':', trim($plugin)); + + if(!isset($aPlugin[0]) || !isset($aPlugin[1])) + continue; + + $name = trim(str_replace('"', '', $aPlugin[0])); + + if(!isset($packs[$name])) + continue; + + $aList = explode(',', str_replace('"', '', $aPlugin[1])); + + $list = ''; + + foreach($aList as $pid) + { + $pid = trim($pid); + + if(!is_numeric($pid)) + continue; + + $list .= intval($pid).','; + } + + $list = isset($list{0}) ? substr($list, 0, -1) : ''; + + if($list == '') + continue; + + $plugins[$name] = $list; + } + + $aData['plugins_install'] = count($plugins) ? sys::b64js($plugins) : ''; + + $aCores = explode(',', $aData['core_fix']); + + $cores = ''; + + foreach($aCores as $core) + { + $core = trim($core); + + if(!is_numeric($core)) + continue; + + if($core < 1) + continue; + + $cores .= intval($core).','; + } + + $cores = isset($cores{0}) ? substr($cores, 0, -1) : ''; + + $aData['core_fix'] = $cores; + + $aTime = explode(':', $aData['time']); + + $times = ''; + + foreach($aTime as $time) + { + $time = trim($time); + + if(!is_numeric($time)) + continue; + + $times .= intval($time).':'; + } + + $times = isset($times{0}) ? substr($times, 0, -1) : ''; + + $aData['time'] = $times; + + $aTimext = explode(':', $aData['timext']); + + $timexts = ''; + + foreach($aTimext as $timext) + { + $timext = trim($timext); + + if(!is_numeric($timext)) + continue; + + $timexts .= intval($timext).':'; + } + + $timexts = isset($timexts{0}) ? substr($timexts, 0, -1) : ''; + + $aData['timext'] = $timexts; + + $aFps = explode(':', $aData['fps']); + + $sfps = ''; + + foreach($aFps as $fps) + { + $fps = trim($fps); + + if(!is_numeric($fps)) + continue; + + $sfps .= intval($fps).':'; + } + + $sfps = isset($sfps{0}) ? substr($sfps, 0, -1) : ''; + + $aData['fps'] = $sfps; + + $aTick = explode(':', $aData['tickrate']); + + $stick = ''; + + foreach($aTick as $tick) + { + $tick = trim($tick); + + if(!is_numeric($tick)) + continue; + + $stick .= intval($tick).':'; + } + + $stick = isset($stick{0}) ? substr($stick, 0, -1) : ''; + + $aData['tickrate'] = $stick; + + $aRam = explode(':', $aData['ram']); + + $sram = ''; + + foreach($aRam as $ram) + { + $ram = trim($ram); + + if(!is_numeric($ram)) + continue; + + $sram .= intval($ram).':'; + } + + $sram = isset($sram{0}) ? substr($sram, 0, -1) : ''; + + $aData['ram'] = $sram; + + $aPrice = explode(':', $aData['price']); + + $sprice = ''; + + foreach($aPrice as $price) + { + $price = trim($price); + + if(!is_numeric($price)) + continue; + + $sprice .= $price.':'; + } + + $sprice = isset($sprice{0}) ? substr($sprice, 0, -1) : ''; + + $aData['price'] = $sprice; + + switch($aData['game']) + { + case 'cs': + if(count(explode(':', $aData['fps'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + break; + + case 'cssold': + $afps = explode(':', $aData['fps']); + $atick = explode(':', $aData['tickrate']); + $aprice = explode(':', $aData['price']); + + if((count($afps)*count($atick)) != count($aprice)) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + $price = array(); + + $i = 0; + + foreach($afps as $fps) + { + foreach($atick as $tick) + { + $price[$tick.'_'.$fps] = $aprice[$i]; + + $i+=1; + } + } + + $aData['price'] = sys::b64js($price); + + break; + + case 'css': + case 'csgo': + if(count(explode(':', $aData['tickrate'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + break; + + case 'mc': + if(count(explode(':', $aData['ram'])) != count(explode(':', $aData['price']))) + sys::outjs(array('e' => 'Неправильно указано поле "Цена"')); + + } + + $access = array('ftp', 'plugins', 'console', 'stats', 'copy', 'web'); + + foreach($access as $section) + $aData[$section] = (string) $aData[$section] == 'on' ? '1' : '0'; + + $sql->query('UPDATE `tarifs` set' + .'`unit`="'.$aData['unit'].'",' + .'`game`="'.$aData['game'].'",' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`slots_min`="'.$aData['slots_min'].'",' + .'`slots_max`="'.$aData['slots_max'].'",' + .'`port_min`="'.$aData['port_min'].'",' + .'`port_max`="'.$aData['port_max'].'",' + .'`hostname`="'.htmlspecialchars($aData['hostname']).'",' + .'`packs`="'.$aData['packs'].'",' + .'`path`="'.addslashes($aData['path']).'",' + .'`install`="'.addslashes($aData['install']).'",' + .'`update`="'.addslashes($aData['update']).'",' + .'`fps`="'.$aData['fps'].'",' + .'`tickrate`="'.$aData['tickrate'].'",' + .'`ram`="'.$aData['ram'].'",' + .'`param_fix`="'.$aData['param_fix'].'",' + .'`time`="'.$aData['time'].'",' + .'`timext`="'.$aData['timext'].'",' + .'`test`="'.$aData['test'].'",' + .'`tests`="'.$aData['tests'].'",' + .'`discount`="'.$aData['discount'].'",' + .'`map`="'.addslashes($aData['map']).'",' + .'`ftp`="'.$aData['ftp'].'",' + .'`plugins`="'.$aData['plugins'].'",' + .'`console`="'.$aData['console'].'",' + .'`stats`="'.$aData['stats'].'",' + .'`copy`="'.$aData['copy'].'",' + .'`web`="'.$aData['web'].'",' + .'`plugins_install`="'.$aData['plugins_install'].'",' + .'`hdd`="'.$aData['hdd'].'",' + .'`autostop`="'.$aData['autostop'].'",' + .'`price`="'.$aData['price'].'",' + .'`core_fix`="'.$aData['core_fix'].'",' + .'`ip`="'.$aData['ip'].'",' + .'`show`="'.$aData['show'].'",' + .'`sort`="'.$aData['sort'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $games = '' + .'' + .''; + + $fix = $tarif['param_fix'] ? '' : ''; + $test = $tarif['test'] ? '' : ''; + $discount = $tarif['discount'] ? '' : ''; + $autostop = $tarif['autostop'] ? '' : ''; + $show = $tarif['show'] ? '' : ''; + + $units = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + $units .= ''; + + $units = str_replace('"'.$tarif['unit'].'"', '"'.$tarif['unit'].'" selected="select"', $units); + $games = str_replace('"'.$tarif['game'].'"', '"'.$tarif['game'].'" selected="select"', $games); + + $html->get('tarif', 'sections/tarifs'); + + if($tarif['game'] == 'cssold') + { + $sprice = ''; + + $aPrice = sys::b64djs($tarif['price']); + + foreach($aPrice as $price) + $sprice .= $price.':'; + + $sprice = isset($sprice{0}) ? substr($sprice, 0, -1) : ''; + + $tarif['price'] = $sprice; + } + + foreach($tarif as $field => $val) + $html->set($field, $val); + + $html->set('units', $units); + $html->set('games', $games); + $html->set('param_fix', $fix); + $html->set('test', $test); + $html->set('discount', $discount); + $html->set('autostop', $autostop); + $html->set('show', $show); + + foreach(array('ftp', 'plugins', 'console', 'stats', 'copy', 'web') as $section) + { + if($tarif[$section]) + $html->unit($section, 1); + else + $html->unit($section); + } + + $packs = ''; + + $aPacks = sys::b64djs($tarif['packs']); + + foreach($aPacks as $name => $fullname) + $packs .= '"'.$name.'":"'.$fullname.'",'; + + $packs = isset($packs{0}) ? substr($packs, 0, -1) : ''; + + $html->set('packs', $packs); + + $plugins = ''; + + $aPlugins = sys::b64djs($tarif['plugins_install']); + + foreach($aPlugins as $pack => $list) + $plugins .= '"'.$pack.'":"'.$list.'",'; + + $plugins = isset($plugins{0}) ? substr($plugins, 0, -1) : ''; + + $html->set('plugins_install', $plugins); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/units/add.php b/system/acp/sections/units/add.php new file mode 100644 index 0000000..74c7c5c --- /dev/null +++ b/system/acp/sections/units/add.php @@ -0,0 +1,69 @@ + 'Необходимо заполнить все поля')); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($aData['passwd'], $aData['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с локацией')); + + $sql->query('INSERT INTO `units` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`address`="'.$aData['address'].'",' + .'`passwd`="'.$aData['passwd'].'",' + .'`sql_login`="'.$aData['sql_login'].'",' + .'`sql_passwd`="'.$aData['sql_passwd'].'",' + .'`sql_port`="'.$aData['sql_port'].'",' + .'`sql_ftp`="'.$aData['sql_ftp'].'",' + .'`cs`="'.$aData['cs'].'",' + .'`cssold`="'.$aData['cssold'].'",' + .'`css`="'.$aData['css'].'",' + .'`csgo`="'.$aData['csgo'].'",' + .'`samp`="'.$aData['samp'].'",' + .'`crmp`="'.$aData['crmp'].'",' + .'`mta`="'.$aData['mta'].'",' + .'`mc`="'.$aData['mc'].'",' + .'`ram`="'.$aData['ram'].'",' + .'`test`="'.$aData['test'].'",' + .'`show`="'.$aData['show'].'",' + .'`sort`="'.$aData['sort'].'",' + .'`domain`="'.$aData['domain'].'"'); + + sys::outjs(array('s' => $sql->id())); + } + + $html->get('add', 'sections/units'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/units/delete.php b/system/acp/sections/units/delete.php new file mode 100644 index 0000000..6d3ac17 --- /dev/null +++ b/system/acp/sections/units/delete.php @@ -0,0 +1,67 @@ +query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + sys::outjs(array('e' => 'PANEL не удалось создать связь.')); + + $servers = $sql->query('SELECT `id`, `user`, `game` FROM `servers` WHERE `unit`="'.$id.'"'); + while($server = $sql->get($servers)) + { + $crons = $sql->query('SELECT `id`, `cron` FROM `crontab` WHERE `server`="'.$server['id'].'"'); + while($cron = $sql->get($crons)) + { + $ssh->set('echo "" >> /etc/crontab && cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab"); + $ssh->set('crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `crontab` WHERE `id`="'.$cron['id'].'" LIMIT 1'); + } + + $helps = $sql->query('SELECT `id` FROM `help` WHERE `type`="server" AND `service`="'.$server['id'].'"'); + while($help = $sql->get($helps)) + { + $sql->query('DELETE FROM `help_dialogs` WHERE `help`="'.$help['id'].'"'); + $sql->query('DELETE FROM `help` WHERE `id`="'.$help['id'].'" LIMIT 1'); + } + + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$server['id'].'" LIMIT 1'); + $sql->query('DELETE FROM `address_buy` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `logs_sys` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `owners` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `copy` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `graph` WHERE `server`="'.$server['id'].'" LIMIT 1'); + $sql->query('DELETE FROM `graph_day` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `graph_hour` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `web` WHERE `server`="'.$server['id'].'"'); + } + + $sql->query('DELETE FROM `address` WHERE `unit`="'.$id.'"'); + $sql->query('DELETE FROM `tarifs` WHERE `unit`="'.$id.'"'); + }else{ + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$id.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Нельзя удалить локацию с серверами.')); + } + + $sql->query('DELETE FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/units/index.php b/system/acp/sections/units/index.php new file mode 100644 index 0000000..54d94d5 --- /dev/null +++ b/system/acp/sections/units/index.php @@ -0,0 +1,29 @@ +query('SELECT `id`, `name`, `address`, `show`, `domain` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + { + $list .= ''; + $list .= ''.$unit['id'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$unit['address'].''; + $list .= ''.($unit['show'] == '1' ? 'Доступна' : 'Недоступна').''; + $list .= ''.$unit['domain'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/units'); + + $html->set('list', $list); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/units/loading.php b/system/acp/sections/units/loading.php new file mode 100644 index 0000000..958af65 --- /dev/null +++ b/system/acp/sections/units/loading.php @@ -0,0 +1,103 @@ +query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(isset($url['service']) AND in_array($url['service'], array('apache2', 'nginx', 'mysql', 'unit', 'geo', 'ungeo'))) + { + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с локацией')); + + switch($url['service']) + { + case 'unit': + $ssh->set('screen -dmS reboot reboot'); + break; + + case 'geo': + $ssh->set('iptables-restore < /etc/firewall/geo.conf; iptables-restore << '.$cfg['iptables']); + + $sql->query('UPDATE `units` set `ddos`="1" WHERE `id`="'.$id.'" LIMIT 1'); + break; + + case 'ungeo': + $ssh->set('iptables-restore < /etc/firewall/ungeo.conf; iptables-restore << '.$cfg['iptables'].'; iptables-restore << /root/'.$cfg['iptables'].'_geo'); + + $sql->query('UPDATE `units` set `ddos`="0" WHERE `id`="'.$id.'" LIMIT 1'); + break; + + default: + $ssh->set('screen -dmS sr_'.$url['service'].' service '.$url['service'].' restart'); + } + + sys::outjs(array('s' => 'ok')); + } + + $aData = array( + 'cpu' => '0%', + 'ram' => '0%', + 'hdd' => '0%', + 'apache' => 'unknown', + 'nginx' => 'unknown', + 'mysql' => 'unknown', + 'uptime' => 'unknown', + 'ssh' => 'error' + ); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs($aData); + + $aData['ssh'] = ''; + + $stat_ram = $ssh->get('echo `cat /proc/meminfo | grep MemTotal | awk \'{print $2}\'; cat /proc/meminfo | grep MemFree | awk \'{print $2}\'; cat /proc/meminfo | grep Buffers | awk \'{print $2}\'; cat /proc/meminfo | grep Cached | grep -v SwapCached | awk \'{print $2}\'`'); + $aData['ram'] = ceil(sys::ram_load($stat_ram)).'%'; + + $aData['hdd'] = $ssh->get('df -P / | awk \'{print $5}\' | tail -1'); + + $aData['apache'] = sys::status($ssh->get('service apache2 status')) ? 'Работает' : 'Поднять'; + $aData['nginx'] = sys::status($ssh->get('service nginx status')) ? 'Работает' : 'Поднять'; + $aData['mysql'] = sys::status($ssh->get('service mysql status')) ? 'Работает' : 'Поднять'; + + $time = ceil($ssh->get('cat /proc/uptime | awk \'{print $1}\'')); + $aData['uptime'] = sys::uptime_load($time); + + $aData['cpu'] = sys::cpu_load($ssh->get('echo "`ps -A -o pcpu | tail -n+2 | paste -sd+ | bc | awk \'{print $0}\'` `cat /proc/cpuinfo | grep processor | wc -l | awk \'{print $1}\'`"')).'%'; + + sys::outjs($aData); + } + + $loads = ''; + $list = ''; + + $sql->query('SELECT `id`, `name` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get()) + { + $list .= ''; + $list .= ''.$unit['id'].''; + $list .= ''.$unit['name'].''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + $list .= ''; + + $loads .= 'units_load(\''.$unit['id'].'\', false);'; + } + + $html->get('loading', 'sections/units'); + + $html->set('list', $list); + $html->set('loads', $loads); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/units/stats.php b/system/acp/sections/units/stats.php new file mode 100644 index 0000000..90bfa46 --- /dev/null +++ b/system/acp/sections/units/stats.php @@ -0,0 +1,65 @@ +query('SELECT `id`, `name`, `show` FROM `units` ORDER BY `id` ASC'); + while($unit = $sql->get($units)) + { + $servers = $sql->query('SELECT `id`, `user` FROM `servers` WHERE `unit`="'.$unit['id'].'"'); + $all_servers = $sql->num($servers); + + $money_all = 0; + $money_month = 0; + + $time = date('j', $start_point)*86400; + + while($server = $sql->get($servers)) + { + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$server['user'].'" AND `group`="user" LIMIT 1'); + if(!$sql->num()) + continue; + + $sql->query('SELECT `money`, `date` FROM `logs` WHERE `user`="'.$server['user'].'" AND (`type`="buy" OR `type`="extend") AND `text` LIKE \'%(сервер: #'.$server['id'].')%\''); + while($logs = $sql->get()) + { + $money_all += $logs['money']; + + if($logs['date'] >= ($start_point-$time)) + $money_month += $logs['money']; + } + } + + $all_money += $money_all; + $all_money_month += $money_month; + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$unit['id'].'" AND `time`<"'.$start_point.'"'); + $overdue_servers = $sql->num(); + + $list .= ''; + $list .= ''.$unit['id'].''; + $list .= ''.$unit['name'].''; + $list .= ''.($unit['show'] == '1' ? 'Доступна' : 'Недоступна').''; + $list .= ''.$all_servers.' шт.'; + $list .= ''.$overdue_servers.' шт.'; + $list .= ''.$money_all.' '.$cfg['currency'].''; + $list .= ''.$money_month.' '.$cfg['currency'].''; + $list .= ''; + } + + $html->get('stats', 'sections/units'); + + $html->set('list', $list); + + $html->set('month', mb_strtolower(params::$aNameMonth[sys::int(date('n', $start_point))], 'UTF-8')); + + $html->set('all_money', $all_money); + $html->set('all_money_month', $all_money_month); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/units/unit.php b/system/acp/sections/units/unit.php new file mode 100644 index 0000000..d8c6fc4 --- /dev/null +++ b/system/acp/sections/units/unit.php @@ -0,0 +1,85 @@ +query('SELECT * FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : $unit['name']; + $aData['address'] = isset($_POST['address']) ? trim($_POST['address']) : $unit['address']; + $aData['passwd'] = isset($_POST['passwd']) ? trim($_POST['passwd']) : $unit['passwd']; + $aData['sql_login'] = isset($_POST['sql_login']) ? trim($_POST['sql_login']) : $unit['sql_login']; + $aData['sql_passwd'] = isset($_POST['sql_passwd']) ? trim($_POST['sql_passwd']) : $unit['sql_passwd']; + $aData['sql_port'] = isset($_POST['sql_port']) ? sys::int($_POST['sql_port']) : $unit['sql_port']; + $aData['sql_ftp'] = isset($_POST['sql_ftp']) ? trim($_POST['sql_ftp']) : $unit['sql_ftp']; + $aData['cs'] = isset($_POST['cs']) ? $_POST['cs'] : $unit['cs']; + $aData['cssold'] = isset($_POST['cssold']) ? $_POST['cssold'] : $unit['cssold']; + $aData['css'] = isset($_POST['css']) ? $_POST['css'] : $unit['css']; + $aData['csgo'] = isset($_POST['csgo']) ? $_POST['csgo'] : $unit['csgo']; + $aData['samp'] = isset($_POST['samp']) ? $_POST['samp'] : $unit['samp']; + $aData['crmp'] = isset($_POST['crmp']) ? $_POST['crmp'] : $unit['crmp']; + $aData['mta'] = isset($_POST['mta']) ? $_POST['mta'] : $unit['mta']; + $aData['mc'] = isset($_POST['mc']) ? $_POST['mc'] : $unit['mc']; + $aData['ram'] = isset($_POST['ram']) ? sys::int($_POST['ram']) : $unit['ram']; + $aData['test'] = isset($_POST['test']) ? sys::int($_POST['test']) : $unit['test']; + $aData['show'] = isset($_POST['show']) ? $_POST['show'] : $unit['show']; + $aData['sort'] = isset($_POST['sort']) ? sys::int($_POST['sort']) : $unit['sort']; + $aData['domain'] = isset($_POST['domain']) ? trim($_POST['domain']) : $unit['domain']; + + foreach(array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc') as $game) + $aData[$game] = (string) $aData[$game] == 'on' ? '1' : '0'; + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($aData['passwd'], $aData['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с локацией')); + + $sql->query('UPDATE `units` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`address`="'.$aData['address'].'",' + .'`passwd`="'.$aData['passwd'].'",' + .'`sql_login`="'.$aData['sql_login'].'",' + .'`sql_passwd`="'.$aData['sql_passwd'].'",' + .'`sql_port`="'.$aData['sql_port'].'",' + .'`sql_ftp`="'.$aData['sql_ftp'].'",' + .'`cs`="'.$aData['cs'].'",' + .'`cssold`="'.$aData['cssold'].'",' + .'`css`="'.$aData['css'].'",' + .'`csgo`="'.$aData['csgo'].'",' + .'`samp`="'.$aData['samp'].'",' + .'`crmp`="'.$aData['crmp'].'",' + .'`mta`="'.$aData['mta'].'",' + .'`mc`="'.$aData['mc'].'",' + .'`ram`="'.$aData['ram'].'",' + .'`test`="'.$aData['test'].'",' + .'`show`="'.$aData['show'].'",' + .'`sort`="'.$aData['sort'].'",' + .'`domain`="'.$aData['domain'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => $id)); + } + + $html->get('unit', 'sections/units'); + + foreach($unit as $i => $val) + $html->set($i, $val); + + foreach(array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc') as $game) + { + if($unit[$game]) + $html->unit('game_'.$game, 1); + else + $html->unit('game_'.$game); + } + + $html->set('show', $unit['show'] == 1 ? '' : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/users/action.php b/system/acp/sections/users/action.php new file mode 100644 index 0000000..0e10076 --- /dev/null +++ b/system/acp/sections/users/action.php @@ -0,0 +1,164 @@ + 'логина', + 'mail' => 'почты' + ); + + $arr_other_null = array( + 'name' => 'имени', + 'lastname' => 'фамилии', + 'patronymic' => 'отчества', + 'contacts' => 'контактов', + 'phone' => 'номера' + ); + + foreach($arr_other as $input => $name) + if(sys::valid($aData[$input], 'other', $aValid[$input])) + sys::outjs(array('e' => 'Неправильный формат '.$name)); + + foreach($arr_other as $input => $name) + { + if($aData[$input] == '') + continue; + + if(sys::valid($aData[$input], 'other', $aValid[$input])) + sys::outjs(array('e' => 'Неправильный формат '.$name)); + } + + $sql->query('SELECT `id` FROM `users` WHERE `id`!="'.$id.'" AND `login`="'.$aData['login'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Логин занят другим пользователем')); + + $sql->query('SELECT `id` FROM `users` WHERE `id`!="'.$id.'" AND `mail`="'.$aData['mail'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Почта занята другим пользователем')); + + if($aData['contacts'] != '') + { + $sql->query('SELECT `id` FROM `users` WHERE `id`!="'.$id.'" AND `contacts`="'.$aData['contacts'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Контакты заняты другим пользователем')); + } + + if($aData['phone'] != '') + { + $sql->query('SELECT `id` FROM `users` WHERE `id`!="'.$id.'" AND `phone`="'.$aData['phone'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Номер занят другим пользователем')); + } + + if($aData['passwd'] != '') + { + if(sys::valid($aData['passwd'], 'other', $aValid['passwd'])) + sys::outjs(array('e' => 'Неправильный формат пароля')); + + $aData['passwd'] = sys::passwdkey($aData['passwd']); + }else + $aData['passwd'] = $us['passwd']; + + $aData['help'] = $aData['help'] == 0 ? 0 : 1; + $aData['confirm_phone'] = $aData['confirm_phone'] == 0 ? 0 : 1; + $aData['group'] = in_array($aData['group'], array('user', 'support', 'admin')) ? $aData['group'] : $us['group']; + $aData['level'] = in_array($aData['level'], array(0, 1, 2)) ? $aData['level'] : $us['level']; + + if($aData['support_info'] != '' AND sys::valid($aData['support_info'], 'other', $aValid['support_info'])) + sys::outjs(array('e' => 'Неправильный формат подписи')); + + if($aData['balance'] == '') $aData['balance'] = 0; + + if(!is_numeric($aData['balance'])) + sys::outjs(array('e' => 'Неправильный формат баланса')); + + if(!is_numeric($aData['part_money'])) + sys::outjs(array('e' => 'Неправильный формат заработанных средств')); + + if($aData['replenish'] > 0) + { + if(!is_numeric($aData['replenish'])) + sys::outjs(array('e' => 'Неправильный формат суммы пополнения')); + + $aData['balance'] += $aData['replenish']; + + $sql->query('INSERT INTO `logs` set `user`="'.$id.'", `text`="Пополнение баланса на сумму: '.$aData['replenish'].' '.$cfg['currency'].' (прямой платеж)", `date`="'.$start_point.'", `type`="replenish", `money`="'.$aData['replenish'].'"'); + } + + if($aData['part_money'] < $us['part_money']) + { + $cashout = round($us['part_money']-$aData['part_money'], 2); + + $sql->query('INSERT INTO `logs` set `user`="'.$id.'", `text`="Вывод заработанных средств: '.$cashout.' '.$cfg['currency'].'", `date`="'.$start_point.'", `type`="cashout", `money`="'.$cashout.'"'); + } + + if($aData['rental']) + { + $rental = sys::int($aData['rental']); + + if($rental) + $aData['rental'] = strpos($aData['rental'], '%') ? $rental.'%' : $rental; + else + $aData['rental'] = 0; + }else + $aData['rental'] = 0; + + if(strlen($aData['rental']) > 4) + sys::outjs(array('e' => 'Неправильно указана скидка на аренду')); + + if($aData['extend']) + { + $extend = sys::int($aData['extend']); + + if($extend) + $aData['extend'] = strpos($aData['extend'], '%') ? $extend.'%' : $extend; + else + $aData['extend'] = 0; + }else + $aData['extend'] = 0; + + if(strlen($aData['extend']) > 4) + sys::outjs(array('e' => 'Неправильно указана скидка на аренду')); + + $sql->query('UPDATE `users` set ' + .'`login`="'.$aData['login'].'",' + .'`mail`="'.$aData['mail'].'",' + .'`passwd`="'.$aData['passwd'].'",' + .'`name`="'.$aData['name'].'",' + .'`lastname`="'.$aData['lastname'].'",' + .'`patronymic`="'.$aData['patronymic'].'",' + .'`balance`="'.$aData['balance'].'",' + .'`part_money`="'.$aData['part_money'].'",' + .'`group`="'.$aData['group'].'",' + .'`support_info`="'.$aData['support_info'].'",' + .'`level`="'.$aData['level'].'",' + .'`contacts`="'.$aData['contacts'].'",' + .'`phone`="'.$aData['phone'].'",' + .'`confirm_phone`="'.$aData['confirm_phone'].'",' + .'`help`="'.$aData['help'].'",' + .'`rental`="'.$aData['rental'].'",' + .'`extend`="'.$aData['extend'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/users/delete.php b/system/acp/sections/users/delete.php new file mode 100644 index 0000000..0b5d18b --- /dev/null +++ b/system/acp/sections/users/delete.php @@ -0,0 +1,38 @@ +query('DELETE FROM `auth` WHERE `user`="'.$id.'"'); + $sql->query('DELETE FROM `logs` WHERE `user`="'.$id.'"'); + + $helps = $sql->query('SELECT `id` FROM `help` WHERE `user`="'.$id.'"'); + while($help = $sql->get($helps)) + { + $sql->query('DELETE FROM `help_dialogs` WHERE `help`="'.$help['id'].'"'); + $sql->query('DELETE FROM `help` WHERE `id`="'.$help['id'].'" LIMIT 1'); + } + + $uploads = $sql->query('SELECT `id`, `name` FROM `help_upload` WHERE `user`="'.$id.'"'); + while($upload = $sql->get($uploads)) + { + @unlink(ROOT.'upload/'.$upload['name']); + + $sql->query('DELETE FROM `help_upload` WHERE `id`="'.$upload['id'].'" LIMIT 1'); + } + + $sql->query('DELETE FROM `logs_sys` WHERE `user`="'.$id.'"'); + $sql->query('DELETE FROM `owners` WHERE `user`="'.$id.'"'); + $sql->query('DELETE FROM `promo_use` WHERE `user`="'.$id.'"'); + $sql->query('DELETE FROM `recovery` WHERE `user`="'.$id.'"'); + $sql->query('DELETE FROM `security` WHERE `user`="'.$id.'"'); + + $sql->query('UPDATE `servers` set `user`="0" WHERE `user`="'.$id.'"'); + $sql->query('UPDATE `web` set `user`="0" WHERE `user`="'.$id.'"'); + } + + $sql->query('DELETE FROM `users` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/users/index.php b/system/acp/sections/users/index.php new file mode 100644 index 0000000..28e8f47 --- /dev/null +++ b/system/acp/sections/users/index.php @@ -0,0 +1,65 @@ + $sort); + } + + $list = ''; + + $aGroup = array('user' => 'Пользователь', 'support' => 'Тех. поддержка', 'admin' => 'Администратор'); + + $sql->query('SELECT `id` FROM `users`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/users'.$sort_page); + + $sql->query('SELECT `id`, `login`, `mail`, `balance`, `group` FROM `users` '.$sort_sql.' LIMIT '.$aPage['num'].', 20'); + while($us = $sql->get()) + { + $list .= ''; + $list .= ''.$us['id'].''; + $list .= ''.$us['login'].''; + $list .= ''.$us['mail'].''; + $list .= ''.$us['balance'].' '.$cfg['currency'].''; + $list .= ''.$aGroup[$us['group']].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/users'); + + $html->set('sort_id', 'asc'); + $html->set('sort_balance', 'asc'); + $html->set('sort_group', 'asc'); + + if(isset($sort_icon)) + $html->set('sort_'.key($sort_icon), array_shift($sort_icon)); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/users/offline.php b/system/acp/sections/users/offline.php new file mode 100644 index 0000000..658bca1 --- /dev/null +++ b/system/acp/sections/users/offline.php @@ -0,0 +1,34 @@ + 'Пользователь', 'support' => 'Тех. поддержка', 'admin' => 'Администратор'); + + $sql->query('SELECT `id` FROM `users` WHERE `time`<"'.($start_point-181).'"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/users/section'); + + $sql->query('SELECT `id`, `login`, `mail`, `group`, `time` FROM `users` WHERE `time`<"'.($start_point-181).'" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($us = $sql->get()) + { + $list .= ''; + $list .= ''.$us['id'].''; + $list .= ''.$us['login'].''; + $list .= ''.$us['mail'].''; + $list .= ''.$aGroup[$us['group']].''; + $list .= ''.sys::today($us['time']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('offline', 'sections/users'); + + $html->set('list', $list); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/users/online.php b/system/acp/sections/users/online.php new file mode 100644 index 0000000..df6840c --- /dev/null +++ b/system/acp/sections/users/online.php @@ -0,0 +1,39 @@ + 'Пользователь', 'support' => 'Тех. поддержка', 'admin' => 'Администратор'); + + $sql->query('SELECT `id` FROM `users` WHERE `time`>"'.($start_point-180).'"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/users/section'); + + include(LIB.'geo.php'); + + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $sql->query('SELECT `id`, `login`, `group`, `ip`, `browser` FROM `users` WHERE `time`>"'.($start_point-180).'" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($us = $sql->get()) + { + $list .= ''; + $list .= ''.$us['id'].''; + $list .= ''.$us['login'].''; + $list .= ''.$aGroup[$us['group']].''; + $list .= ''.sys::browser($us['browser']).''; + $list .= ''.$us['ip'].''; + $list .= ''.sys::country($us['ip']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('online', 'sections/users'); + + $html->set('list', $list); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/users/search.php b/system/acp/sections/users/search.php new file mode 100644 index 0000000..bb94c7a --- /dev/null +++ b/system/acp/sections/users/search.php @@ -0,0 +1,67 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if($text{0} == 'i' AND $text{1} == 'd') + $sql->query('SELECT `id`, `login`, `mail`, `balance`, `group` FROM `users` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`login` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`mail` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`balance` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`group` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`phone` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`contacts` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`ip` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $sql->query('SELECT `id`, `login`, `mail`, `balance`, `group` FROM `users` WHERE '.$like.' ORDER BY `id` ASC LIMIT 10'); + } + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($us = $sql->get()) + { + $list .= ''; + $list .= ''.$us['id'].''; + $list .= ''.$us['login'].''; + $list .= ''.$us['mail'].''; + $list .= ''.$us['balance'].' '.$cfg['currency'].''; + $list .= ''.$aGroup[$us['group']].''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/users/signup.php b/system/acp/sections/users/signup.php new file mode 100644 index 0000000..fe9ad72 --- /dev/null +++ b/system/acp/sections/users/signup.php @@ -0,0 +1,31 @@ +query('DELETE FROM `signup` WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $list = ''; + + $sql->query('SELECT `id`, `mail`, `key`, `date` FROM `signup` ORDER BY `id` ASC'); + while($sign = $sql->get()) + { + $list .= ''; + $list .= ''.$sign['id'].''; + $list .= ''.$sign['mail'].''; + $list .= ''.$sign['key'].''; + $list .= ''.sys::today($sign['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('signup', 'sections/users'); + + $html->set('list', $list); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/users/stats.php b/system/acp/sections/users/stats.php new file mode 100644 index 0000000..6d075e6 --- /dev/null +++ b/system/acp/sections/users/stats.php @@ -0,0 +1,36 @@ +query('SELECT `id`, `login`, `mail`, `balance` FROM `users` WHERE `group`="user" AND `balance`!="0" ORDER BY `balance` DESC LIMIT 10'); + while($us = $sql->get($uss)) + { + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$us['id'].'" LIMIT 10'); + $servers = $sql->num(); + + $list .= ''; + $list .= ''.$us['id'].''; + $list .= ''.$us['login'].''; + $list .= ''.$us['mail'].''; + $list .= ''.$us['balance'].' '.$cfg['currency'].''; + $list .= ''.$servers.' шт.'; + $list .= ''; + } + + $html->get('stats', 'sections/users'); + + $html->set('list', $list); + + $sql->query('SELECT `balance` FROM `users` WHERE `group`="user" AND `balance`!="0"'); + $html->set('users', $sql->num()); + + $money = 0; + while($us = $sql->get()) + $money += $us['balance']; + + $html->set('money', $money); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/users/user.php b/system/acp/sections/users/user.php new file mode 100644 index 0000000..af3b622 --- /dev/null +++ b/system/acp/sections/users/user.php @@ -0,0 +1,125 @@ + 'Работает', + 'off' => 'Выключен', + 'start' => 'Запускается', + 'restart' => 'Перезапускается', + 'change' => 'Смена карты', + 'install' => 'Устанавливается', + 'reinstall' => 'Переустанавливается', + 'update' => 'Обновляется', + 'recovery' => 'Восстанавливается', + 'overdue' => 'Просрочен', + 'blocked' => 'Заблокирован' + ); + + $sql->query('SELECT * FROM `users` WHERE `id`="'.$id.'" LIMIT 1'); + $us = $sql->get(); + + if($go) + include(SEC.'users/action.php'); + + $auth_list = ''; + + include(LIB.'geo.php'); + + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $sql->query('SELECT `ip`, `date`, `browser` FROM `auth` WHERE `user`="'.$id.'" ORDER BY `id` DESC LIMIT 15'); + while($auth_info = $sql->get()) + { + $auth_list .= ''; + $auth_list .= 'Авторизация через браузер: '.sys::browser(base64_decode($auth_info['browser'])).''; + $auth_list .= ''.$auth_info['ip'].''; + $auth_list .= ''.sys::country($auth_info['ip']).''; + $auth_list .= ''.sys::today($auth_info['date']).''; + $auth_list .= ''; + } + + $logs_list = ''; + + $sql->query('SELECT `text`, `date` FROM `logs` WHERE `user`="'.$id.'" ORDER BY `id` DESC LIMIT 30'); + while($logs_info = $sql->get()) + { + $logs_list .= ''; + $logs_list .= ''.$logs_info['text'].''; + $logs_list .= ''.sys::today($logs_info['date']).''; + $logs_list .= ''; + } + + $serv_user = ''; + + $servers_user = $sql->query('SELECT `id`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `slots`, `name`, `time`, `online` FROM `servers` WHERE `user`="'.$id.'" ORDER BY `id` DESC LIMIT 30'); + while($server_user = $sql->get($servers_user)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server_user['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name` FROM `tarifs` WHERE `id`="'.$server_user['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $serv_user .= ''; + $serv_user .= ''.$server_user['id'].''; + $serv_user .= ''.$server_user['address'].' (Перейти)'; + $serv_user .= '#'.$server_user['tarif'].' '.$tarif['name'].''; + $serv_user .= ''.$status[$server_user['status']].''; + $serv_user .= ''.strtoupper($aGname[$server_user['game']]).''; + $serv_user .= ''.$time_end = $server_user['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server_user['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server_user['time']).''; + $serv_user .= ''; + } + + $money_all = 0; + $money_buy = 0; + $money_month = 0; + + $sql->query('SELECT `money` FROM `logs` WHERE `user`="'.$us['id'].'" AND (`type`="buy" OR `type`="extend")'); + while($logs = $sql->get()) + $money_all += $logs['money']; + + $sql->query('SELECT `money` FROM `logs` WHERE `user`="'.$us['id'].'" AND `type`="buy"'); + while($logs = $sql->get()) + $money_buy += $logs['money']; + + $time = (params::$aDayMonth[date('n', $start_point)]-date('j', $start_point))*86400; + + $sql->query('SELECT `money` FROM `logs` WHERE `user`="'.$us['id'].'" AND (`type`="buy" OR `type`="extend") AND `date`>"'.($start_point-$time).'"'); + while($logs = $sql->get()) + $money_month += $logs['money']; + + $html->get('user', 'sections/users'); + + foreach($us as $i => $val) + $html->set($i, $val); + + $html->set('time', $us['time'] < $start_point-600 ? sys::today($us['time']) : sys::ago($us['time'])); + $html->set('date', sys::today($us['date'])); + + $html->set('month', mb_strtolower(params::$aNameMonth[sys::int(date('n', $start_point))], 'UTF-8')); + $html->set('money_all', $money_all); + $html->set('money_buy', $money_buy); + $html->set('money_extend', $money_all-$money_buy); + $html->set('money_month', $money_month); + + $html->set('auth', $auth_list); + $html->set('logs', $logs_list); + $html->set('serv_user', $serv_user); + + $html->set('confirm_phone', str_replace($us['confirm_phone'], $us['confirm_phone'].'" selected="select', '')); + $html->set('group', str_replace($us['group'], $us['group'].'" selected="select', '')); + $html->set('help', str_replace($us['help'], $us['help'].'" selected="select', '')); + + if($us['group'] == 'support') + { + $html->set('level', str_replace($us['level'].'"', $us['level'].'" selected="select"', '')); + $html->unit('support', true, true); + }else + $html->unit('support', false, true); + + $html->set('rental', $us['rental']); + $html->set('extend', $us['extend']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/web/amxbans.php b/system/acp/sections/web/amxbans.php new file mode 100644 index 0000000..fe1126d --- /dev/null +++ b/system/acp/sections/web/amxbans.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="amxbans" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/astats.php b/system/acp/sections/web/astats.php new file mode 100644 index 0000000..6699189 --- /dev/null +++ b/system/acp/sections/web/astats.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="astats" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/csbans.php b/system/acp/sections/web/csbans.php new file mode 100644 index 0000000..6215144 --- /dev/null +++ b/system/acp/sections/web/csbans.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="csbans" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/csstats.php b/system/acp/sections/web/csstats.php new file mode 100644 index 0000000..ea17c00 --- /dev/null +++ b/system/acp/sections/web/csstats.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="csstats" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/hosting.php b/system/acp/sections/web/hosting.php new file mode 100644 index 0000000..671bcd7 --- /dev/null +++ b/system/acp/sections/web/hosting.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="hosting" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/index.php b/system/acp/sections/web/index.php new file mode 100644 index 0000000..bbac61c --- /dev/null +++ b/system/acp/sections/web/index.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/mysql.php b/system/acp/sections/web/mysql.php new file mode 100644 index 0000000..3b546e8 --- /dev/null +++ b/system/acp/sections/web/mysql.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="mysql" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/psychostats.php b/system/acp/sections/web/psychostats.php new file mode 100644 index 0000000..9444164 --- /dev/null +++ b/system/acp/sections/web/psychostats.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="psychostats" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/rankme.php b/system/acp/sections/web/rankme.php new file mode 100644 index 0000000..4b0f726 --- /dev/null +++ b/system/acp/sections/web/rankme.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="rankme" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/web/search.php b/system/acp/sections/web/search.php new file mode 100644 index 0000000..6c1df6e --- /dev/null +++ b/system/acp/sections/web/search.php @@ -0,0 +1,88 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if(substr($text, 0, 5) == 'game=') + { + $game = trim(substr($text, 5)); + + if(in_array($game, array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'))) + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `game`="'.$game.'" ORDER BY `id` ASC'); + }elseif($text{0} == 'i' AND $text{1} == 'd') + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`type` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`server` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`user` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`unit` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`domain` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`login` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE '.$like.' ORDER BY `id` ASC'); + } + + if(!$sql->num($webs)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/web/sourcebans.php b/system/acp/sections/web/sourcebans.php new file mode 100644 index 0000000..dee3f4f --- /dev/null +++ b/system/acp/sections/web/sourcebans.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `web`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/web'); + + $webs = $sql->query('SELECT `id`, `type`, `server`, `user`, `unit`, `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="sourcebans" ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($web = $sql->get($webs)) + { + if(!$web['unit']) + $unit = array('name' => 'Веб хостинг'); + else{ + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + } + + $list .= ''; + $list .= ''.$web['id'].''; + $list .= 'USER_'.$web['user'].''; + $list .= ''.$web['domain'].''; + $list .= ''.$web['login'].''; + $list .= ''.date('H:i:s', $web['date']).''; + $list .= 'Перейти'; + $list .= ''; + + $list .= ''; + $list .= ''.$aWebname[$web['type']].''; + $list .= 'SERVER_'.$web['server'].''; + $list .= ''.$unit['name'].''; + $list .= ''.$web['passwd'].''; + $list .= ''.date('d.n.Y', $web['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/web'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/add.php b/system/acp/sections/wiki/add.php new file mode 100644 index 0000000..7916c56 --- /dev/null +++ b/system/acp/sections/wiki/add.php @@ -0,0 +1,51 @@ + 'Необходимо заполнить все поля')); + + if(sys::strlen($aData['tags']) > 100) + sys::outjs(array('e' => 'Теги не должен превышать 100 символов.')); + + $sql->query('SELECT `id` FROM `wiki_category` WHERE `id`="'.$aData['cat'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанная категория не найдена')); + + $sql->query('INSERT INTO `wiki` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`cat`="'.$aData['cat'].'",' + .'`tags`="'.htmlspecialchars($aData['tags']).'",' + .'`date`="'.$start_point.'"'); + + $id = $sql->id(); + + $sql->query('INSERT INTO `wiki_answer` set ' + .'`wiki`="'.$id.'",' + .'`cat`="'.$aData['cat'].'",' + .'`text`="'.htmlspecialchars($aData['text']).'"'); + + sys::outjs(array('s' => 'ok')); + } + + $cats = ''; + + $sql->query('SELECT `id`, `name` FROM `wiki_category` ORDER BY `id` ASC'); + while($cat = $sql->get()) + $cats .= ''; + + $html->get('add', 'sections/wiki'); + + $html->set('cats', $cats); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/addcat.php b/system/acp/sections/wiki/addcat.php new file mode 100644 index 0000000..a1f625e --- /dev/null +++ b/system/acp/sections/wiki/addcat.php @@ -0,0 +1,25 @@ + 'Необходимо заполнить все поля')); + + $sql->query('INSERT INTO `wiki_category` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`sort`="'.$aData['sort'].'"'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('addcat', 'sections/wiki'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/cat.php b/system/acp/sections/wiki/cat.php new file mode 100644 index 0000000..37a3069 --- /dev/null +++ b/system/acp/sections/wiki/cat.php @@ -0,0 +1,32 @@ +query('SELECT * FROM `wiki_category` WHERE `id`="'.$id.'" LIMIT 1'); + $wiki = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : htmlspecialchars_decode($wiki['name']); + $aData['sort'] = isset($_POST['sort']) ? sys::int($_POST['sort']) : $wiki['sort']; + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + $sql->query('UPDATE `wiki_category` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`sort`="'.$aData['sort'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $html->get('cat', 'sections/wiki'); + + $html->set('name', htmlspecialchars_decode($wiki['name'])); + $html->set('id', $wiki['id']); + $html->set('sort', $wiki['sort']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/cats.php b/system/acp/sections/wiki/cats.php new file mode 100644 index 0000000..c7e1c04 --- /dev/null +++ b/system/acp/sections/wiki/cats.php @@ -0,0 +1,25 @@ +query('SELECT `id`, `name`, `sort` FROM `wiki_category` ORDER BY `id` ASC'); + while($cat = $sql->get($cats)) + { + $sql->query('SELECT `name` FROM `wiki` WHERE `cat`="'.$cat['id'].'"'); + $wiki = $sql->num(); + + $list .= ''; + $list .= ''.$cat['id'].''; + $list .= ''.$cat['name'].''; + $list .= ''.$wiki.' шт.'; + $list .= ''.$cat['sort'].''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('cats', 'sections/wiki'); + + $html->set('list', $list); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/delete.php b/system/acp/sections/wiki/delete.php new file mode 100644 index 0000000..cd60e19 --- /dev/null +++ b/system/acp/sections/wiki/delete.php @@ -0,0 +1,13 @@ +query('DELETE FROM `wiki_category` WHERE `id`="'.$id.'" LIMIT 1'); + else{ + $sql->query('DELETE FROM `wiki` WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `wiki_answer` WHERE `wiki`="'.$id.'" LIMIT 1'); + } + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/index.php b/system/acp/sections/wiki/index.php new file mode 100644 index 0000000..1ce66f0 --- /dev/null +++ b/system/acp/sections/wiki/index.php @@ -0,0 +1,42 @@ +query('SELECT `id` FROM `wiki`'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'acp/wiki'); + + $wikis = $sql->query('SELECT `id`, `name`, `cat`, `date` FROM `wiki` ORDER BY `id` ASC LIMIT '.$aPage['num'].', 20'); + while($wiki = $sql->get($wikis)) + { + $sql->query('SELECT `name` FROM `wiki_category` WHERE `id`="'.$wiki['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $list .= ''; + $list .= ''.$wiki['id'].''; + $list .= ''.$wiki['name'].''; + $list .= ''.$cat['name'].''; + $list .= ''.date('d.m.Y - H:i:s', $wiki['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $html->get('index', 'sections/wiki'); + + $html->set('list', $list); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/search.php b/system/acp/sections/wiki/search.php new file mode 100644 index 0000000..e89f27e --- /dev/null +++ b/system/acp/sections/wiki/search.php @@ -0,0 +1,65 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + if($text{0} == 'i' AND $text{1} == 'd') + $wikis = $sql->query('SELECT `id`, `name`, `cat`, `date` FROM `wiki` WHERE `id`="'.sys::int($text).'" LIMIT 1'); + else{ + $like = '`id` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`cat` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') OR' + .'`tags` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\')'; + + $wiki = $sql->query('SELECT `id`, `name`, `cat`, `date` FROM `wiki` WHERE '.$like.' ORDER BY `id` ASC LIMIT 20'); + } + + if(!$sql->num($wikis)) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $list = ''; + + while($wiki = $sql->get($wikis)) + { + $sql->query('SELECT `name` FROM `wiki_category` WHERE `id`="'.$wiki['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $list .= ''; + $list .= ''.$wiki['id'].''; + $list .= ''.$wiki['name'].''; + $list .= ''.$cat['name'].''; + $list .= ''.date('d.m.Y - H:i:s', $wiki['date']).''; + $list .= 'Удалить'; + $list .= ''; + } + + $mcache->set($mkey, array('s' => $list), false, 15); + + sys::outjs(array('s' => $list)); +?> \ No newline at end of file diff --git a/system/acp/sections/wiki/wiki.php b/system/acp/sections/wiki/wiki.php new file mode 100644 index 0000000..e0615eb --- /dev/null +++ b/system/acp/sections/wiki/wiki.php @@ -0,0 +1,58 @@ +query('SELECT `name`, `cat`, `tags` FROM `wiki` WHERE `id`="'.$id.'" LIMIT 1'); + $wiki = $sql->get(); + + $sql->query('SELECT `text` FROM `wiki_answer` WHERE `wiki`="'.$id.'" LIMIT 1'); + $wiki = array_merge($wiki, $sql->get()); + + if($go) + { + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : htmlspecialchars_decode($wiki['name']); + $aData['text'] = isset($_POST['text']) ? sys::bbc(trim($_POST['text'])) : htmlspecialchars_decode($wiki['text']); + $aData['cat'] = isset($_POST['cat']) ? sys::int($_POST['cat']) : $wiki['cat']; + $aData['tags'] = isset($_POST['tags']) ? trim($_POST['tags']) : htmlspecialchars_decode($wiki['tags']); + + if(in_array('', $aData)) + sys::outjs(array('e' => 'Необходимо заполнить все поля')); + + if(sys::strlen($aData['tags']) > 100) + sys::outjs(array('e' => 'Теги не должен превышать 100 символов.')); + + $sql->query('SELECT `id` FROM `wiki_category` WHERE `id`="'.$aData['cat'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанная категория не найдена')); + + $sql->query('UPDATE `wiki` set ' + .'`name`="'.htmlspecialchars($aData['name']).'",' + .'`cat`="'.$aData['cat'].'",' + .'`tags`="'.htmlspecialchars($aData['tags']).'",' + .'`date`="'.$start_point.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('UPDATE `wiki_answer` set ' + .'`cat`="'.$aData['cat'].'",' + .'`text`="'.htmlspecialchars($aData['text']).'" WHERE `wiki`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $cats = ''; + + $sql->query('SELECT `id`, `name` FROM `wiki_category` ORDER BY `id` ASC'); + while($cat = $sql->get()) + $cats .= ''; + + $html->get('wiki', 'sections/wiki'); + + $html->set('id', $id); + $html->set('name', htmlspecialchars_decode($wiki['name'])); + $html->set('text', htmlspecialchars_decode($wiki['text'])); + $html->set('tags', htmlspecialchars_decode($wiki['tags'])); + $html->set('cats', str_replace('"'.$wiki['cat'].'"', '"'.$wiki['cat'].'" selected', $cats)); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/data/SxGeoCity.dat b/system/data/SxGeoCity.dat new file mode 100644 index 0000000..c0df873 Binary files /dev/null and b/system/data/SxGeoCity.dat differ diff --git a/system/data/acpengine.php b/system/data/acpengine.php new file mode 100644 index 0000000..2d7429a --- /dev/null +++ b/system/data/acpengine.php @@ -0,0 +1,52 @@ + '/^[A-Za-z0-9_]{4,16}$/', + 'mail' => '/^([a-z0-9_\.-])+@[a-z0-9-]+\.([a-z]{2,4}\.)?[a-z]{2,4}$/i', + 'name' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'lastname' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'patronymic' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'phone' => '/^380+[0-9]{9,9}$|^77+[0-9]{9,9}$|^79+[0-9]{9,9}$|^375+[0-9]{9,9}$/m', + 'contacts' => '/^(http|https):\/\/(new\.vk|vk)\.com\/[A-Za-z\_\.]{1,2}[A-Za-z0-9\_\.]{4,32}$|^[A-Za-z][A-Za-z0-9\.\-\_]{6,32}$/', + 'passwd' => '/^[A-Za-z0-9]{6,26}$/', + 'support_info' => '/[^а-яА-Я\s]+/msi', + 'address' => '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:[0-9]{1,5}/' + ); + + // Массив имен игр + $aGname = array( + 'cs' => 'CS: 1.6', + 'css' => 'CS: Source', + 'csgo' => 'CS: Global Offensive', + 'cssold' => 'CS: Source v34', + 'mc' => 'MineCraft', + 'mta' => 'GTA: MTA', + 'samp' => 'GTA: SAMP' + ); +?> \ No newline at end of file diff --git a/system/data/boost.php b/system/data/boost.php new file mode 100644 index 0000000..7f1ad99 --- /dev/null +++ b/system/data/boost.php @@ -0,0 +1,22 @@ + array( + 'boost' => array( + + ), + + 'mon' => array( + 'site' => '', // адрес сайта раскрутки + 'api' => '', // адрес API сайта раскрутки + 'key' => '', // секретный ключ для API + 'services' => array(), // array(номер услуги) - выборка (номер услуги либо кол-во кругов) + 'circles' => array(), // array(номер услуги => кол-во кругов) - выборка + 'price' => array(), // array(номер услуги => цена) + 'type' => 'def' // тип работы с API сайта раскрутки + ) + ) + ); +?> \ No newline at end of file diff --git a/system/data/config.php b/system/data/config.php new file mode 100644 index 0000000..364c5e7 --- /dev/null +++ b/system/data/config.php @@ -0,0 +1,305 @@ + 'EngineGP', // Название сайта + 'graph' => 'EngineGP', // Описание сайта + 'url' => 'IPADDR', // Тут ваш IP или Домен, пример: 127.0.0.1 + 'http' => 'http://IPADDR/', // Тут ваш IP или Домен с указанием http, пример: http://127.0.0.1 + 'plugins' => 'http://IPADDR/files/plugins/', // Путь к плагинам + 'ip' => 'IPADDR', // IP-Адрес сайта прмер: 127.0.0.1 + 'subnet' => 'IPADDR.0/23', // Подсеть сайта пример: 127.0.0.1.0/23 .0/23(не стирать) + + 'cdn' => 'http://cdn.enginegp.ru/', // CDN сервис EGP, если ваш сайт переехал на https то следует тут тоже сменить протокол с http на https + + // Данные для пополнения баланса пользователям + 'freekassa_id' => '', // Номер кассы + 'freekassa_key_1' => '', // Первый секретный ключ FreeKassa + 'freekassa_key_2' => '', // Второй секретный ключ FreeKassa + 'webmoney_wmr' => '', // Wmr кошелек + 'webmoney_key' => '', // Секретный ключ WebMoney + 'unitpay_key' => '', // Секретный ключ UnitPay + 'unitpay_pubkey' => '', // Публичный ключ UnitPay + + // Данные для отправки почты + 'smtp_url' => '', // * SMTP URL, пример: ssl://smtp.mail.ru | ssl://smtp.yandex.ru | ssl://smtp.google.com + 'smtp_login' => '', // * E-mail отправителя, пример: support@enginegp.ru + 'smtp_passwd' => '', // * Пароль от E-mail отправителя support@enginegp.ru + 'smtp_name' => '', // * Имя отправителя, пример: EngineGP Support + 'smtp_mail' => '', // * E-mail отправителя(ещё раз) - (support@enginegp.ru) + + // Уведомления о сообщениях в тикетах + 'notice_admin' => array(1), // перечислить id пользователя, на их почты будут отправлять уведомления + + // Данные для работы с sms шлюзом (sms.ru) + 'sms_gateway' => 'http://sms.ru/sms/send?api_id=_KEY_&from=_WHO_', // шлюз + 'sms_to' => 'to', // GET параметр для получателя + 'sms_text' => 'text', // GET параметр для сообщения + 'sms_ok' => '100', // значение удачи + + // Новости + 'news_page' => 10, // Кол-во новостей на странице + + // Данные для рассчетов + 'benefitblock' => true, // Включена ли система контроля скидок (запрет выгоды при использовании скидок) + 'settlement_period' => false, // Включена ли система расчетного периода + 'currency' => 'руб.', // Наименование валюты + 'curinrub' => 1, // Курс к рублю + 'promo_discount' => true, // Суммировать скидки промо-кода и периода + 'part_proc' => 10, // Процент партнерской программы + 'part_money' => true, // true == зачислять в отдельный счет / false == сразу суммировать с балансом + 'part' => false, // true == пополнять процент при пополнении счета рефералом / false == пополнять при списании средств у реферала (продление/аренда) + + // Данные для вывода средств (если part_money == true) + 'part_log' => 'Лицевой счет', // название кошелька при выводе на баланс сайта + 'part_output_proc' => 10, // процент комисси за вывод + 'part_limit_min' => 100, // мин. лимит на вывод за раз пользователем + 'part_limit_max' => 500, // макс. лимит на вывод за день пользователем + 'part_limit_day' => 5000, // лимит на вывод за день + 'part_output' => false, // true == выводить без одобрения / false == вывод производиться после одобрения администратором + 'part_gateway' => 'unitpay', // платежный шлюз для вывода (unitpay) + + // Остальное + 'text_group' => true, // Вывод сообщений (ошибок) по группе пользователя + 'recaptcha' => false, // Требовать повторного ввода капчи (false - сохранить удачу в кеше на 60 секунд) + 'server_delete' => 3, // Через сколько дней удалить игровой сервер после окончания его аренды. + 'steamcmd' => '/path/cmd', // Путь к steamcmd на локациях (/path/steam) + 'iptables' => 'iptables_block', // Файл правил для FireWall (блокировка на уровне оборудования) (/root/_FILE_) + 'cron_key' => 'CRONKEY', // Ключ для cron.php + 'cron_taskset' => '0', // Ядро, на котором запускать cron.php (уставновить отличный от нуля, если на VDS больше 1 ядра/потока) + + // Кеш (кол-во секунд) + 'mcache_server_mon' => 2, // Мониторинг (онлайн, название, карта) + 'mcache_server_status' => 2, // Статус (состояние: включен, смена карты, переустановка) + 'mcache_server_resources' => 2, // Ресурсы (нагрузка: cpu, ram hdd) + + // Контролеры / параметры + 'autostop' => 30, // Через сколько минут выключить CW сервер, если на нем нет игроков + 'teststop' => 10, // Через сколько минут выключить тестовый сервер, если на нем нет игроков + 'fpsplus' => 100, // Прибавление fps к параметру "sys_ticrate" при старте (пример: 1000+100 | итог: sys_ticrate 1100) + 'pingboost' => 3, // Значение pingboost по умолчанию (1,2,3 | 0 = без pingboost) + 'change_pingboost' => false, // Смена pingboost клиентом (true = разрешено / false = запрещено) + 'cpu_route' => true, // Активация (EngineGP CPU ROUTE) автораспределения игровых серверов по ядрам/потокам | false - выключена + 'cpu_first' => true, // Запретить использовать первый поток cpu (значение имеет вес при 2х и более потоках) | РЕКОМЕНДУЕМОЕ ЗНАЧЕНИЕ: true + 'crontabs' => 3, // Количество заданий crontab на 1 игровой сервер + + // Услуга "Контроль" + 'control_delete' => 10, // через сколько дней удалять услугу + 'control_time' => array(30, 90), // периоды аренды + 'control_limit' => array( // лимит / цена + 1 => 50, + 5 => 100, + 10 => 150, + 20 => 250 + ), + 'control_server' => 'http://games.enginegp.ru/', // головной сервер, путь к архивам + 'control_packs' => array( + 'cs' => array( + '6153' => 'Build 6153', + '5787' => 'Build 5787', + 'rehlds' => 'ReHLDS' + ), + 'cssold' => array( + 'cssold' => 'Стандарт', + ), + 'css' => array( + 'default' => 'Стандарт', + ), + 'csgo' => array( + 'default' => 'Стандарт', + ) + ), + 'control_install' => array( + 'cs' => 'pack="6153", `map_start`="de_dust2", `fps`="1100"', + 'cssold' => 'pack="cssold", `map_start`="de_dust2", `fps`="1000",`tickrate`="100"', + 'css' => 'pack="default", `map_start`="de_dust2", `tickrate`="100"', + 'csgo' => 'pack="default", `map_start`="de_dust2", `tickrate`="128"' + ), + 'control_steamcmd' => array( + 'css' => 232330, + 'csgo' => 740 + ), + + // Задержка в возможности повторной переустановки сервера (минуты) + 'reinstall' => array( + 'cs' => '60', + 'cssold' => '60', + 'css' => '60', + 'csgo' => '60', + 'samp' => '60', + 'crmp' => '60', + 'mta' => '60', + 'mc' => '60' + ), + + // Задержка в возможности повторного обновления сервера (минуты) + 'update' => array( + 'cs' => '60', + 'cssold' => '60', + 'css' => '60', + 'csgo' => '60' + ), + + // RAM на 1 слот + 'ram' => array( + 'cs' => '32', + 'cssold' => '32', + 'css' => '32', + 'csgo' => '32', + 'samp' => '32', + 'crmp' => '32', + 'mta' => '32' + ), + + // Максимальная нагрузка % на RAM 1-го игрового сервера + 'ram_use_max' => array( + 'cs' => '99', + 'cssold' => '99', + 'css' => '99', + 'csgo' => '99', + 'samp' => '99', + 'crmp' => '99', + 'mta' => '99', + ), + + // Максимальная нагрузка % на CPU 1-го игрового сервера + 'cpu_use_max' => array( + 'cs' => '99', + 'cssold' => '99', + 'css' => '99', + 'csgo' => '99', + 'samp' => '99', + 'crmp' => '99', + 'mta' => '99', + 'mc' => '99', + ), + + // Параметры ftp игровых серверов + 'ftp' => array( + // Корневая директория серверов (false = server/(cstrike | csgo | l4d)/ | true = server/) + 'root' => array( + 'cs' => false, + 'cssold' => false, + 'css' => false, + 'csgo' => false, + 'samp' => false, + 'crmp' => false, + 'mta' => false, + 'mc' => false + ), + + // Путь к директори для файлового менеджера EngineGP (используется при $cfg['ftp']['root'][$game] == TRUE) + 'dir' => array( + 'cs' => '/cstrike', + 'cssold' => '/cstrike', + 'css' => '/cstrike', + 'csgo' => '/csgo', + 'samp' => '/', + 'crmp' => '/', + 'mta' => '/mods/deathmatch', + 'mc' => '/' + ), + + // Путь к директори (используется при $cfg['ftp']['root'][$game] == FALSE) + 'home' => array( + 'cs' => '/cstrike', + 'cssold' => '/cstrike', + 'css' => '/cstrike', + 'csgo' => '/csgo', + 'samp' => '/', + 'crmp' => '/', + 'mta' => '/mods/deathmatch', + 'mc' => '/' + ), + ), + + // Смена количества слот + 'change_slots' => array( + 'cs' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'cssold' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'css' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'csgo' => array( + 'days' => false, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'samp' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'crmp' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'mta' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ), + + 'mc' => array( + 'days' => true, // При смене кол-ва слот вычитывать/добавлять дни аренды (add == true), если false, то смена (увеличение) на платной основе + 'down' => true, // Если 'days == true', то дать возможность уменьшать слоты + 'add' => true // Если 'down == true', то при уменьшении кол-во слот, добавлять дни к аренде + ) + ), + + // Смена локации + 'change_unit' => array( + 'cs' => false, + 'cssold' => false, + 'css' => false, + 'csgo' => false, + 'samp' => false, + 'crmp' => false, + 'mta' => false, + 'mc' => false + ), + + // Аренда выделенного адреса (пример: cs 1.6 => ip:27015) + 'buy_address' => array( + 'cs' => true, // true == по месячная аренда, false == разовая оплата на весь период аренды игрового сервера + 'cssold' => true, + 'css' => true, + 'csgo' => true, + 'samp' => true, + 'crmp' => true, + 'mta' => true, + 'mc' => true + ), + + // Тестовый период (тестовый период возможен только пользователям с подтвержденным номером, выдается 1 раз) + 'tests' => array( + 'game' => false, // Разрешить брать тест другой игры + 'sametime' => false // Разрешить брать тест другой игры во время тестирования. (при условии, что game == true) + ), + + // Боты на сервере (включение -nobots в параметре запуска сервера) + 'bots' => array( + 'cssold' => false, // true == разрешены, false == запрещены + 'css' => false, + 'csgo' => false + ) + ); +?> \ No newline at end of file diff --git a/system/data/control/egp.sh b/system/data/control/egp.sh new file mode 100644 index 0000000..7c1ee6e --- /dev/null +++ b/system/data/control/egp.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +cd /tmp; + +rm sqlpasswd; wget -O sqlpasswd http://IPADDR/autocontrol/action/sqlpasswd +rm proftpd; wget -O proftpd http://IPADDR/autocontrol/action/proftpd +rm proftpd_modules; wget -O proftpd_modules http://IPADDR/autocontrol/action/proftpd_modules +rm proftpd_sql; wget -O proftpd_sql http://IPADDR/autocontrol/action/proftpd_sql +rm proftpd_passwd; wget -O proftpd_passwd http://IPADDR/autocontrol/action/proftpd_passwd +rm proftpd_sqldump; wget -O proftpd_sqldump http://IPADDR/autocontrol/action/proftpd_sqldump +rm rclocal; wget -O rclocal http://IPADDR/autocontrol/action/rclocal +rm nginx; wget -O nginx http://IPADDR/autocontrol/action/nginx +rm mysql-apt-config_0.8.0-1_all.deb; wget -O mysql-apt-config_0.8.0-1_all.deb http://IPADDR/autocontrol/action/mysqlaptconfig + +echo "Europe/Moscow" > /etc/timezone +echo PURGE | debconf-communicate mysql-apt-config +echo PURGE | debconf-communicate mysql-community-server +echo PURGE | debconf-communicate proftpd-basic +echo mysql-apt-config mysql-apt-config/select-server select mysql-5.7 | debconf-set-selections +echo mysql-apt-config mysql-apt-config/tools-component string mysql-tools | debconf-set-selections +echo mysql-apt-config mysql-apt-config/repo-url string http://repo.mysql.com/apt | debconf-set-selections +echo mysql-apt-config mysql-apt-config/preview-component string | debconf-set-selections +echo mysql-apt-config mysql-apt-config/unsupported-platform select abort | debconf-set-selections +echo mysql-apt-config mysql-apt-config/dmr-warning note | debconf-set-selections +echo mysql-apt-config mysql-apt-config/select-preview select Disabled | debconf-set-selections +echo mysql-apt-config mysql-apt-config/repo-codename select wheezy | debconf-set-selections +echo mysql-apt-config mysql-apt-config/select-product select Ok | debconf-set-selections +echo mysql-apt-config mysql-apt-config/select-tools select Enabled | debconf-set-selections +echo mysql-apt-config mysql-apt-config/repo-distro select debian | debconf-set-selections +echo mysql-community-server mysql-community-server/root-pass password `cat sqlpasswd` | debconf-set-selections +echo mysql-community-server mysql-community-server/re-root-pass password `cat sqlpasswd` | debconf-set-selections +echo mysql-community-server mysql-community-server/data-dir note | debconf-set-selections +echo mysql-community-server mysql-community-server/remove-data-dir boolean false | debconf-set-selections +echo mysql-community-server mysql-community-server/root-pass-mismatch error | debconf-set-selections +echo proftpd-basic shared/proftpd/inetd_or_standalone select standalone | debconf-set-selections + +echo "deb http://mirror.yandex.ru/debian/ wheezy main" > /etc/apt/sources.list +echo "deb-src http://mirror.yandex.ru/debian/ wheezy main" >> /etc/apt/sources.list +echo "deb http://security.debian.org/ wheezy/updates main" >> /etc/apt/sources.list +echo "deb-src http://security.debian.org/ wheezy/updates main" >> /etc/apt/sources.list +echo "deb http://mirror.yandex.ru/debian/ wheezy-updates main" >> /etc/apt/sources.list +echo "deb-src http://mirror.yandex.ru/debian/ wheezy-updates main" >> /etc/apt/sources.list + +export DEBIAN_FRONTEND="noninteractive" + +apt-get update +apt-get install -y lsb-release + +dpkg -i mysql-apt-config_0.8.0-1_all.deb + +apt-get update +apt-get install -y sudo screen htop tcpdump ssh zip unzip mc qstat gdb lib32gcc1 nginx ntpdate lsof +apt-get install -y mysql-community-server --force-yes +apt-get update --fix-missing +apt-get install -y mysql-community-server --force-yes +apt-get update --fix-missing +apt-get install -y mysql-community-server --force-yes +apt-get install -y proftpd-basic proftpd-mod-mysql +aptitude install -y lib32z1 + +dpkg-reconfigure tzdata -f noninteractive + +sed -i '14d' /etc/rc.local + +mv proftpd /etc/proftpd/proftpd.conf +mv proftpd_modules /etc/proftpd/modules.conf +mv proftpd_sql /etc/proftpd/sql.conf +mv nginx /etc/nginx/nginx.conf + +cat rclocal >> /etc/rc.local + +touch /root/iptables_block + +chmod 500 proftpd_passwd /root/iptables_block + +./proftpd_passwd + +echo "UseDNS no" >> /etc/ssh/sshd_config +echo "UTC=no" >> /etc/default/rcS + +mkdir -p /copy /servers /path/steam /var/nginx + +cd /path/steam && wget http://media.steampowered.com/client/steamcmd_linux.tar.gz && tar xvfz steamcmd_linux.tar.gz && rm steamcmd_linux.tar.gz + +groupmod -g 998 `cat /etc/group | grep :1000 | awk -F":" '{print $1}'` +groupadd -g 1000 servers; + +chmod 711 /servers; chown root:servers /servers +chmod -R 755 /path; chown path:servers /path +chmod -R 750 /copy; chown root:root /copy +chmod -R 750 /etc/proftpd + +wget -O endinstall http://IPADDR/autocontrol/action/endinstall + +reboot \ No newline at end of file diff --git a/system/data/control/mysqlaptconfig.txt b/system/data/control/mysqlaptconfig.txt new file mode 100644 index 0000000..36a4510 Binary files /dev/null and b/system/data/control/mysqlaptconfig.txt differ diff --git a/system/data/control/nginx.txt b/system/data/control/nginx.txt new file mode 100644 index 0000000..f2ced90 --- /dev/null +++ b/system/data/control/nginx.txt @@ -0,0 +1,48 @@ +user root; worker_processes 1; + +error_log /var/log/nginx/error.log; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; +} + +http { + include /etc/nginx/mime.types; + + access_log /var/log/nginx/access.log; + + sendfile on; + tcp_nopush on; + keepalive_timeout 15; + tcp_nodelay on; + directio 5m; + expires max; + + include /etc/nginx/conf.d/*.conf; + + server { + listen 8080; + location / { + root /var/nginx/; + index index.html index.htm; + set $limit_rate 20m; + } + location ~ /(.*)/.*\.cfg { + deny all; + } + location ~ /(.*)/.*\.vpk { + deny all; + } + location ~ /(.*)/cfg/ { + deny all; + } + location ~ /(.*)/addons/ { + deny all; + } + location ~ /(.*)/logs/ { + deny all; + } + } +} diff --git a/system/data/control/proftpd.txt b/system/data/control/proftpd.txt new file mode 100644 index 0000000..a512cc9 --- /dev/null +++ b/system/data/control/proftpd.txt @@ -0,0 +1,89 @@ +Include /etc/proftpd/modules.conf + +UseIPv6 on +IdentLookups off + +ServerName "Debian" +ServerType standalone +DeferWelcome off + +MultilineRFC2228 on +DefaultServer on +ShowSymlinks on + +TimeoutNoTransfer 600 +TimeoutStalled 600 +TimeoutIdle 1200 + +DisplayLogin welcome.msg +DisplayChdir .message true +ListOptions "-l" + +DenyFilter \*.*/ + +DefaultRoot ~ + +Port 21 +UseReverseDNS off +PassivePorts 49152 65534 + + +MaxInstances 30 + +User proftpd +Group nogroup + +Umask 022 022 + +AllowOverwrite on + +TransferLog /var/log/proftpd/xferlog +SystemLog /var/log/proftpd/proftpd.log + + + QuotaEngine off + + + + Ratios off + + + + DelayEngine on + + + + ControlsEngine off + ControlsMaxClients 2 + ControlsLog /var/log/proftpd/controls.log + ControlsInterval 5 + ControlsSocket /var/run/proftpd/proftpd.sock + + + + AdminControlsEngine off + + +Include /etc/proftpd/conf.d/ + +Include /etc/proftpd/sql.conf + +AuthOrder mod_sql.c + + + AllowOverwrite on + + + AllowAll + + + + AllowAll + + + DenyFilter ^(\..+|samp.+|server\.properties|srcds_.+|steam|.+\.sh|hlds_.+|hltv.*|.+\.cmds|usermodel\.amxx|console\.log|start\.jar)$ + HideFiles ^(\..+|samp.+|server\.properties|srcds_.+|steam|.+\.sh|hlds_.+|hltv.*|.+\.cmds|usermodel\.amxx|console\.log|start\.jar)$ + PathDenyFilter ^(\..+|samp.+|server\.properties|srcds_.+|steam|.+\.sh|hlds_.+|hltv.*|.+\.cmds|usermodel\.amxx|start\.jar)$ + + +RequireValidShell off \ No newline at end of file diff --git a/system/data/control/proftpd_modules.txt b/system/data/control/proftpd_modules.txt new file mode 100644 index 0000000..3d91b1b --- /dev/null +++ b/system/data/control/proftpd_modules.txt @@ -0,0 +1,32 @@ +ModulePath /usr/lib/proftpd +ModuleControlsACLs insmod,rmmod allow user root +ModuleControlsACLs lsmod allow user * +LoadModule mod_ctrls_admin.c +LoadModule mod_tls.c +LoadModule mod_sql.c +LoadModule mod_sql_mysql.c +LoadModule mod_radius.c +LoadModule mod_quotatab.c +LoadModule mod_quotatab_file.c +LoadModule mod_quotatab_sql.c +LoadModule mod_quotatab_radius.c +LoadModule mod_wrap.c +LoadModule mod_rewrite.c +LoadModule mod_load.c +LoadModule mod_ban.c +LoadModule mod_wrap2.c +LoadModule mod_wrap2_file.c +LoadModule mod_dynmasq.c +LoadModule mod_exec.c +LoadModule mod_shaper.c +LoadModule mod_ratio.c +LoadModule mod_site_misc.c +LoadModule mod_sftp.c +LoadModule mod_sftp_pam.c +LoadModule mod_facl.c +LoadModule mod_unique_id.c +LoadModule mod_copy.c +LoadModule mod_deflate.c +LoadModule mod_ifversion.c +LoadModule mod_tls_memcache.c +LoadModule mod_ifsession.c \ No newline at end of file diff --git a/system/data/control/proftpd_passwd.txt b/system/data/control/proftpd_passwd.txt new file mode 100644 index 0000000..ebfdc1a --- /dev/null +++ b/system/data/control/proftpd_passwd.txt @@ -0,0 +1,4 @@ +mysql -uroot -p[passwd] -e "CREATE DATABASE ftp;"; +mysql -uroot -p[passwd] -e "CREATE USER 'ftp'@'localhost' IDENTIFIED BY '[passwd_ftp]';"; +mysql -uroot -p[passwd] -e "GRANT ALL PRIVILEGES ON ftp . * TO 'ftp'@'localhost';"; +mysql -uroot -p[passwd] ftp < /tmp/proftpd_sqldump; \ No newline at end of file diff --git a/system/data/control/proftpd_sql.txt b/system/data/control/proftpd_sql.txt new file mode 100644 index 0000000..16f2c2a --- /dev/null +++ b/system/data/control/proftpd_sql.txt @@ -0,0 +1,23 @@ + + SQLBackend mysql + SQLEngine on + SQLAuthTypes Plaintext + SQLConnectInfo ftp@localhost root [passwd] + SQLUserInfo users username password uid gid homedir shell + SQLAuthenticate users* + SQLMinUserUID 33 + SQLMinUserGID 33 + + + + QuotaEngine on + QuotaDirectoryTally on + QuotaDisplayUnits Mb + QuotaShowQuotas on + SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM quotalimits WHERE name = '%{0}' AND quota_type = '%{1}'" + SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM quotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" + SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" quotatallies + SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" quotatallies + QuotaLimitTable sql:/get-quota-limit + QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally + \ No newline at end of file diff --git a/system/data/control/proftpd_sqldump.txt b/system/data/control/proftpd_sqldump.txt new file mode 100644 index 0000000..fc527cd --- /dev/null +++ b/system/data/control/proftpd_sqldump.txt @@ -0,0 +1,33 @@ +CREATE TABLE IF NOT EXISTS `users` ( + `username` varchar(32) NOT NULL, + `password` varchar(32) NOT NULL, + `uid` int(11) NOT NULL, + `gid` int(11) NOT NULL DEFAULT '1000', + `homedir` varchar(255) NOT NULL, + `shell` varchar(255) NOT NULL DEFAULT '/bin/false', + UNIQUE KEY `username` (`username`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `quotalimits` ( + `name` varchar(30) DEFAULT NULL, + `quota_type` enum('user','group','class','all') NOT NULL, + `per_session` enum('false','true') NOT NULL, + `limit_type` enum('soft','hard') NOT NULL, + `bytes_in_avail` float NOT NULL DEFAULT '0', + `bytes_out_avail` float NOT NULL DEFAULT '0', + `bytes_xfer_avail` float NOT NULL DEFAULT '0', + `files_in_avail` int(10) unsigned NOT NULL DEFAULT '0', + `files_out_avail` int(10) unsigned NOT NULL DEFAULT '0', + `files_xfer_avail` int(10) unsigned NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `quotatallies` ( + `name` varchar(30) NOT NULL, + `quota_type` enum('user','group','class','all') NOT NULL, + `bytes_in_used` float NOT NULL DEFAULT '0', + `bytes_out_used` float NOT NULL DEFAULT '0', + `bytes_xfer_used` float NOT NULL DEFAULT '0', + `files_in_used` int(10) unsigned NOT NULL DEFAULT '0', + `files_out_used` int(10) unsigned NOT NULL DEFAULT '0', + `files_xfer_used` int(10) unsigned NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/system/data/control/rclocal.txt b/system/data/control/rclocal.txt new file mode 100644 index 0000000..d529bd3 --- /dev/null +++ b/system/data/control/rclocal.txt @@ -0,0 +1,3 @@ +/root/iptables_block + +exit 0 \ No newline at end of file diff --git a/system/data/engine.php b/system/data/engine.php new file mode 100644 index 0000000..6c7da1a --- /dev/null +++ b/system/data/engine.php @@ -0,0 +1,193 @@ + '/^[A-Za-z0-9_]{4,16}$/', + 'mail' => '/^([a-z0-9_\.-])+@[a-z0-9-]+\.([a-z]{2,4}\.)?[a-z]{2,4}$/i', + 'name' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'lastname' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'patronymic' => '/^[А-Я]{1,1}[а-я]{2,15}$/u', + 'phone' => '/^380+[0-9]{9,9}$|^77+[0-9]{9,9}$|^79+[0-9]{9,9}$|^375+[0-9]{9,9}$/m', + 'contacts' => '/^(http|https):\/\/(new\.vk|vk)\.com\/[A-Za-z\_\.]{1,2}[A-Za-z0-9\_\.]{4,32}$|^[A-Za-z][A-Za-z0-9\.\-\_]{6,32}$/', + 'passwd' => '/^[A-Za-z0-9]{6,26}$/', + 'cslogs' => '/^L[A-Za-z0-9\.]/', + 'csamxlogs' => '/^[A-Za-z0-9_\.-]/', + 'csssmlogs' => '/^[A-Za-z0-9_\.-]/', + 'address' => '/^(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}:[0-9]{4,5}$/', + ); + + // Массив данных для регистрации + $aSignup = array( + // Массив дополнительных полей + 'input' => array( + 'login' => true, + 'mail' => true, + 'name' => true, + 'lastname' => true, + 'patronymic' => false, + 'phone' => false, + 'contacts' => false, + 'passwd' => true + ), + // Массив описания полей + 'info' => array( + 'login' => 'Логин', + 'mail' => 'Почта', + 'name' => 'Имя', + 'lastname' => 'Фамилия', + 'patronymic' => 'Отчество', + 'phone' => 'Телефон', + 'contacts' => 'Контакты', + 'passwd' => 'Пароль' + ), + // Массив типа полей + 'type' => array( + 'login' => 'text', + 'mail' => 'text', + 'name' => 'text', + 'lastname' => 'text', + 'patronymic' => 'text', + 'phone' => 'text', + 'contacts' => 'text', + 'passwd' => 'password' + ), + // Массив подсказки полей + 'placeholder' => array( + 'login' => 'Введите логин', + 'mail' => 'Введите почту', + 'name' => 'Введите имя', + 'lastname' => 'Введите фамилию', + 'patronymic' => 'Введите отчество', + 'phone' => 'Введите номер', + 'contacts' => 'Введите skype или vk', + 'passwd' => 'Введите пароль' + ) + ); + + // Данные для вывода информаци отправителя + $iHelp = 0; // 0 = Имя/Отчество || 1 = Имя || 2 = Логин | 3 = Почта + + // Вывод времени сообщения + $tHelp = 0; // 0 - вариант: * минут назад (макс 10мин) || 1 - дата. время (* минут назад) + + // Названия игр + $aGname = array( + 'cs' => 'CS: 1.6', + 'css' => 'CS: Source', + 'csgo' => 'CS: Global Offensive', + 'cssold' => 'CS: Source v34', + 'mc' => 'MineCraft', + 'mta' => 'GTA: MTA', + 'samp' => 'GTA: SAMP', + 'crmp' => 'GTA: CRMP' + ); + + // Роутер подразделов + $aRouteSub = array( + 'settings' => array( + 'api', + 'pack', + 'firewall', + 'crontab', + 'startlogs', + 'file' + ), + ); + + // Директория логов StartLogs + $aSLdir = array( + 'cs' => 'cstrike/oldstart', + 'cssold' => 'cstrike/oldstart', + 'css' => 'cstrike/oldstart', + 'csgo' => 'csgo/oldstart', + 'mc' => 'oldstart', + 'mta' => 'mods/deathmatch/oldstart', + 'samp' => 'oldstart', + 'crmp' => 'oldstart' + ); + + // Директория логов StartLogs ftp (указывать изходя из настроек ftp) + $aSLdirFtp = array( + 'cs' => 'oldstart', + 'cssold' => 'oldstart', + 'css' => 'oldstart', + 'csgo' => 'csgo/oldstart', + 'mc' => 'oldstart', + 'mta' => 'mods/deathmatch/oldstart', + 'samp' => 'oldstart', + 'crmp' => 'oldstart' + ); + + // Права для совладельцев + $aOwners = array( + 'cs' => array('start' , 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps', 'filetp', 'tarif', 'copy', 'graph'), + 'cssold' => array('start' , 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps', 'filetp', 'tarif', 'copy', 'graph'), + 'css' => array('start' , 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps', 'filetp', 'tarif', 'copy', 'graph'), + 'csgo' => array('start' , 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps', 'filetp', 'tarif', 'copy', 'graph'), + 'mc' => array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins', 'filetp', 'tarif', 'copy', 'graph'), + 'mta' => array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins', 'filetp', 'tarif', 'copy', 'graph'), + 'samp' => array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins', 'filetp', 'tarif', 'copy', 'graph'), + 'crmp' => array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins', 'filetp', 'tarif', 'copy', 'graph'), + ); + + $aOwnersI = array( + 'start' => 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'change' => 'Смена карты', + 'reinstall' => 'Переустановка', + 'update' => 'Обновление', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"', + 'maps' => 'Раздел "Карты"', + 'filetp' => 'Раздел "FileTP"', + 'tarif' => 'Раздел "Тариф"', + 'copy' => 'Раздел "Копии"', + 'graph' => 'Раздел "Графики"' + ); +?> \ No newline at end of file diff --git a/system/data/filedits.php b/system/data/filedits.php new file mode 100644 index 0000000..9ca62ab --- /dev/null +++ b/system/data/filedits.php @@ -0,0 +1,173 @@ + array( + 'all' => array( + 'files' => array( + 'autoexec.cfg', + 'fastdl.cfg', + 'plugins.ini', + 'users.ini', + 'motd.txt', + ), + 'path' => array( + 'autoexec.cfg' => 'cstrike/', + 'fastdl.cfg' => 'cstrike/', + 'plugins.ini' => 'cstrike/addons/amxmodx/configs/', + 'users.ini' => 'cstrike/addons/amxmodx/configs/', + 'motd.txt' => 'cstrike/', + ), + 'desc' => array( + 'autoexec.cfg' => 'Автоподключаемый конфигурационный файл.', + 'fastdl.cfg' => 'Быстрая закачка файлов с сервера.', + 'plugins.ini' => 'Список плагинов на сервере.', + 'users.ini' => 'Список админов на сервере.', + 'motd.txt' => 'Окно приветствия на сервере.', + ) + ), + + ), + + 'cssold' => array( + 'all' => array( + 'files' => array( + 'autoexec.cfg', + 'fastdl.cfg', + 'admins_simple.ini', + ), + 'path' => array( + 'autoexec.cfg' => 'cstrike/cfg/', + 'fastdl.cfg' => 'cstrike/cfg/', + 'admins_simple.ini' => 'cstrike/addons/sourcemod/configs/', + ), + 'desc' => array( + 'autoexec.cfg' => 'Автоподключаемый конфигурационный файл.', + 'fastdl.cfg' => 'Быстрая закачка файлов с сервера.', + 'admins_simple.ini' => 'Список админов на сервере.', + ) + ) + ), + + 'css' => array( + 'all' => array( + 'files' => array( + 'autoexec.cfg', + 'fastdl.cfg', + 'admins_simple.ini', + ), + 'path' => array( + 'autoexec.cfg' => 'cstrike/cfg/', + 'fastdl.cfg' => 'cstrike/cfg/', + 'admins_simple.ini' => 'cstrike/addons/sourcemod/configs/', + ), + 'desc' => array( + 'autoexec.cfg' => 'Автоподключаемый конфигурационный файл.', + 'fastdl.cfg' => 'Быстрая закачка файлов с сервера.', + 'admins_simple.ini' => 'Список админов на сервере.', + ) + ) + ), + + 'csgo' => array( + 'all' => array( + 'files' => array( + 'autoexec.cfg', + 'fastdl.cfg', + 'webapi_authkey.txt', + ), + 'path' => array( + 'autoexec.cfg' => 'csgo/cfg/', + 'fastdl.cfg' => 'csgo/cfg/', + 'webapi_authkey.txt' => 'csgo/', + ), + 'desc' => array( + 'autoexec.cfg' => 'Автоподключаемый конфигурационный файл.', + 'fastdl.cfg' => 'Быстрая закачка файлов с сервера.', + 'webapi_authkey.txt' => 'API ключ для установки карт из мастерской WorkShop.', + ) + ) + ), + + 'mta' => array( + 'all' => array( + 'files' => array( + 'mtaserver.conf', + 'acl.xml', + 'vehiclecolors.conf' + ), + 'path' => array( + 'mtaserver.conf' => 'mods/deathmatch/', + 'acl.xml' => 'mods/deathmatch/', + 'vehiclecolors.conf' => 'mods/deathmatch/' + ), + 'desc' => array( + 'mtaserver.conf' => 'Основной конфигурационный файл сервера.', + 'acl.xml' => 'Настройки прав на игровом сервере.', + 'vehiclecolors.conf' => 'Настройки цветов автомобилей на игровом сервере.' + ) + ) + ), + + 'mc' => array( + 'all' => array( + 'files' => array( + 'ops.txt', + 'permissions.yml', + 'white-list.txt', + 'banned-players.txt', + 'banned-ips.txt' + ), + 'path' => array( + 'ops.txt' => '/', + 'permissions.yml' => '/', + 'white-list.txt' => '/', + 'banned-players.txt' => '/', + 'banned-ips.txt' => '/' + ), + 'desc' => array( + 'ops.txt' => 'Файл в котором прописываются админы.', + 'permissions.yml' => 'Список разрешений', + 'white-list.txt' => 'Белый список игроков.', + 'banned-players.txt' => 'Забаненные игроки.', + 'banned-ips.txt' => 'Забаненные IP адреса.' + ) + ) + ) + ); + + if(isset($aEditslist)) + { + $dir = isset($ctrlmod) ? 'control/' : ''; + + // Генерация общего списка редактируемых файлов + if(isset($aEdits[$server['game']]['all']['files'])) + foreach($aEdits[$server['game']]['all']['files'] as $file) + { + $html->get('edits_list', 'sections/'.$dir.'servers/games/settings'); + $html->set('id', $id); + $html->set('name', $file); + $html->set('desc', $aEdits[$server['game']]['all']['desc'][$file]); + + if(isset($ctrlmod)) + $html->set('server', $sid); + $html->pack('edits'); + } + + if(!isset($ctrlmod)) + { + // Генерация списка редактируемых файлов по тарифу + if(isset($aEdits[$server['game']][$tarif['name']]['files'])) + foreach($aEdits[$server['game']][$tarif['name']]['files'] as $file) + { + $html->get('edits_list', 'sections/servers/games/settings'); + $html->set('id', $id); + $html->set('name', $file); + $html->set('desc', $aEdits[$server['game']][$tarif['name']]['desc'][$file]); + $html->pack('edits'); + } + } + } +?> \ No newline at end of file diff --git a/system/data/graph.php b/system/data/graph.php new file mode 100644 index 0000000..0b11f83 --- /dev/null +++ b/system/data/graph.php @@ -0,0 +1,42 @@ + array( + 'fon' => array('R' => 232, 'G' => 235, 'B' => 240), + 'border' => array('R' => 220, 'G' => 220, 'B' => 220), + 'graph' => array('R' => 255, 'G' => 255, 'B' => 255, 'Surrounding' => -200, 'Alpha' => 10), + 'line' => array('R' => 68, 'G' => 148, 'B' => 224), + 'leftbox' => array('R' => 0, 'G' => 0, 'B' => 0), + 'box' => array('R' => 0, 'G' => 0, 'B' => 0), + 'boxcolor' => array('R' => 255, 'G' => 255, 'B' => 255), + 'color' => array('R' => 0, 'G' => 0, 'B' => 0), + 'progress' => array('R' => 68, 'G' => 148, 'B' => 224) + ), + + 'black' => array( + 'fon' => array('R' => 0, 'G' => 0, 'B' => 0), + 'border' => array('R' => 232, 'G' => 235, 'B' => 240), + 'graph' => array('R' => 232, 'G' => 235, 'B' => 240, 'Surrounding' => -200, 'Alpha' => 100), + 'line' => array('R' => 68, 'G' => 148, 'B' => 224), + 'leftbox' => array('R' => 255, 'G' => 255, 'B' => 255), + 'box' => array('R' => 255, 'G' => 255, 'B' => 255), + 'boxcolor' => array('R' => 0, 'G' => 0, 'B' => 0), + 'color' => array('R' => 255, 'G' => 255, 'B' => 255), + 'progress' => array('R' => 68, 'G' => 148, 'B' => 224) + ), + + 'camo' => array( + 'fon' => array('R' => 55, 'G' => 62, 'B' => 40), + 'border' => array('R' => 62, 'G' => 68, 'B' => 51), + 'graph' => array('R' => 46, 'G' => 50, 'B' => 37, 'Surrounding' => -200, 'Alpha' => 10), + 'line' => array('R' => 166, 'G' => 186, 'B' => 149), + 'leftbox' => array('R' => 32, 'G' => 35, 'B' => 27), + 'box' => array('R' => 46, 'G' => 50, 'B' => 37), + 'boxcolor' => array('R' => 210, 'G' => 225, 'B' => 181), + 'color' => array('R' => 136, 'G' => 156, 'B' => 99), + 'progress' => array('R' => 136, 'G' => 156, 'B' => 99, 'BoxBorderR' => 46, 'BoxBorderG' => 50, 'BoxBorderB' => 37) + ), + ); +?> \ No newline at end of file diff --git a/system/data/header.php b/system/data/header.php new file mode 100644 index 0000000..83497c1 --- /dev/null +++ b/system/data/header.php @@ -0,0 +1,31 @@ + array( + 'description' => 'Наш хостинг игровых серверов это высокое качество техподдержки, быстрое оформление и разумные расценки. Качественный хостинг игровых серверов', + 'keywords' => 'аренда игровых серверов, хостинг игровых серверов, игровой хостинг, дешевый хостинг игровых серверов, хостинг игровых серверов css, самый дешевый хостинг игровых серверов, качественный хостинг игровых серверов, бесплатный игровой хостинг' + ), + + 'news' => array( + 'description' => 'Наш хостинг игровых серверов это высокое качество техподдержки, быстрое оформление и разумные расценки. Качественный хостинг игровых серверов', + 'keywords' => 'аренда игровых серверов, хостинг игровых серверов, игровой хостинг, дешевый хостинг игровых серверов, хостинг игровых серверов css, самый дешевый хостинг игровых серверов, качественный хостинг игровых серверов, бесплатный игровой хостинг' + ), + + 'services' => array( + 'description' => 'Наш хостинг игровых серверов это высокое качество техподдержки, быстрое оформление и разумные расценки. Качественный хостинг игровых серверов', + 'keywords' => 'аренда игровых серверов, хостинг игровых серверов, игровой хостинг, дешевый хостинг игровых серверов, хостинг игровых серверов css, самый дешевый хостинг игровых серверов, качественный хостинг игровых серверов, бесплатный игровой хостинг' + ), + + 'wiki' => array( + 'description' => 'Наш хостинг игровых серверов это высокое качество техподдержки, быстрое оформление и разумные расценки. Качественный хостинг игровых серверов', + 'keywords' => 'аренда игровых серверов, хостинг игровых серверов, игровой хостинг, дешевый хостинг игровых серверов, хостинг игровых серверов css, самый дешевый хостинг игровых серверов, качественный хостинг игровых серверов, бесплатный игровой хостинг' + ), + + 'contacts' => array( + 'description' => 'Наш хостинг игровых серверов это высокое качество техподдержки, быстрое оформление и разумные расценки. Качественный хостинг игровых серверов', + 'keywords' => 'аренда игровых серверов, хостинг игровых серверов, игровой хостинг, дешевый хостинг игровых серверов, хостинг игровых серверов css, самый дешевый хостинг игровых серверов, качественный хостинг игровых серверов, бесплатный игровой хостинг' + ) + ); +?> \ No newline at end of file diff --git a/system/data/mail.ini b/system/data/mail.ini new file mode 100644 index 0000000..a9d17dd --- /dev/null +++ b/system/data/mail.ini @@ -0,0 +1,51 @@ +
    + + + + + + +
    + + + + + + +
    + + + + + + + + + + + + +
    + + [name] + +
    + + + + + + + + + +
    + +

    + [text] +

    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/system/data/maps.php b/system/data/maps.php new file mode 100644 index 0000000..fbb6158 --- /dev/null +++ b/system/data/maps.php @@ -0,0 +1,29 @@ + array( + 'de' => array('de'), + 'cs' => array('cs'), + 'aim' => array('aim'), + 'awp' => array('awp'), + 'bhop' => array('bhop'), + 'csde' => array('csde'), + 'deathrun' => array('deathrun'), + 'jail' => array('jail', 'jailbreak', 'jb'), + 'zm' => array('zm', 'ze'), + 'fy' => array('fy'), + 'gg' => array('gg'), + 'surf' => array('surf'), + 'dm' => array('dm', 'deathmatch'), + 'as' => array('as'), + 'es' => array('es'), + 'fun' => array('fun'), + 'he' => array('he'), + 'ka' => array('ka'), + 'sp' => array('sp'), + '35hp' => array('35hp') + ) + ); +?> \ No newline at end of file diff --git a/system/data/mysql.php b/system/data/mysql.php new file mode 100644 index 0000000..220679b --- /dev/null +++ b/system/data/mysql.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/system/data/params.php b/system/data/params.php new file mode 100644 index 0000000..072bf8d --- /dev/null +++ b/system/data/params.php @@ -0,0 +1,249 @@ + array( + 'time' => array( + 'buy' => array( + '15' => '+:30', + '90' => '-:5%', + '180' => '-:7%' + ), + + 'extend' => array( + '1' => '+:100%', + '15' => '+:30%', + '90' => '-:5%', + '180' => '-:7%' + ) + ), + + 9 => array( + 'buy' => array( + '30' => '+:49%' + ), + + 'extend' => array( + '1' => '+:50%' + ) + ) + ) + ); + + // Стандартные порты + public static $aDefPort = array( + 'cs' => 27015, + 'cssold' => 27015, + 'css' => 27015, + 'csgo' => 27015, + 'samp' => 7777, + 'crmp' => 7777, + 'mta' => 22003, + 'mc' => 25565, + ); + + // Параметры раздела "Копии" + public static $section_copy = array( + 'cs' => array( + 'CopyFull' => 'cstrike', + + 'aCopy' => array( + 'addons' => 'Директория с дополнениями (модули/плагины)', + 'cfg' => 'Файлы настроек (server.cfg/motd.txt/liblist.gam/banned.cfg и т.д.)', + 'dlls' => 'Директория с библиотеками (название.so)', + 'gfx' => 'Директория с изображениями (название.tga)', + 'maps' => 'Директория с картами (название.bsp)', + 'models' => 'Директория с моделями (название.mdl)', + 'sound' => 'Директория со звуками (название.mp3/название.wav)' + ), + + 'aCopyDir' => array( + 'addons' => 'cstrike/addons', + 'dlls' => 'cstrike/dlls', + 'gfx' => 'cstrike/gfx', + 'maps' => 'cstrike/maps', + 'models' => 'cstrike/models', + 'sound' => 'cstrike/sound' + ), + + 'aCopyFile' => array( + 'cfg' => 'cstrike/server.cfg cstrike/motd.txt cstrike/fastdl.cfg cstrike/liblist.gam cstrike/banned.cfg cstrike/listip.cfg cstrike/reunion.cfg cstrike/mapcycle.txt' + ) + ), + + 'cssold' => array( + 'CopyFull' => 'cstrike', + + 'aCopy' => array( + 'addons' => 'Директория с дополнениями (модули/плагины)', + 'cfg' => 'Файлы настроек (server.cfg/motd.txt/banned_user.cfg/banned_ip.cfg и т.д.)', + 'maps' => 'Директория с картами (название.bsp)', + 'models' => 'Директория с моделями (название.mdl)', + 'sound' => 'Директория со звуками (название.mp3/название.wav)' + ), + + 'aCopyDir' => array( + 'addons' => 'cstrike/addons', + 'maps' => 'cstrike/maps', + 'models' => 'cstrike/models', + 'sound' => 'cstrike/sound' + ), + + 'aCopyFile' => array( + 'cfg' => 'cstrike/cfg/server.cfg cstrike/motd.txt cstrike/fastdl.cfg cstrike/banned_user.cfg cstrike/banned_ip.cfg cstrike/mapcycle.txt cstrike/maplist.txt' + ) + ), + + 'css' => array( + 'CopyFull' => 'cstrike', + + 'aCopy' => array( + 'addons' => 'Директория с дополнениями (модули/плагины)', + 'cfg' => 'Файлы настроек (server.cfg/motd.txt/banned_user.cfg/banned_ip.cfg и т.д.)', + 'maps' => 'Директория с картами (название.bsp)', + 'models' => 'Директория с моделями (название.mdl)', + 'sound' => 'Директория со звуками (название.mp3/название.wav)' + ), + + 'aCopyDir' => array( + 'addons' => 'cstrike/addons', + 'maps' => 'cstrike/maps', + 'models' => 'cstrike/models', + 'sound' => 'cstrike/sound' + ), + + 'aCopyFile' => array( + 'cfg' => 'cstrike/cfg/server.cfg cstrike/motd.txt cstrike/fastdl.cfg cstrike/banned_user.cfg cstrike/banned_ip.cfg cstrike/mapcycle.txt cstrike/maplist.txt' + ) + ), + + 'csgo' => array( + 'CopyFull' => 'csgo', + + 'aCopy' => array( + 'addons' => 'Директория с дополнениями (модули/плагины)', + 'cfg' => 'Файлы настроек (server.cfg/motd.txt/banned_user.cfg/banned_ip.cfg и т.д.)', + 'maps' => 'Директория с картами (название.bsp)', + 'models' => 'Директория с моделями (название.mdl)', + 'sound' => 'Директория со звуками (название.mp3/название.wav)' + ), + + 'aCopyDir' => array( + 'addons' => 'csgo/addons', + 'maps' => 'csgo/maps', + 'models' => 'csgo/models', + 'sound' => 'csgo/sound' + ), + + 'aCopyFile' => array( + 'cfg' => 'csgo/cfg/server.cfg csgo/motd.txt csgo/fastdl.cfg csgo/banned_user.cfg csgo/banned_ip.cfg csgo/mapcycle.txt csgo/maplist.txt' + ) + ), + + 'samp' => array( + 'CopyFull' => '*', + + 'aCopy' => array( + 'filterscripts' => 'Директория с дополнительными скриптами', + 'cfg' => 'Файл настроек (server.cfg)', + 'gamemodes' => 'Директория с модами', + 'scriptfiles' => 'Директория с скриптами' + ), + + 'aCopyDir' => array( + 'filterscripts' => 'filterscripts', + 'gamemodes' => 'gamemodes', + 'scriptfiles' => 'scriptfiles' + ), + + 'aCopyFile' => array( + 'cfg' => 'server.cfg' + ) + ), + + 'crmp' => array( + 'CopyFull' => '*', + + 'aCopy' => array( + 'filterscripts' => 'Директория с дополнительными скриптами', + 'cfg' => 'Файл настроек (server.cfg)', + 'gamemodes' => 'Директория с модами', + 'scriptfiles' => 'Директория с скриптами' + ), + + 'aCopyDir' => array( + 'filterscripts' => 'filterscripts', + 'gamemodes' => 'gamemodes', + 'scriptfiles' => 'scriptfiles' + ), + + 'aCopyFile' => array( + 'cfg' => 'server.cfg' + ) + ), + + 'mta' => array( + 'CopyFull' => '*', + + 'aCopy' => array( + 'databases' => 'Директория баз данных', + 'cfg' => 'Файлы настроек (mtaserver.conf, acl.xml, vehiclecolors.conf и т.д.)', + 'modules ' => 'Директория с модулями', + 'resources' => 'Директория с ресурсами' + ), + + 'aCopyDir' => array( + 'databases' => 'mods/deathmatch/databases', + 'modules' => 'mods/deathmatch/modules', + 'resources' => 'mods/deathmatch/resources' + ), + + 'aCopyFile' => array( + 'cfg' => 'mods/deathmatch/mtaserver.conf mods/deathmatch/acl.xml mods/deathmatch/vehiclecolors.conf mods/deathmatch/settings.xml' + ) + ) + ); + + // Дни в месяцах + public static $aDayMonth = array( + 1 => 31, 2 => 28, 3 => 31, 4 => 30, + 5 => 31, 6 => 30, 7 => 31, 8 => 31, + 9 => 30, 10 => 31, 11 => 30, 12 => 31 + ); + + // Названия месяцев + public static $aNameMonth = array( + 1 => 'Январь', 2 => 'Февраль', 3 => 'Март', 4 => 'Апрель', + 5 => 'Май', 6 => 'Июнь', 7 => 'Июль', 8 => 'Август', + 9 => 'Сентябрь', 10 => 'Октябрь', 11 => 'Ноябрь', 12 => 'Декабрь' + ); + + // Директории + public static $aDirGame = array( + 'cs' => 'cstrike', + 'cssold' => 'cstrike', + 'css' => 'cstrike', + 'csgo' => 'csgo', + 'samp' => '', + 'crmp' => '', + 'mta' => '', + 'mc' => '', + ); + + // Исполняемые файлы + public static $aFileGame = array( + 'cs' => 'hlds_run hlds_linux hlds_i686', + 'cssold' => 'srcds_run srcds_i486 srcds_i686', + 'css' => 'srcds_linux srcds_run', + 'csgo' => 'srcds_linux srcds_run', + 'samp' => 'samp03svr', + 'crmp' => 'samp03svr-cr', + 'mta' => 'mta-server', + 'mc' => 'start.jar' + ); + } +?> \ No newline at end of file diff --git a/system/data/scfg/crmp.php b/system/data/scfg/crmp.php new file mode 100644 index 0000000..a00972b --- /dev/null +++ b/system/data/scfg/crmp.php @@ -0,0 +1,53 @@ + 'Название игрового сервера.', + 'rcon' => 'Управление RCON командами.', + 'rcon_password' => 'Пароль для упраления сервером через RCON команды.', + 'password' => 'Пароль для входа на сервер.', + 'lanmode' => 'Тип игрового сервера.', + 'gamemode0' => 'Моды на сервере.', + 'filterscripts' => 'Сценарии на сервере.', + 'announce' => 'Отображение сервера в интернете.', + 'weburl' => 'Адрес сайта севера.', + 'maxnpc' => 'Максимальное число NPC подключаемых к серверу.', + 'onfoot_rate' => 'Время в миллисекундах за которое сервер обновляет данные о пешем игроке.', + 'incar_rate' => 'Время в миллисекундах за которое сервер обновляет данные о игроке находящемся в транспорте.', + 'weapon_rate' => 'Время в миллисекундах за которое сервер обновляет данные о стрельбе игрока.', + 'stream_distance' => 'Дистанция для обновления стримера игроков.', + 'stream_rate' => 'Время в миллисекундах за которое сервер обновляет игроков в стримере.', + 'logqueries' => 'Логирование всех запросов.' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'password' => '', + 'gamemode0' => '', + 'filterscripts' => '', + 'maxnpc' => '', + 'onfoot_rate' => '', + 'incar_rate' => '', + 'weapon_rate' => '', + 'stream_distance' => '', + 'stream_rate' => '', + 'lagcompmode' => '', + 'rcon' => '', + 'announce' => '', + 'logqueries' => '', + 'lanmode' => '' + ); +?> \ No newline at end of file diff --git a/system/data/scfg/cs.php b/system/data/scfg/cs.php new file mode 100644 index 0000000..8754229 --- /dev/null +++ b/system/data/scfg/cs.php @@ -0,0 +1,104 @@ + 'Название игрового сервера.', + 'rcon_password' => 'Пароль для упраления сервером через RCON команды.', + 'sv_password' => 'Пароль для входа на сервер.', + 'decalfrequency' => 'Установить как часто игрок может рисовать свою эмблему. Значения выставляются в секундах.', + 'allow_spectators' => 'Максимальное количество наблюдателей на сервере. Поставтьте 0, что бы выключить.', + 'mp_autokick' => 'Включает автоматический бан для тимкиллеров и кикает подвисших игроков.', + 'mp_autoteambalance' => 'Автобаланс игроков.', + 'mp_chattime' => 'Количество секунд на которое сервер позволяет игрокам писать в общий чат после конца карты и до загрузки новой.', + 'mp_decals' => 'Определяет количество декалов на сервере (напр кол-во дырок от пуль на стенах сохраняемых сервером).', + 'mp_fadetoblack' => 'Погибшие игроки не могут наблюдать за игрой (черный экран).', + 'mp_flashlight' => 'Разрешить использовать фонарик.', + 'mp_footsteps' => 'Разрешить игрокам слышать звук шагов.', + 'mp_forcecamera' => 'Задает также параметры наблюдения.', + 'mp_forcechasecam' => 'Команда задает режим наблюдения за игроками.', + 'mp_fraglimit' => 'Лимит убийств игрока до смены карты. 0 - Отключено.', + 'mp_freezetime' => 'Время заморозки игроков перед началом раунда. 0 - Отключено.', + 'mp_friendlyfire' => 'Нанесение повреждений игрокам своей команды.', + 'mp_hostagepenalty' => 'Устанавливает количество заложников, которых можно убить, прежде чем вас выкинет с сервера. 0 - Отключено.', + 'mp_limitteams' => 'Число игроков, на которое одна команда может превышать другую. Лишних игроков не будет пускать в команду. 0 - Отключено.', + 'mp_maxrounds' => 'Максимальное количество раундов, которые могут быть сыграны на карте до ее смены.', + 'mp_playerid' => 'Всплывающие подсказки при наведении прицела на игрока.', + 'mp_roundtime' => 'Время раунда. Измеряется в минутах.', + 'mp_startmoney' => 'Количество денег у игрока в первом раунде.', + 'mp_timelimit' => 'Время, отведенное на одну карту. Измеряется в минутах. Значение 0 - отключение лимита времени.', + 'mp_tkpunish' => 'В начале нового раунда убивает игрока, который в предыдущем убил игрока своей команды.', + 'mp_winlimit' => 'Ограничение по победам на карту.', + 'sv_allowdownload' => 'Возможность скачивать с сервера файлы.', + 'sv_allowupload' => 'Возможность закачивать на сервер файлы. Например спрэи.', + 'sv_alltalk' => 'Режим работы общего голосового чата. При включении все игроки будут слышать друг друга независимо от команды, в которой они играют.', + 'sv_gravity' => 'Гравитация на сервере. По умолчанию 800.', + 'sv_maxspeed' => 'Максимальная скорость передвижения игроков на сервере. По умолчанию 320.', + 'sv_maxunlag' => 'Максимальная лаго компенсация в секунду.', + 'pausable' => 'Возможность использования паузы во время игры.', + 'sv_voiceenable' => 'Возможность использовать микрофон в игре.', + 'mp_c4timer' => 'Время таймера до взрыва бомбы с момента ее установки. Измеряется в секундах.', + 'mp_consistency' => 'Проверка соответствия файлов сервера и клиента.', + 'mp_buytime' => 'Время для закупки оружия в начале раунда. Значение выставляется в минутах.', + 'sv_contact' => 'Контакты админа.', + 'sv_rcon_banpenalty' => 'Колличество минут на которое банится игрок пытавшийся подобрать rcon-пароль к серверу.', + 'sv_rcon_maxfailures' => 'Максимальное колличество попыток при наборе rcon-пароля, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailures' => 'Колличество попыток при наборе rcon-пароля во время заданное sv_rcon_minfailuretime, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailuretime' => 'Колличество секунд для определения неверной rcon-аутенфикации.', + 'sv_maxrate' => 'Максимально-допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_maxupdaterate' => 'Максимальное количество переданных пакетов в секунду.', + 'sv_minrate' => 'Минимально допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_minupdaterate' => 'Минимальное количество переданных пакетов в секунду.', + 'mp_mapvoteratio' => 'Процент голосование за следующую карту, командой votemap.' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'sv_password' => '', + 'decalfrequency' => '', + 'allow_spectators' => '', + 'mp_autokick' => '', + 'mp_autoteambalance' => '', + 'mp_chattime' => '', + 'mp_decals' => '', + 'mp_fadetoblack' => '', + 'mp_flashlight' => '', + 'mp_footsteps' => '', + 'mp_forcecamera' => '', + 'mp_fraglimit' => '', + 'mp_freezetime' => '', + 'mp_friendlyfire' => '', + 'mp_hostagepenalty' => '', + 'mp_limitteams' => '', + 'mp_maxrounds' => '', + 'mp_playerid' => '', + 'mp_roundtime' => '', + 'mp_startmoney' => '', + 'mp_timelimit' => '', + 'mp_tkpunish' => '', + 'mp_winlimit' => '', + 'sv_allowdownload' => '', + 'sv_allowupload' => '', + 'sv_alltalk' => '', + 'sv_gravity' => '', + 'sv_maxspeed' => '', + 'sv_maxunlag' => '', + 'pausable' => '', + 'sv_voiceenable' => '', + 'mp_c4timer' => '', + 'mp_consistency' => '', + 'mp_buytime' => '', + 'sv_contact' => '', + 'sv_rcon_banpenalty' => '', + 'sv_rcon_maxfailures' => '', + 'sv_rcon_minfailures' => '', + 'sv_rcon_minfailuretime' => '', + 'sv_maxrate' => '', + 'sv_maxupdaterate' => '', + 'sv_minrate' => '', + 'sv_minupdaterate' => '', + 'mp_mapvoteratio' => '', + 'mp_forcechasecam' => '' + ); +?> \ No newline at end of file diff --git a/system/data/scfg/csgo.php b/system/data/scfg/csgo.php new file mode 100644 index 0000000..74a59cf --- /dev/null +++ b/system/data/scfg/csgo.php @@ -0,0 +1,46 @@ + 'Название игрового сервера.', + 'rcon_password' => 'Пароль для упраления сервером через RCON команды.', + 'sv_password' => 'Пароль для входа на сервер.', + 'sv_pure' => 'Режим проверки соответствия файлов моделей на клиенте.', + 'host_name_store' => 'Передача названия сервера в GOTV.', + 'host_info_show' => 'Передача информации о сервере.', + 'host_players_show' => 'Передача информации о игроках на сервере.', + 'sv_steamgroup' => 'Группа в steam сервера.', + 'sv_downloadurl' => 'Место, из которого клиенты могут скачать недостающие файлы.
    Использовать, если не включен FastDL.', + 'mapgroup' => 'Набор карт на сервере.', + 'sv_hibernate_when_empty' => 'Через сколько секунд переводить сервер в спящий режим.
    0 = Cпящий режим выключен.', + 'sv_setsteamaccount' => 'Токен для игрового сервера (без него на сервер не смогут зайти игроки).' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'sv_password' => '', + 'sv_pure' => '', + 'host_name_store' => '', + 'host_info_show' => '', + 'host_players_show' => '', + 'sv_steamgroup' => '', + 'sv_downloadurl' => '', + 'mapgroup' => '', + 'sv_hibernate_when_empty' => '', + 'sv_setsteamaccount' => '' + ); +?> \ No newline at end of file diff --git a/system/data/scfg/css.php b/system/data/scfg/css.php new file mode 100644 index 0000000..094dab2 --- /dev/null +++ b/system/data/scfg/css.php @@ -0,0 +1,152 @@ + 'Название игрового сервера.', + 'rcon_password' => 'Пароль для управления сервером через RCON команды.', + 'sv_password' => 'Пароль доступа на сервер.', + 'mp_allowspectators' => 'Присутствие в игре спектаторов.', + 'mp_autoteambalance' => 'Выравнивание количества играющих в командах.', + 'mp_chattime' => 'Время перед сменой карты после победы одной из команд. Измеряется в секундах.', + 'mp_decals' => 'Определяет количество декалов на сервере (например кол-во дырок от пуль на стенах сохраняемых сервером)', + 'mp_fadetoblack' => 'Мертвые игроки не могут наблюдать за игрой (черный экран)', + 'mp_falldamage' => 'Режим реалистичных повреждений при падениях с крыш и т.п.', + 'mp_flashlight' => 'Разрешить использовать фонарик.', + 'mp_footsteps' => 'Разрешить игрокам слышать звук шагов.', + 'mp_forcecamera' => 'Отключает режим свободного обзора для мертвых игроков.', + 'mp_forcerespawn' => 'Режим автоматического подключения игроков за команду.', + 'mp_fraglimit' => 'Лимит убийств игрока до смены карты. 0 - Отключено.', + 'mp_freezetime' => 'Время закупки перед началом раунда. (Заморозка игроков на одном месте).', + 'mp_friendlyfire' => 'Нанесение повреждений игрокам своей команды.', + 'mp_hostagepenalty' => 'Устанавливает количество заложников, которых можно убить, прежде чем вас выкинет с сервера. 0 - Отключено.', + 'mp_limitteams' => 'Число игроков, на которое одна команда может превышать другую. Лишних игроков не будет пускать в команду. 0 - Отключено.', + 'mp_maxrounds' => 'Максимальное количество раундов, которые могут быть сыграны на карте до ее смены.', + 'mp_playerid' => 'Всплывающие подсказки при наведении прицела на игрока.', + 'mp_roundtime' => 'Время раунда. Измеряется в минутах.', + 'mp_spawnprotectiontime' => 'Время защиты игрока после респавна. Измеряется в секундах.', + 'mp_startmoney' => 'Количество денег у игрока в первом раунде.', + 'mp_timelimit' => 'Время, отведенное на одну карту. Измеряется в минутах. Значение 0 - отключение лимита времени. 0 = Отключено.', + 'mp_tkpunish' => 'В начале нового раунда убивает игрока, который в предыдущем убил игрока своей команды.', + 'mp_weaponstay' => 'Упавшее с игроков оружие остается лежать на земле.', + 'mp_winlimit' => 'Ограничение по победам на карту.', + 'sv_airaccelerate' => 'Ускорение игрока в полете. Опцию имеет смысл изменять только для Surf сервера.', + 'sv_allowdownload' => 'Возможность скачивать с сервера файлы.', + 'sv_allowupload' => 'Возможность закачивать на сервер файлы. Например эмблемы.', + 'sv_alltalk' => 'Режим работы общего голосового чата. При включении все игроки будут слышать друг друга независимо от команды, в которой они играют.', + 'sv_gravity' => 'Гравитация на сервере. По умолчанию 800.', + 'sv_pausable' => 'Возможность использования паузы во время игры.', + 'sv_voiceenable' => 'Режим работы голосового чата в игре.', + 'sv_downloadurl' => 'Место, из которого клиенты могут загрузить недостающие файлы.', + 'mp_c4timer' => 'Время таймера до взрыва бомбы с момента ее установки. Измеряется в секундах.', + 'sv_timeout' => 'Таймаут подключения при потери связи.', + 'sv_pure' => 'Проверка соответствия файлов сервера и клиента.', + 'sv_pushaway_force' => 'Сила отталкивания предметов.', + 'sv_turbophysics' => 'Позволяет толкать предметы при нажатии на кнопку "E"', + 'mp_buytime' => 'Время для закупки оружия в начале раунда. Значение выставляется в минутах.', + 'net_maxfilesize' => 'Максимальный размер загружаемого файла в MB.', + 'sv_contact' => 'Контакты админа игрового сервера.', + 'sm_deadtalk' => 'Голосовое общение мертвых игроков.', + 'sv_nostats' => 'Статистика и получение достижений (achievements) на сервере.', + 'sv_nomvp' => 'MVP (самый результативный игрок).', + 'sv_nonemesis' => 'Cистема доминирования и реванша на сервере.', + 'sv_disablefreezecam' => 'Заморозка камеры при убийстве.', + 'sv_rcon_banpenalty' => 'Колличество минут на которое банится игрок пытавшийся подобрать rcon-пароль к серверу.', + 'sv_rcon_maxfailures' => 'Максимальное колличество попыток при наборе rcon-пароля, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailures' => 'Колличество попыток при наборе rcon-пароля во время заданное sv_rcon_minfailuretime, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailuretime' => 'Колличество секунд для определения неверной rcon-аутенфикации.', + 'sv_maxrate' => 'Максимально-допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_mincmdrate' => 'Минимальное количество пакетов в секунду к серверу.', + 'sv_minrate' => 'Минимально допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_maxcmdrate' => 'Максимальное количество пакетов в секунду к серверу.', + 'sv_minupdaterate' => 'Минимальное количество переданных пакетов в секунду.', + 'sv_client_cmdrate_difference' => '-', + 'sv_maxupdaterate' => 'Максимальное количество переданных пакетов в секунду.', + 'sv_steamgroup' => 'Номер группы Steam для отображения Вашего сервера в списке серверов у игроков Группы в главном меню игры.', + 'sv_tags' => 'Отображается справа в браузере поиска серверов.', + 'sv_enablebunnyhopping' => 'Распрыжка (Bhop)', + 'mp_ignore_round_win_conditions' => 'Бесконечный раунд на сервере.', + 'sv_maxspeed' => 'Максимальная скорость передвижения игроков на сервере. По умолчанию 320', + 'mp_disable_respawn_times' => 'Время респауна обоих команда, в секундах.', + 'sv_ignoregrenaderadio' => 'Радио-уведомление "Fire In Hole!" При броске гранаты.', + 'sv_hudhint_sound' => 'Озвучивать окошко подсказок.', + 'phys_timescale' => 'Коэффициент шкалы времени для вычисления "физики" в игре. Если по тарифу тикрейт 100, то нужно выставить значение 1.5.', + 'sv_use_steam_voice' => 'Использовать голосовой кодек Steam.', + 'sv_allow_voice_from_file' => 'Разрешить игрокам использовать voice_inputfromfile на сервере.' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'sv_password' => '', + 'mp_allowspectators' => '', + 'sv_allow_voice_from_file' => '', + 'mp_playerid' => '', + 'mp_autokick' => '', + 'sv_pure' => '', + 'sm_deadtalk' => '', + 'mp_autoteambalance' => '', + 'mp_fadetoblack' => '', + 'mp_falldamage' => '', + 'mp_flashlight' => '', + 'mp_footsteps' => '', + 'mp_forcecamera' => '', + 'mp_forcerespawn' => '', + 'mp_friendlyfire' => '', + 'mp_tkpunish' => '', + 'mp_weaponstay' => '', + 'sv_allowdownload' => '', + 'sv_allowupload' => '', + 'sv_alltalk' => '', + 'sv_pausable' => '', + 'sv_voiceenable' => '', + 'sv_turbophysics' => '', + 'sv_nostats' => '', + 'sv_nomvp' => '', + 'sv_nonemesis' => '', + 'sv_enablebunnyhopping' => '', + 'mp_ignore_round_win_conditions' => '', + 'sv_use_steam_voice' => '', + 'sv_disablefreezecam' => '', + 'sv_ignoregrenaderadio' => '', + 'sv_hudhint_sound' => '', + 'mp_chattime' => '', + 'mp_decals' => '', + 'mp_fraglimit' => '', + 'mp_freezetime' => '', + 'mp_hostagepenalty' => '', + 'mp_limitteams' => '', + 'mp_maxrounds' => '', + 'mp_roundtime' => '', + 'mp_spawnprotectiontime' => '', + 'mp_startmoney' => '', + 'mp_timelimit' => '', + 'mp_winlimit' => '', + 'sv_airaccelerate' => '', + 'sv_gravity' => '', + 'sv_downloadurl' => '', + 'mp_c4timer' => '', + 'sv_timeout' => '', + 'sv_pushaway_force' => '', + 'mp_buytime' => '', + 'net_maxfilesize' => '', + 'sv_contact' => '', + 'sv_rcon_banpenalty' => '', + 'sv_rcon_maxfailures' => '', + 'sv_rcon_minfailures' => '', + 'sv_rcon_minfailuretime' => '', + 'sv_maxrate' => '', + 'sv_mincmdrate' => '', + 'sv_minrate' => '', + 'sv_minupdaterate' => '', + 'sv_client_cmdrate_difference' => '', + 'sv_maxupdaterate' => '', + 'sv_steamgroup' => '', + 'sv_tags' => '', + 'sv_maxspeed' => '', + 'mp_disable_respawn_times' => '', + 'phys_timescale' => '', + 'sv_maxcmdrate' => '' + + ); +?> \ No newline at end of file diff --git a/system/data/scfg/cssold.php b/system/data/scfg/cssold.php new file mode 100644 index 0000000..2e34d60 --- /dev/null +++ b/system/data/scfg/cssold.php @@ -0,0 +1,126 @@ + 'Название игрового сервера.', + 'rcon_password' => 'Пароль для упраления сервером через RCON команды.', + 'sv_password' => 'Пароль для входа на сервер.', + 'decalfrequency' => 'Установить как часто игрок может рисовать свою эмблему. Значения выставляются в секундах.', + 'mp_allowspectators' => 'Присутствие в игре спектаторов.', + 'mp_autokick' => 'Включает автоматическое запрещение тим-киллеров и скидывает не играющих клиентов.', + 'mp_autoteambalance' => 'Выравнивание количества играющих в командах.', + 'mp_chattime' => 'Время перед сменой карты после победы одной из команд. Измеряется в секундах.', + 'mp_decals' => 'Определяет количество декалов на сервере (напр кол-во дырок от пуль на стенах сохраняемых сервером).', + 'mp_fadetoblack' => 'Погибшие игроки не могут наблюдать за игрой (черный экран).', + 'mp_falldamage' => 'Режим реалистичных повреждений при падениях с крыш и т.п.', + 'mp_flashlight' => 'Разрешить использовать фонарик.', + 'mp_footsteps' => 'Разрешить игрокам слышать звук шагов.', + 'mp_forcecamera' => 'Отключает режим свободного обзора для мертвых игроков.', + 'mp_forcerespawn' => 'Режим автоматического подключения игроков за команду', + 'mp_fraglimit' => 'Лимит убийств игрока до смены карты. 0 - Отключено.', + 'mp_freezetime' => 'Время закупки перед началом раунда. (Заморозка игроков на одном месте).', + 'mp_friendlyfire' => 'Нанесение повреждений игрокам своей команды.', + 'mp_hostagepenalty' => 'Устанавливает количество заложников, которых можно убить, прежде чем вас выкинет с сервера. 0 - Отключено.', + 'mp_limitteams' => 'Число игроков, на которое одна команда может превышать другую. Лишних игроков не будет пускать в команду. 0 - Отключено.', + 'mp_maxrounds' => 'Максимальное количество раундов, которые могут быть сыграны на карте до ее смены.', + 'mp_playerid' => 'Всплывающие подсказки при наведении прицела на игрока.', + 'mp_roundtime' => 'Время раунда. Измеряется в минутах.', + 'mp_spawnprotectiontime' => 'Время защиты игрока после респавна. Измеряется в секундах.', + 'mp_startmoney' => 'Количество денег у игрока в первом раунде.', + 'mp_timelimit' => 'Время, отведенное на одну карту. Измеряется в минутах. Значение 0 - отключение лимита времени. 0 = Отключено.', + 'mp_tkpunish' => 'В начале нового раунда убивает игрока, который в предыдущем убил игрока своей команды.', + 'mp_weaponstay' => 'Упавшее с игроков оружие остается лежать на земле.', + 'mp_winlimit' => 'Ограничение по победам на карту.', + 'mp_c4timer' => 'Время таймера до взрыва бомбы с момента ее установки. Измеряется в секундах.', + 'mp_buytime' => 'Время для закупки оружия в начале раунда. Значение выставляется в минутах.', + 'sv_airaccelerate' => 'Ускорение игрока в полете. Опцию имеет смысл изменять только для Surf сервера.', + 'sv_downloadurl' => 'Место, из которого клиенты могут скачать недостающие файлы.
    Использовать, если не включен FastDL.', + 'sv_allowdownload' => 'Возможность скачивать с сервера файлы.', + 'sv_allowupload' => 'Возможность закачивать на сервер файлы. Например эмблемы.', + 'sv_alltalk' => 'Режим работы общего голосового чата. При включении все игроки будут слышать друг друга независимо от команды, в которой они играют.', + 'sm_deadtalk' => 'Голосовое общение мертвых игроков.', + 'sv_consistency' => 'Режим проверки соответствия файлов моделей на клиенте.', + 'sv_gravity' => 'Гравитация на сервере. По умолчанию 800.', + 'sv_maxspeed' => 'Максимальная скорость передвижения игроков на сервере. По умолчанию 320.', + 'sv_maxunlag' => 'Опция влияет на хитбоксы и стрельбу. Меняйте только в том случае, если вы точно знаете, что делаете.', + 'sv_pausable' => 'Возможность использования паузы во время игры.', + 'sv_voiceenable' => 'Режим работы голосового чата в игре.', + 'sv_pushaway_force' => 'Сила отталкивания предметов.', + 'sv_turbophysics' => 'Позволяет толкать предметы при нажатии на кнопку "E".', + 'sv_contact' => 'Контакты админа.', + 'sv_rcon_banpenalty' => 'Колличество минут на которое банится игрок пытавшийся подобрать rcon-пароль к серверу.', + 'sv_rcon_maxfailures' => 'Максимальное колличество попыток при наборе rcon-пароля, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailures' => 'Колличество попыток при наборе rcon-пароля во время заданное sv_rcon_minfailuretime, после истечения которых игрок будет забанен.', + 'sv_rcon_minfailuretime' => 'Колличество секунд для определения неверной rcon-аутенфикации.', + 'sv_maxrate' => 'Максимально-допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_maxcmdrate' => 'Максимальное количество пакетов в секунду к серверу.', + 'sv_maxupdaterate' => 'Максимальное количество переданных пакетов в секунду.', + 'sv_minrate' => 'Минимально допустимый предел передачи/приёма байт в секунду между клиентом и сервером.', + 'sv_mincmdrate' => 'Минимальное количество пакетов в секунду к серверу. 0 = Не лимитирован.', + 'sv_minupdaterate' => 'Минимальное количество переданных пакетов в секунду.', + 'net_maxfilesize' => 'Максимальный размер загружаемого файла в MB', + 'phys_timescale' => 'Коэффициент шкалы времени для вычисления "физики" в игре. Если по тарифу тикрейт 100, то нужно выставить значение 1.5' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'sv_password' => '', + 'decalfrequency' => '', + 'mp_allowspectators' => '', + 'mp_autokick' => '', + 'mp_autoteambalance' => '', + 'mp_chattime' => '', + 'mp_decals' => '', + 'mp_fadetoblack' => '', + 'mp_falldamage' => '', + 'mp_flashlight' => '', + 'mp_footsteps' => '', + 'mp_forcecamera' => '', + 'mp_forcerespawn' => '', + 'mp_fraglimit' => '', + 'mp_freezetime' => '', + 'mp_friendlyfire' => '', + 'mp_hostagepenalty' => '', + 'mp_limitteams' => '', + 'mp_maxrounds' => '', + 'mp_playerid' => '', + 'mp_roundtime' => '', + 'mp_spawnprotectiontime' => '', + 'mp_startmoney' => '', + 'mp_timelimit' => '', + 'mp_tkpunish' => '', + 'mp_weaponstay' => '', + 'mp_winlimit' => '', + 'mp_c4timer' => '', + 'mp_buytime' => '', + 'sv_airaccelerate' => '', + 'sv_allowdownload' => '', + 'sv_allowupload' => '', + 'sv_alltalk' => '', + 'sm_deadtalk' => '', + 'sv_consistency' => '', + 'sv_gravity' => '', + 'sv_maxspeed' => '', + 'sv_maxunlag' => '', + 'sv_pausable' => '', + 'sv_voiceenable' => '', + 'sv_pushaway_force' => '', + 'sv_turbophysics' => '', + 'sv_contact' => '', + 'sv_rcon_banpenalty' => '', + 'sv_rcon_maxfailures' => '', + 'sv_rcon_minfailures' => '', + 'sv_rcon_minfailuretime' => '', + 'sv_maxrate' => '', + 'sv_maxcmdrate' => '', + 'sv_maxupdaterate' => '', + 'sv_minrate' => '', + 'sv_mincmdrate' => '', + 'sv_minupdaterate' => '', + 'sv_downloadurl' => '', + 'net_maxfilesize' => '', + 'phys_timescale' => '' + ); +?> \ No newline at end of file diff --git a/system/data/scfg/mc.php b/system/data/scfg/mc.php new file mode 100644 index 0000000..8069232 --- /dev/null +++ b/system/data/scfg/mc.php @@ -0,0 +1,113 @@ + 'Название игрового сервера.', + 'server-name' => 'Название игрового сервера.', + 'level-name' => 'Название карты.', + 'rcon.password' => 'ароль для управления сервером через RCON команды.', + 'enable-rcon' => 'Разрешено управление RCON командами на сервере.', + 'allow-nether' => 'Разрешено игрокам путешествовать в Нижний мир (Nether).', + 'allow-flight' => 'Разрешено игрокам летать в режиме выживания, если установлен мод для полетов.', + 'white-list' => 'Белый список на сервере. Если на сервере включен "белый лист", то на нем могут играть только пользователи записанные в файле white-list.txt.', + 'spawn-animals' => 'Появление животных.', + 'spawn-monsters' => 'Появление монстров.', + 'online-mode' => 'Проверять наличие игрока в базе аккаунтов minecraft. При включении, игроки смогут играть только с лицензионного клиента игры.', + 'pvp' => 'Получение урона игрокам от атак других игроков на сервере. При выключении игроки не смогут наносить прямой урон один другому.', + 'difficulty' => 'Cложность игры на сервере..', + 'gamemode' => 'Режим игры на сервере.', + 'view-distance' => 'Дистанция обзора со стороны сервера. Рекомендуемое значение 10. Если наблюдаются сильные лаги можно уменьшить это значение.', + 'level-seed' => 'Входные данные (сид) для генератора уровня.', + 'level-type' => 'Опция генерации мира. DEFAULT - Стандартный, FLAT - Суперплоскость, LARGEBIOMES - Большие биомы, DAYZ, BIOMESOP.', + 'generate-structures' => 'Генерировать ли структуры (сокровищницы, крепости, деревни...).', + 'max-built-height' => 'Указывает максимальную высоту постройки на сервере.', + 'texture-pack' => 'Для серверов версии ниже 1.7.2. Архив текстур, который сервер предложит загрузить игроку при соединении. В данном поле нужно указать имя zip-архива, находящегося в папке сервера.', + 'resource-pack' => 'Для серверов версии ниже 1.7.2. Архив ресурсов, который сервер предложит загрузить игроку при соединении. В данном поле нужно указать имя zip-архива, находящегося в папке сервера.', + 'enable-command-block' => 'Командный блок.', + 'hardcore' => 'Включает на сервере режим Хардкор. После смерти - бан, переподключиться нельзя.', + 'announce-player-achievements' => 'Отправлять в чат сообщения о получении достижений.', + 'op-permission-level' => 'Позволяет изменять права операторов.' + .'
  • 1 - Операторы могут ломать / ставить блоки внутри радиуса защиты территории спауна.
  • ' + .'
  • 2 - Операторы могут использовать команды /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /tp, и могут изменять командные блоки.
  • ' + .'
  • 3 - Операторы могут использовать команды /ban, /deop, /kick, и /op.
  • ' + .'
  • 4 - Операторы могут использовать команду /stop.
  • ' + ); + + $aScfg_form = array( + 'motd' => '', + 'server-name' => '', + 'level-name' => '', + 'rcon.password' => '', + 'view-distance' => '', + 'level-seed' => '', + 'level-type' => '', + 'texture-pack' => '', + 'resource-pack' => '', + 'enable-rcon' => '', + 'generate-structures' => '', + 'allow-nether' => '', + 'allow-flight' => '', + 'white-list' => '', + 'hardcore' => '', + 'spawn-animals' => '', + 'announce-player-achievements' => '', + 'spawn-monsters' => '', + 'online-mode' => '', + 'pvp' => '', + 'enable-command-block' => '', + 'difficulty' => '', + 'gamemode' => '', + 'max-built-height' => '', + 'op-permission-level' => '' + ); +?> \ No newline at end of file diff --git a/system/data/scfg/samp.php b/system/data/scfg/samp.php new file mode 100644 index 0000000..a00972b --- /dev/null +++ b/system/data/scfg/samp.php @@ -0,0 +1,53 @@ + 'Название игрового сервера.', + 'rcon' => 'Управление RCON командами.', + 'rcon_password' => 'Пароль для упраления сервером через RCON команды.', + 'password' => 'Пароль для входа на сервер.', + 'lanmode' => 'Тип игрового сервера.', + 'gamemode0' => 'Моды на сервере.', + 'filterscripts' => 'Сценарии на сервере.', + 'announce' => 'Отображение сервера в интернете.', + 'weburl' => 'Адрес сайта севера.', + 'maxnpc' => 'Максимальное число NPC подключаемых к серверу.', + 'onfoot_rate' => 'Время в миллисекундах за которое сервер обновляет данные о пешем игроке.', + 'incar_rate' => 'Время в миллисекундах за которое сервер обновляет данные о игроке находящемся в транспорте.', + 'weapon_rate' => 'Время в миллисекундах за которое сервер обновляет данные о стрельбе игрока.', + 'stream_distance' => 'Дистанция для обновления стримера игроков.', + 'stream_rate' => 'Время в миллисекундах за которое сервер обновляет игроков в стримере.', + 'logqueries' => 'Логирование всех запросов.' + ); + + $aScfg_form = array( + 'hostname' => '', + 'rcon_password' => '', + 'password' => '', + 'gamemode0' => '', + 'filterscripts' => '', + 'maxnpc' => '', + 'onfoot_rate' => '', + 'incar_rate' => '', + 'weapon_rate' => '', + 'stream_distance' => '', + 'stream_rate' => '', + 'lagcompmode' => '', + 'rcon' => '', + 'announce' => '', + 'logqueries' => '', + 'lanmode' => '' + ); +?> \ No newline at end of file diff --git a/system/data/text/error.php b/system/data/text/error.php new file mode 100644 index 0000000..1b77176 --- /dev/null +++ b/system/data/text/error.php @@ -0,0 +1,46 @@ + array( + // Если вывод ошибок по группе пользователя + 'admin' => 'Не удалось создать соединение с оборудованием.', + + 'support' => 'Проблемы на линии связи между панелью и оборудованием.', + + 'user' => 'Не удалось выполнить операцию, ошибка #1, обратитесь в тех.поддержку.', + + // Если вывод ошибок не учитывать группу пользователя + 'all' => 'Не удалось создать соединение с оборудованием.' + ), + + 'cpu' => array( + // Если вывод ошибок по группе пользователя + 'admin' => 'Не удается запустить игровой сервер, нет свободного потока.', + + 'support' => 'Не удается запустить игрвоой сервер, нет свободного потока.', + + 'user' => 'Не удалось выполнить операцию, ошибка #с404, обратитесь в тех.поддержку.', + + // Если вывод ошибок не учитывать группу пользователя + 'all' => 'Не удается запустить игровой сервер, нет свободного потока.' + ), + + 'mail' => 'Не удалось отправить сообщение на почту.', + + 'signup' => 'Подача регистрации не найдена.', + + 'recovery' => 'Подача восстановления не найдена.', + + 'ser_stop' => 'Выключение невозможно, сервер должен быть включен.', + 'ser_start' => 'Включение невозможно, сервер должен быть выключен.', + 'ser_restart' => 'Перезагрузка невозможна, сервер должен быть включен.', + 'ser_reinstall' => 'Переустановка невозможна, сервер должен быть выключен.', + 'ser_update' => 'Обновление невозможно, сервер должен быть выключен.', + 'ser_change' => 'Смена карты невозможна, сервер должен быть полностью запущен.', + 'ser_change_go' => 'Не удалось сменить карту.', + 'ser_owner' => 'У вас нет доступа к данной операции.', + 'ser_delete' => 'Удаление невозможно, сервер должен быть выключен.', + ); +?> \ No newline at end of file diff --git a/system/data/text/input.php b/system/data/text/input.php new file mode 100644 index 0000000..534a900 --- /dev/null +++ b/system/data/text/input.php @@ -0,0 +1,31 @@ + 'Необходимо заполнить все поля.', + 'login_valid' => 'Неправильный формат логина.', + 'mail_valid' => 'Неправильный формат почты.', + 'name_valid' => 'Неправильный формат имени.', + 'lastname_valid' => 'Неправильный формат фамилии.', + 'patronymic_valid' => 'Неправильный формат отчества.', + 'contacts_valid' => 'Неправильный формат контактов.
    Пример: vk - https://vk.com/enginegamespanel или skype - enginegamepanel.', + 'passwd_valid' => 'Неправильный формат пароля, используйте латинские буквы и цифры от 4 до 20 символов.', + 'phone_valid' => 'Указанный номер имеет неверный формат, пример: RU - 79260010203, KZ - 77058197322.', + 'wmr_valid' => 'Указанный кошелек имеет неверный формат, пример: R123456789100.', + + 'mail_use' => 'Почта занята другим пользователем.', + 'login_use' => 'Логин занят другим пользователем.', + 'phone_use' => 'Телефон занят другим пользователем.', + 'contacts_use' => 'Контакты заняты другим пользователем.', + + 'auth' => 'Неправильный логин или пароль.', + 'recovery' => 'Пользователь не найден.', + 'word' => 'В сообщении присутствует длинное слово.', + 'similar' => 'Указанные данные совпадают с текущими.', + 'phone_confirm' => 'Изменение подтвержденного номера невозможно.', + 'wmr_confirm' => 'Изменение кошелька невозможно.', + 'phone' => 'Для подтверждения номера, необходимо его указать.', + 'code' => 'Указанный код неправильный.', + ); +?> \ No newline at end of file diff --git a/system/data/text/logs.php b/system/data/text/logs.php new file mode 100644 index 0000000..3797e5e --- /dev/null +++ b/system/data/text/logs.php @@ -0,0 +1,23 @@ + 'Аренда игрового сервера на срок: [days], списана сумма: [money] руб. (сервер: #[id])', + 'buy_control' => 'Аренда услуги \"Контроль\" на срок: [days], списана сумма: [money] руб. (сервер: #[id])', + 'buy_server_promo' => 'Аренда игрового сервера на срок: [days], использование промо-кода: [promo], списана сумма: [money] руб. (сервер: #[id])', + 'buy_server_test' => 'Получение тестового периода для игрового сервера, списана сумма: 0 руб. (сервер: #[id])', + 'extend_server' => 'Продление игрового сервера на срок: [days], списана сумма: [money] руб. (сервер: #[id])', + 'extend_control' => 'Продление подключенного сервера на срок: [days], списана сумма: [money] руб. (контроль: #[id])', + 'extend_server_promo' => 'Продление игрового сервера на срок: [days], использование промо-кода: [promo], списана сумма: [money] руб. (сервер: #[id])', + 'part' => 'Партнерская программа: прибыль [money] руб. от партнера (пользоветль: #[part])', + 'cashback' => 'Вывод средств на [purse], сумма [money] руб.', + 'profit' => 'Продажа привилегии на игровом сервере: прибыль [money] руб. (сервер: #[server])', + 'buy_address' => 'Аренда выделенного адреса, списана сумма: [money] руб. (сервер: #[id])', + 'extend_address' => 'Продление аренды выделенного адреса, списана сумма: [money] руб. (сервер: #[id])', + 'buy_slots' => 'Аренда дополнительных слот: [slots] шт., списана сумма: [money] руб. (сервер: #[id])', + 'buy_boost' => 'Покупка кругов: [circles] шт. на сайте: [site], списана сумма: [money] руб. (сервер: #[id])', + 'buy_plugin' => 'Покупка плагина: [plugin], списана сумма: [money] руб. (сервер: #[id])', + 'ctrl_buy_plugin' => 'Покупка плагина: [plugin], списана сумма: [money] руб. (CTRL сервер: #[id])', + ); +?> \ No newline at end of file diff --git a/system/data/text/mail.php b/system/data/text/mail.php new file mode 100644 index 0000000..fa21199 --- /dev/null +++ b/system/data/text/mail.php @@ -0,0 +1,66 @@ + '
    Здравствуйте, для завершения регистрации ' + .'на сайте: [site], необходимо подтвердить свои действия, ' + .'для этого необходимо перейти по ссылке: подтвердить.' + .'
    ' + .'Если вы не регистрировались на данном сайте, то проигнорируйте данное сообщение.' + .'

    ' + .'С уважением, администрация [site].', + + 'signup_end' => '
    Здравствуйте, вы успешно зарегистрированы ' + .'на сайте: [site], ваши персональные данные: ' + .'

    ' + .'Логин: [login]' + .'
    ' + .'Пароль: [passwd]' + .'

    ' + .'С уважением, администрация [site].', + + 'recovery' => '
    Здравствуйте, для восстановления доступа ' + .'на сайте: [site], необходимо подтвердить свои действия, ' + .'для этого необходимо перейти по ссылке: подтвердить.' + .'
    ' + .'Если вы не производили данную операцию, то проигнорируйте данное сообщение, не беспокойтесь, пароль не будет изменен.' + .'

    ' + .'С уважением, администрация [site].', + + 'change' => '
    Здравствуйте, для смена почты ' + .'на сайте: [site], необходимо подтвердить свои действия, ' + .'для этого необходимо перейти по ссылке: подтвердить.' + .'
    ' + .'Если вы не производили данную операцию, то проигнорируйте данное сообщение, не беспокойтесь, почта не будет изменена.' + .'

    ' + .'С уважением, администрация [site].', + + 'recovery_end' => '
    Здравствуйте, восстановление доступа ' + .'на сайте: [site] успешно завершено.' + .'
    ' + .'Ваш новый пароль: [passwd], теперь вы можете авторизоваться.' + .'

    ' + .'С уважением, администрация [site].', + + 'security_code' => '
    Здравствуйте, для авторизации ' + .'укажите код подверждения: [code]. (код будет доступен 180 секунд.)' + .'
    ' + .'Если авторизацию инициировали не вы, не беспокойтесь, без данного кода авторизация не будет завершена.' + .'

    ' + .'Система защиты по коду [site].', + + 'notice_help' => '
    Здравствуйте, на ваш вопрос был дан ответ, прочитать.' + .'
    ' + .'С уважением, администрация [site].', + + 'notice_help_admin' => '
    Новый тикет в тех. подвержке: прочитать.', + 'notice_help_admin_new' => '
    Новое сообщение в тех. подвержке: прочитать.', + + 'notice_server_overdue' => '
    Здравствуйте, ваш арендованный игровой сервер #[id] ([address]) просрочен,' + .'
    ' + .'через некоторое время он будет удален, во избежание этого, необходимо продлить аренду.' + .'
    ' + .'С уважением, администрация [site].', + ); +?> \ No newline at end of file diff --git a/system/data/text/other.php b/system/data/text/other.php new file mode 100644 index 0000000..2831222 --- /dev/null +++ b/system/data/text/other.php @@ -0,0 +1,9 @@ + 'Пожалуйста, дождитесь выполнения предыдущего запроса.', + 'captcha' => 'Неправильно указан код проверки либо закончился срок его жизни.', + ); +?> \ No newline at end of file diff --git a/system/data/text/output.php b/system/data/text/output.php new file mode 100644 index 0000000..af0e4f6 --- /dev/null +++ b/system/data/text/output.php @@ -0,0 +1,20 @@ + 'На указанную почту отправлено письмо с дальнейшей инструкцией.', + 'remail' => 'На указанную почту повторно отправлено письмо с подтверждением.', + 'signup' => 'Вы успешно зарегистрировались, на вашу почту отправлены логин и пароль для авторизации на сайте.', + 'oldmail' => 'На старую почту отправлено письмо с инструкцией.', + + 'confirm_key_error' => 'Неправильный код подтверждения операции.', + 'confirm_mail_done' => 'Операция смены почты успешно выполнена.', + 'confirm_phone' => 'Ваш номер подтвержден, сменить его нельзя.', + 'confirm_phone_done' => 'Ваш номер уже подтвержден.', + 'confirm_phone_error' => 'Не удалось подтвердить номер.', + + 'auth' => 'Вы уже авторизованы, обновите страницу.', + 'noauth' => 'Необходимо авторизоваться.', + ); +?> \ No newline at end of file diff --git a/system/data/text/servers.php b/system/data/text/servers.php new file mode 100644 index 0000000..50f51f0 --- /dev/null +++ b/system/data/text/servers.php @@ -0,0 +1,14 @@ + 'Игровой сервер выключен.', + 'nomap' => 'Отсутствует стартовая карта: [map].', + 'change' => 'Отсутствует выбранная карта: [map].', + 'reinstall' => 'Повторная переустановка возможна через [time].', + 'update' => 'Повторное обновление возможно через [time].', + 'firewall' => 'Неверный формат адреса.', + 'bans' => 'Неверный формат переданных данных.', + ); +?> \ No newline at end of file diff --git a/system/data/text/syslogs.php b/system/data/text/syslogs.php new file mode 100644 index 0000000..e3bbf85 --- /dev/null +++ b/system/data/text/syslogs.php @@ -0,0 +1,14 @@ + 'Переустановка игрового сервера.', + 'update' => 'Обновление игрового сервера.', + 'recovery' => 'Восстановление игрового сервера.', + + 'change_slots' => 'Изменение количества слот.', + 'change_plan' => 'Изменение тарифного плана.', + 'change_unit' => 'Изменение локации.', + ); +?> \ No newline at end of file diff --git a/system/data/web.php b/system/data/web.php new file mode 100644 index 0000000..6643f82 --- /dev/null +++ b/system/data/web.php @@ -0,0 +1,511 @@ + array( + #'update', + 'passwd', + 'delete', + 'connect' + ), + + 'csstats' => array( + #'update', + 'delete', + 'connect' + ), + + 'bp' => array( + #'update', + 'settings', + 'passwd', + 'delete' + ), + + 'astats' => array( + #'update', + 'delete', + 'connect' + ), + + 'sourcebans' => array( + #'update', + 'passwd', + 'delete', + 'connect' + ), + + 'mysql' => array( + 'install', + 'passwd', + 'delete' + ), + + 'hosting' => array( + 'install', + 'passwd', + 'delete' + ) + ); + + // Бесплатные доп. услуги + $aWeb = array( + 'cs' => array( + 'csbans' => true, + + 'bp' => true, + + 'csstats' => true, + 'astats' => true, + + 'mysql' => true, + 'hosting' => true + ), + + 'cssold' => array( + 'sourcebans' => false, + + 'mysql' => true, + 'hosting' => true + ), + + 'css' => array( + 'sourcebans' => true, + + 'mysql' => true, + 'hosting' => true + ), + + 'csgo' => array( + 'sourcebans' => true, + + 'mysql' => true, + 'hosting' => true + ), + + 'samp' => array( + 'mysql' => true, + 'hosting' => true + ), + + 'crmp' => array( + 'mysql' => true, + 'hosting' => true + ), + + 'mta' => array( + 'mysql' => true, + 'hosting' => true + ), + + 'mc' => array( + 'mysql' => true, + 'hosting' => true + ) + ); + + $aWebOne = array( + 'cs' => array( + 'csbans' => array(), + + 'bp' => array(), + + 'csstats' => array('astats'), + 'astats' => array('csstats'), + + 'mysql' => array(), + 'hosting' => array() + ), + + 'cssold' => array( + 'sourcebans' => array(), + 'mysql' => array(), + 'hosting' => array() + ), + + 'css' => array( + 'sourcebans' => array(), + 'mysql' => array(), + 'hosting' => array() + ), + + 'csgo' => array( + 'sourcebans' => array(), + 'mysql' => array(), + 'hosting' => array() + ), + + 'samp' => array( + 'mysql' => array(), + 'hosting' => array() + ), + + 'mta' => array( + 'mysql' => array(), + 'hosting' => array() + ), + + 'mc' => array( + 'mysql' => array(), + 'hosting' => array() + ) + ); + + $aWebInstall = array( + /* + 'unit' ==> одна услуга на одной локации + + 'user' ==> одна услуга на одного пользователя + + 'server' ==> каждая услуга на каждый игровой сервер + */ + 'system' => array( + 'csbans' => 'server', + 'csstats' => 'server', + 'bp' => 'server', + 'astats' => 'server', + 'sourcebans' => 'server', + 'mysql' => 'server', + 'hosting' => 'server' + ), + + 'cs' => array( + 'csbans' => 'unit', + + 'bp' => 'user', + + 'csstats' => 'server', + 'astats' => 'unit', + + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'cssold' => array( + 'sourcebans' => 'unit', + + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'css' => array( + 'sourcebans' => 'unit', + + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'csgo' => array( + 'sourcebans' => 'unit', + + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'samp' => array( + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'crmp' => array( + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'mta' => array( + 'mysql' => 'server', + 'hosting' => 'user' + ), + + 'mc' => array( + 'mysql' => 'server', + 'hosting' => 'user' + ) + ); + + $aWebname = array( + 'csbans' => 'СS:Bans 1.3', + + 'bp' => 'Buy Privileges', + + 'csstats' => 'CsStats', + 'astats' => 'AStats', + + 'sourcebans' => 'SourceBans', + + 'mysql' => 'MySQL', + 'hosting' => 'WebHosting' + ); + + $aWebDesc = array( + 'csbans' => 'система контроля наказаний игроков на серверах (замена amxbans).', + + 'bp' => 'многофункциональная система продажи привилегий.', + + 'csstats' => 'подробная статистика игроков, для одного сервера.', + 'astats' => 'выводит топ игроков на веб странице.', + + 'sourcebans' => 'система контроля наказаний игроков на серверах.', + + 'mysql' => 'свободная реляционная система управления базами данных.', + 'hosting' => 'услуга для размещения сайта, форума или обычных файлов в сети.' + ); + + $aWebType = array( + 'csbans' => 'bans', + 'sourcebans' => 'bans', + + 'csstats' => 'stats', + 'astats' => 'stats', + + 'bp' => 'other', + 'mysql' => 'other', + 'hosting' => 'other' + ); + + $aWebTypeInfo = array( + 'cs' => array( + 'bans' => 'Системы управления банами', + 'stats' => 'Статистика', + 'other' => 'Прочее' + ), + + 'cssold' => array( + 'bans' => 'Системы управления банами', + 'stats' => 'Статистика', + 'other' => 'Прочее' + ), + + 'css' => array( + 'bans' => 'Системы управления банами', + 'stats' => 'Статистика', + 'other' => 'Прочее' + ), + + 'csgo' => array( + 'bans' => 'Системы управления банами', + 'stats' => 'Статистика', + 'other' => 'Прочее' + ), + + 'samp' => array( + 'other' => 'Прочее' + ), + + 'crmp' => array( + 'other' => 'Прочее' + ), + + 'mta' => array( + 'other' => 'Прочее' + ), + + 'mc' => array( + 'other' => 'Прочее' + ) + ); + + $aWebParam = array( + 'csbans' => array( + 'passwd' => 10, + 'desing' => array( + 'default' => 'Default' + ), + ), + + 'csstats' => array( + 'desing' => array( + 'default' => 'Default' + ), + ), + + 'astats' => array( + 'desing' => array( + 'default' => 'Default' + ), + ), + + 'sourcebans' => array( + 'passwd' => 10, + 'desing' => array( + 'default' => 'Default' + ), + ), + + 'mysql' => array( + 'passwd' => 10, + ), + + 'hosting' => array( + 'passwd' => 10, + ) + ); + + $aWebVHTtype = true; // Разрешен ли всем вирт. хостинг + $aWebVHT = array( // Массив списка tarif_id зависит от значения VHT, если VHT true, то перечисленным id тарифов недоступен вирт. хост или наоборот. + + ); + + $aWebUnit = array( + 'address' => '127.0.0.1:22', // ip:22 web сервера + 'passwd' => 'kgdfgjksad', // пароль ssh root + 'pma' => '127.0.0.1', // Домен || ip без http / pma / index.php и т.д. + 'domains' => array( + 'domain.ru', + ), + 'subdomains' => array( // список поддоменов, которые нельзя создать + 'panel', 'admin' + ), + + 'isp' => array( + 'panel' => 'ip/manager', // https://_ЗНАЧЕНИЕ_ (панель управления вирт. хостинга ISP MANAGER PRO 4) + + 'domain' => array( + 'create' => 'http://IP:1500/?authinfo=root:password&out=json&name=[subdomain].[domain].&sdtype=A&addr=[ip]&prio=&wght=&port=&func=domain.sublist.edit&elid=&plid=[domain]&sok=ok', + 'delete' => 'http://IP:1500/?authinfo=root:password&out=json&func=domain.sublist.delete&elid=[subdomain].+A++[ip]&plid=[domain]&sok=ok', + ), + + 'account' => array( + 'create' => 'http://IP:1500/?authinfo=root:password&out=json&name=[login]&passwd=[passwd]&confirm=[passwd]&owner=root&ip=IP&domain=[domain]&preset=default&email=[mail]&phpmod=on&func=user.edit&elid=&sok=ok', + 'passwd' => 'http://IP:1500/?authinfo=root:password&out=json&name=[login]&passwd=[passwd]&confirm=[passwd]&preset=default&email=[mail]&disklimit=1000&phpmod=on&func=user.edit&elid=[login]&sok=ok', + 'delete' => 'http://IP:1500/?authinfo=root:password&out=json&func=user.delete&elid=[login]&sok=ok', + ), + + 'crontab' => array( + 'bp' => array( + 'install' => 'http://IP:1500/?authinfo=root:password&out=json&min=*&hour=*&mday=*&month=*&wday=*&name=/usr/bin/wget+http://[subdomain].[domain]/cron.php?cron=874319&period=daily&crmin=all&evmin=02&semin=&crhour=all&evhour=02&sehour=&crmday=all&evmday=02&semday=&crmonth=all&evmonth=02&semonth=&crwday=all&evwday=02&sewday=&hideout=on&func=cron.edit&elid=&sok=ok', + 'delete' => 'http://IP:1500/?authinfo=root:password&out=json&elid=[data]&func=cron.delete&sok=ok' + ) + ) + ), + + 'unit' => array( + 'csbans' => 'remote', + 'csstats' => 'remote', + 'astats' => 'remote', + 'sourcebans' => 'remote', + 'mysql' => 'remote' + ), + + 'path' => array( + 'local' => array( + 'csbans' => '/path/web/csbans/', + 'csstats' => '/path/web/csstats/', + 'astats' => '/path/web/astats/', + 'sourcebans' => '/path/web/sourcebans/' + ), + + 'remote' => array( + 'csbans' => '/path/web/csbans/', + 'csstats' => '/path/web/csstats/', + 'astats' => '/path/web/astats/', + 'sourcebans' => '/path/web/sourcebans/' + ), + ), + + 'install' => array( + 'local' => array( + 'csbans' => '/var/www/', + 'csstats' => '/var/www/', + 'astats' => '/var/www/', + 'sourcebans' => '/var/www/' + ), + + 'remote' => array( + 'csbans' => '/var/www/web/', + 'csstats' => '/var/www/web/', + 'astats' => '/var/www/web/', + 'sourcebans' => '/var/www/web/' + ) + ) + ); + + $aWebConnect = array( + 'csbans' => array( + 'cs' => 0 // id плагина + ), + + 'csstats' => array( + 'cs' => 0 + ), + + 'sourcebans' => array( + 'cssold' => 0, + 'css' => 0, + 'csgo' => 0, + ) + ); + + $aWebChmod = array( + 'csbans' => 'chmod 777 assets protected/runtime', + 'csstats' => '', + 'astats' => 'chmod 777 ftpcache', + 'sourcebans' => 'chmod 777 demos themes_c' + ); + + $aWebSQL = array( + 'csbans' => array( + 'install' => array( + "INSERT INTO amx_webadmins set id='1', username='admin', password=MD5('[passwd]'), level='1', email='[mail]'", + ), + + 'connect' => array( + "DELETE FROM amx_serverinfo WHERE address='[address]'", + "INSERT INTO amx_serverinfo set timestamp='[time]', hostname='[name]', rcon='[rcon]', address='[address]', gametype='cstrike', amxban_version='1.6', motd_delay='10', amxban_menu='1'" + ), + + 'passwd' => array( + "UPDATE amx_webadmins set password=MD5('[passwd]') WHERE id='1' LIMIT 1" + ) + ), + + 'sourcebans' => array( + 'install' => array( + "INSERT INTO sb_admins set aid='1', user='admin', authid='', password=SHA1(SHA1('SourceBans[passwd]')), gid='-1', email='[mail]', extraflags='-513'" + ), + + 'connect' => array( + "DELETE FROM sb_servers WHERE ip='[ip]' and port='[port]'", + "INSERT INTO sb_servers set ip='[ip]', port='[port]', rcon='[rcon]', modid='3', enabled='1'" + ), + + 'passwd' => array( + "UPDATE sb_admins set password=SHA1(SHA1('SourceBans[passwd]')) WHERE aid='1' LIMIT 1" + ) + ), + + 'csstats' => array() + ); + + $aWebdbConf = array( + 'csbans' => array( + 'file' => '/include/db.config.inc.php', + 'chmod' => 0644 + ), + + 'csstats' => array( + 'file' => '/include/config.php', + 'chmod' => 0644 + ), + + 'sourcebans' => array( + 'file' => '/config.php', + 'chmod' => 0644 + ) + ); + + $aWebothPath = array( + + ); +?> \ No newline at end of file diff --git a/system/distributor.php b/system/distributor.php new file mode 100644 index 0000000..8fce0c9 --- /dev/null +++ b/system/distributor.php @@ -0,0 +1,185 @@ +get('users_auth'); + + $user = isset($users[$userkey]) ? $users[$userkey] : 0; + + if(!$user) + { + if((!sys::valid($aAuth['login'], 'other', $aValid['login'])) && !sys::valid($aAuth['passwd'], 'md5')) + { + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" LIMIT 1'); + if($sql->num()) + { + $sql->query('SELECT `id`, `login`, `passwd`, `balance`, `group`, `level`, `time` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" LIMIT 1'); + $user = array_merge(array('authkey' => $authkey), $sql->get()); + + $auth = 1; + + sys::users($users, $user, $authkey); + } + } + + if(!$auth) + { + sys::cookie('egp_login', 'quit', -1); + sys::cookie('egp_passwd', 'quit', -1); + sys::cookie('egp_authkeycheck', 'quit', -1); + } + }else{ + $sql->query('SELECT `balance`, `time` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + sys::user($user); + + $auth = 1; + } + } + + // Заголовок + $title = ''; + + // Навигация + $html->nav($cfg['name'], $cfg['http']); + + include(DATA.'header.php'); + + // Подключение файла + if(in_array($route, $aRoute)) + include(ENG.$route.'.php'); + else + include(ENG.'404.php'); + + // Обновление ссылок + if(isset($html->arr['main'])) + { + $html->upd( + array( + '[home]', + '[js]', + '[css]', + '[img]' + ), + + array( + $cfg['http'], + $cfg['http'].'template/js/', + $cfg['http'].'template/css/', + $cfg['http'].'template/images/' + ), + 'main' + ); + } + + // Онлайн игроков (общее количество всех игроков) + //$aop = $mcache->get('all_online_players'); //Если ваш хостинг чувствует себя плохо из за чрезмерной нагрузки от данного модуля, то включите кеширование, раскомментировав этот кусочек кода + if($aop == '') + { + $sql->query('SELECT SUM(`online`) FROM `servers` WHERE `status`="working" OR `status`="change"'); + $sum = $sql->get(); + + $aop = $sum['SUM(`online`)']; + + $mcache->set('all_online_players', $aop, false, 1); + } + + // Заготовка выхлопа + $html->get('all'); + $html->set('title', $title.' | '.$cfg['name']); + $html->set('description', sys::head('description')); + $html->set('keywords', sys::head('keywords')); + $html->set('home', $cfg['http']); + $html->set('js', $cfg['http'].'template/js/'); + $html->set('css', $cfg['http'].'template/css/'); + $html->set('img', $cfg['http'].'template/images/'); + $html->set('aop', $aop); + $html->set('cur', $cfg['currency']); + + // Если авторизован + if($auth) + { + $html->set('login', $user['login']); + $html->set('balance', round($user['balance'], 2)); + $html->set('other_menu', isset($html->arr['vmenu']) ? $html->arr['vmenu'] : ''); + }else + $html->set('other_menu', ''); + + $html->set('nav', isset($html->arr['nav']) ? $html->arr['nav'] : '', true); + $html->set('main', isset($html->arr['main']) ? $html->arr['main'] : '', true); + + $sql->query('SELECT `id`, `login`, `time` FROM `users` ORDER BY `id` ASC'); + $online = ''; + while($staff = $sql->get()) + { + if ($staff['time']+15 > $start_point) { + $online .= $staff['login'].', '; + } + else { + $online .= ''; + } + } + $online .= ''; + $html->set('online_users', $online); + $html->pack('all'); + + // Блоки + if($auth) + { + // Проверка наличия игрового сервера + $servers = $sql->query('(SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" LIMIT 1) UNION (SELECT `id` FROM `owners` WHERE `user`="'.$user['id'].'" LIMIT 1)'); + + if($sql->num()) + $html->unitall('all', 'servers', 1, 1); + else + $html->unitall('all', 'servers', 0, 1); + + // Проверка наличия игрового сервера + $servers = $sql->query('SELECT `id` FROM `control` WHERE `user`="'.$user['id'].'" LIMIT 1'); + + if($sql->num()) + $html->unitall('all', 'control', 1); + else + $html->unitall('all', 'control', 0); + + $html->unitall('all', 'auth', 1, 1); + $html->unitall('all', 'admin', $user['group'] == 'admin', 1); + $html->unitall('all', 'support', $user['group'] == 'support', 1); + }else{ + $html->unitall('all', 'auth', 0, 1); + $html->unitall('all', 'servers', 0, 1); + $html->unitall('all', 'control', 0, 1); + $html->unitall('all', 'admin', 0, 1); + $html->unitall('all', 'support', 0, 1); + } +?> \ No newline at end of file diff --git a/system/engine/404.php b/system/engine/404.php new file mode 100644 index 0000000..316942e --- /dev/null +++ b/system/engine/404.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/system/engine/agreement.php b/system/engine/agreement.php new file mode 100644 index 0000000..1552f0b --- /dev/null +++ b/system/engine/agreement.php @@ -0,0 +1,10 @@ +nav($title); + + $html->get('agreement'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/api.php b/system/engine/api.php new file mode 100644 index 0000000..524c99d --- /dev/null +++ b/system/engine/api.php @@ -0,0 +1,46 @@ + 'ключ не указан')); + $action = isset($url['action']) ? $url['action'] : sys::outjs(array('e' => 'метод не указан')); + + if(sys::valid($key, 'md5')) + sys::outjs(array('e' => 'ключ имеет неправильный формат')); + + $sql->query('SELECT `id`, `server` FROM `api` WHERE `key`="'.$key.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'ключ не найден')); + + $api = $sql->get(); + + $id = $api['server']; + + include(LIB.'games/games.php'); + include(LIB.'api.php'); + + if(in_array($action, array('start', 'restart', 'stop', 'change', 'reinstall', 'update'))) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'сервер не найден')); + + include(SEC.'servers/action.php'); + } + + switch($action) + { + case 'data': + sys::outjs(api::data($id)); + + case 'load': + sys::outjs(api::load($id)); + + case 'console': + $cmd = isset($url['command']) ? $url['command'] : false; + + sys::outjs(api::console($id, $cmd)); + } + + sys::outjs(array('e' => 'Метод не найден')); +?> \ No newline at end of file diff --git a/system/engine/api_v1.php b/system/engine/api_v1.php new file mode 100644 index 0000000..992f9e7 --- /dev/null +++ b/system/engine/api_v1.php @@ -0,0 +1,10 @@ +nav($title); + + $html->get('api'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/autocontrol.php b/system/engine/autocontrol.php new file mode 100644 index 0000000..6991bb3 --- /dev/null +++ b/system/engine/autocontrol.php @@ -0,0 +1,75 @@ +query('SELECT `id` FROM `control` WHERE `address`="'.$uip.'" LIMIT 1'); + if(!$sql->num()) + sys::out($uip); + + $del = false; + $tmp = DATA.'control/egpautounit.sh'; + + break; + + case 'sqlpasswd': + $sql->query('SELECT `id`, `sql_passwd` FROM `control` WHERE `address`="'.$uip.'" LIMIT 1'); + if(!$sql->num()) + include(ENG.'404.php'); + + $unit = $sql->get(); + + if($unit['sql_passwd']) + $tmp = sys::temp($unit['sql_passwd']); + else{ + $passwd = sys::passwd(); + $tmp = sys::temp($passwd); + $sql->query('UPDATE `control` set `sql_passwd`="'.$passwd.'" WHERE `id`="'.$unit['id'].'" LIMIT 1'); + } + + break; + + case 'proftpd_sql': + $sql->query('SELECT `id`, `sql_passwd` FROM `control` WHERE `address`="'.$uip.'" LIMIT 1'); + if(!$sql->num()) + include(ENG.'404.php'); + + $unit = $sql->get(); + + $data = file_get_contents(DATA.'control/proftpd_sql.txt'); + $tmp = sys::temp(str_replace('[passwd]', $unit['sql_passwd'], $data)); + + break; + + case 'proftpd_passwd': + $sql->query('SELECT `id`, `sql_passwd` FROM `control` WHERE `address`="'.$uip.'" LIMIT 1'); + if(!$sql->num()) + include(ENG.'404.php'); + + $unit = $sql->get(); + + $data = file_get_contents(DATA.'control/proftpd_passwd.txt'); + $tmp = sys::temp(str_replace(array('[passwd]', '[passwd_ftp]'), array($unit['sql_passwd'], sys::passwd()), $data)); + + break; + + case 'endinstall': + $sql->query('UPDATE `control` set `status`="reboot" WHERE `address`="'.$uip.'" LIMIT 1'); + + sys::out('ok:'.$uip); + + default: + sys::outfile(DATA.'control/'.$url['action'].'.txt', $url['action']); + } + + sys::outfile($tmp, $url['action'], $del); +?> \ No newline at end of file diff --git a/system/engine/chat.php b/system/engine/chat.php new file mode 100644 index 0000000..877d7b8 --- /dev/null +++ b/system/engine/chat.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/system/engine/check.php b/system/engine/check.php new file mode 100644 index 0000000..8ed19c9 --- /dev/null +++ b/system/engine/check.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/system/engine/contacts.php b/system/engine/contacts.php new file mode 100644 index 0000000..561d4da --- /dev/null +++ b/system/engine/contacts.php @@ -0,0 +1,11 @@ +nav($title); + + $html->get('contacts'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/control.php b/system/engine/control.php new file mode 100644 index 0000000..1606729 --- /dev/null +++ b/system/engine/control.php @@ -0,0 +1,72 @@ +query('SELECT `id`, `user`, `status`, `time` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('SELECT `id`, `user`, `status`, `time` FROM `control` WHERE `id`="'.$id.' AND `user`="'.$user['id'].'" LIMIT 1'); + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'Сервер #'.$id.' не найден')); + + sys::back($cfg['http'].'control'); + } + + $ctrl = $sql->get(); + + if(in_array($ctrl['status'], array('install', 'overdue', 'blocked', 'reboot')) && !in_array($section, array('extend', 'scan'))) + include(SEC.'control/noaccess.php'); + else{ + if(!$section) + $section = 'index'; + + $sid = array_key_exists('server', $url) ? sys::int($url['server']) : false; + + if($sid) + include(SEC.'control/servers/'.$section.'.php'); + else + include(SEC.'control/'.$section.'.php'); + } + }else{ + $html->nav($title); + + $js = ''; + + $ctrls = $sql->query('SELECT `id`, `address`, `passwd`, `time`, `date`, `status` FROM `control` WHERE `user`="'.$user['id'].'"'); + while($ctrl = $sql->get($ctrls)) + { + $time_end = $ctrl['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $ctrl['overdue']+$cfg['control_delete']*86400) : 'Осталось: '.sys::date('min', $ctrl['time']); + $btn = ctrl::buttons($ctrl['id'], $ctrl['status']); + + $html->get('control', 'sections/control'); + $html->set('id', $ctrl['id']); + $html->set('address', $ctrl['address']); + $html->set('passwd', $ctrl['passwd']); + $html->set('time', sys::today($ctrl['time'])); + $html->set('date', sys::today($ctrl['date'])); + $html->set('time_end', $time_end); + $html->set('status', ctrl::status($ctrl['status'])); + $html->set('btn', $btn); + $html->pack('list'); + + $js .= 'update_resources('.$ctrl['id'].', true);'; + } + + $html->get('controls', 'sections/control'); + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : 'У вас нет подключенных серверов', true); + $html->set('updates_control', $js); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/engine/freekassa.php b/system/engine/freekassa.php new file mode 100644 index 0000000..64b5672 --- /dev/null +++ b/system/engine/freekassa.php @@ -0,0 +1,91 @@ +query('SELECT `id`, `server`, `price` FROM `privileges_buy` WHERE `key`="'.$_POST['us_user'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad key'); + + $privilege = $sql->get(); + + $money = round($sum*$cfg['curinrub'], 2); + + if($money < $privilege['price']) + sys::out('bad sum'); + + $sql->query('SELECT `user` FROM `servers` WHERE `id`="'.$privilege['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad server'); + + $server = $sql->get(); + + $sql->query('SELECT `id`, `balance`, `part_money` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad owner'); + + $user = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'profit'), + array('server' => $privilege['server'], 'money' => $money)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$money.'"'); + + $sql->query('UPDATE `privileges_buy` set `status`="1" WHERE `id`="'.$privilege['id'].'" LIMIT 1'); + + sys::out('YES'); + } + + $user = intval($_POST['us_user']); + + $sql->query('SELECT `id`, `balance`, `part` FROM `users` WHERE `id`="'.$user.'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad user'); + + $user = $sql->get(); + + $money = round($user['balance']+$sum*$cfg['curinrub'], 2); + + if($cfg['part']) + { + $part_sum = round($sum/100*$cfg['part_proc'], 2); + + $sql->query('SELECT `balance`, `part_money` FROM `users` WHERE `id`="'.$user['part'].'" LIMIT 1'); + if($sql->num()) + { + $part = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($part['part_money']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($part['balance']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['part'].'", `text`="'.sys::updtext(sys::text('logs', 'part'), + array('part' => $uid, 'money' => $part_sum)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$part_sum.'"'); + } + } + + $sql->query('UPDATE `users` set `balance`="'.$money.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="Пополнение баланса на сумму: '.$sum.' '.$cfg['currency'].'", `date`="'.$start_point.'", `type`="replenish", `money`="'.$sum.'"'); + + sys::out('YES'); +?> \ No newline at end of file diff --git a/system/engine/graph.php b/system/engine/graph.php new file mode 100644 index 0000000..27138c2 --- /dev/null +++ b/system/engine/graph.php @@ -0,0 +1,65 @@ +query('SELECT `id`, `server`, `time` FROM `graph` WHERE `key`="'.$key.'" LIMIT 1'); + + if(!$sql->num()) + exit; + + $graph = $sql->get(); + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + if(isset($url['type'])) + { + include(DATA.'graph.php'); + + include(LIB.'games/graph.php'); + + $style = isset($url['style']) ? $url['style'] : 'default'; + + if(!array_key_exists($style, $aStyle)) + $style = 'default'; + + $type = isset($url['type']) ? $url['type'] : 'first'; + + if(!in_array($type, array('first', 'second'))) + $type = 'first'; + + // Выхлоп кеш баннера + if(file_exists(TEMP.(md5($key.$style.$type)).'.png') AND $graph['time']+300 > $start_point) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($key.$style.$type)).'.png')); + } + + $sql->query('SELECT `address`, `game`, `slots_start`, `online`, `status`, `name`, `map` FROM `servers` WHERE `id`="'.$graph['server'].'" LIMIT 1'); + if(!$sql->num()) + exit; + + $server = $sql->get(); + + $aPoints = graph::online_day($graph['server'], $server['slots_start']); + + // Обновление баннеров + foreach($aStyle as $name => $styles) + { + graph::first($server, $aPoints, $aStyle, $name, $key); + graph::second($server, $aPoints, $aStyle, $name, $key); + } + + // Обновление данных + $sql->query('UPDATE `graph` set `time`="'.$start_point.'" WHERE `id`="'.$graph['id'].'" LIMIT 1'); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($key.$style.$type)).'.png')); + } +?> \ No newline at end of file diff --git a/system/engine/help.php b/system/engine/help.php new file mode 100644 index 0000000..3358145 --- /dev/null +++ b/system/engine/help.php @@ -0,0 +1,34 @@ +query('SELECT `id` FROM `users` WHERE `id`="'.$user['id'].'" AND `help`="0" LIMIT 1'); + if(!$sql->num()) + { + $html->nav('Техническая поддержка'); + + $html->get('noaccess', 'sections/help'); + $html->pack('main'); + }else{ + // Подключение раздела + if(!in_array($section, array('create', 'dialog', 'open', 'close', 'notice', 'upload'))) + include(ENG.'404.php'); + + $aNav = array( + 'help' => 'Техническая поддержка', + 'create' => 'Создание вопроса', + 'dialog' => 'Решение вопроса', + 'open' => 'Список открытых вопросов', + 'close' => 'Список закрытых вопросов' + ); + + $title = isset($aNav[$section]) ? $aNav[$section] : $section; + $html->nav($aNav['help'], $cfg['http'].'help/section/open'); + $html->nav($title); + + include(SEC.'help/'.$section.'.php'); + } +?> \ No newline at end of file diff --git a/system/engine/index.php b/system/engine/index.php new file mode 100644 index 0000000..d05e9a9 --- /dev/null +++ b/system/engine/index.php @@ -0,0 +1,27 @@ +nav($title); + + $sql->query('SELECT `id`, `name`, `text`, `views`, `tags`, `date` FROM `news` ORDER BY `id` DESC LIMIT 3'); + while($news = $sql->get()) + { + $html->get('list', 'sections/news'); + + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['text'])); + $html->set('views', $news['views']); + $html->set('tags', sys::tags($news['tags'])); + $html->set('date', sys::today($news['date'])); + + $html->pack('news'); + } + + $html->get('index'); + + $html->set('news', isset($html->arr['news']) ? $html->arr['news'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/jobs.php b/system/engine/jobs.php new file mode 100644 index 0000000..c491e92 --- /dev/null +++ b/system/engine/jobs.php @@ -0,0 +1,82 @@ +query('SELECT `name` FROM `jobs` WHERE `id`="'.$id.'" AND `status`!="0" LIMIT 1'); + $nav = $sql->get(); + + $html->nav('Вакансии', $cfg['http'].'jobs'); + $html->nav($nav['name']); + + if($id) + { + $sql->query('SELECT * FROM `jobs` WHERE `id`="'.$id.'" AND `status`!="0" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'jobs'); + + $jobs = $sql->get(); + + if($go) + { + $sql->query('SELECT `id` FROM `jobs_app` WHERE `user`="'.$user['id'].'" AND `job`="'.$id.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Вы уже подали заявку, ожидайте, пожалуйста, ответа от Администрации.')); + + if($_POST['contact'] == '') + sys::outjs(array('e' => 'Необходимо указать контакты для связи!')); + + sys::noauth(); + + $sql->query('INSERT INTO `jobs_app` set' + .'`user`="'.$user['id'].'",' + .'`text`="",' + .'`contact`="'.$_POST['contact'].'",' + .'`job`="'.$id.'",' + .'`date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok')); + } + + $sql->query('SELECT `text` FROM `jobs_app` WHERE `user`="'.$user['id'].'" AND `job`="'.$jobs['id'].'" LIMIT 1'); + $text = $sql->get(); + + $html->get('jobs', 'jobs'); + $html->set('id', $jobs['id']); + $html->set('name', $jobs['name']); + $html->set('job', $jobs['job']); + $html->set('desc', $jobs['desc']); + $html->set('date', sys::today($jobs['date'])); + if(sys::strlen($text['text']) > 0) + { + $html->unit('answer', 1, 1); + $html->set('text', $text['text']); + } else { + $html->unit('answer', 0, 1); + $html->set('text', ''); + } + $html->pack('main'); + } else { + $sql->query('SELECT * FROM `jobs` WHERE `status`!="0" ORDER BY `id` ASC'); + while($jobs = $sql->get()) + { + $html->get('list', 'jobs'); + $html->set('id', $jobs['id']); + $html->set('name', $jobs['name']); + $html->set('job', $jobs['job']); + $html->set('desc', $jobs['desc']); + $html->set('date', sys::today($jobs['date'])); + if($id) $html->unit('close', 1, 1); else $html->unit('close', 0, 1); + $html->pack('jobs_list'); + } + } + + $html->get('index', 'jobs'); + if(!$id) + $html->set('jobs', isset($html->arr['jobs_list']) ? $html->arr['jobs_list'] : '
    На данный момент у нас нет свободных вакансий.
    '); + else + $html->set('jobs', ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/megp/auth.php b/system/engine/megp/auth.php new file mode 100644 index 0000000..18b4e57 --- /dev/null +++ b/system/engine/megp/auth.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/system/engine/megp/help.php b/system/engine/megp/help.php new file mode 100644 index 0000000..9294ede --- /dev/null +++ b/system/engine/megp/help.php @@ -0,0 +1,30 @@ +query('SELECT `id` FROM `users` WHERE `id`="'.$user['id'].'" AND `help`="0" LIMIT 1'); + if(!$sql->num()) + { + $html->get('noaccess', 'sections/help'); + $html->pack('main'); + }else{ + // Подключение раздела + if(!in_array($section, array('create', 'dialog', 'open', 'close', 'notice', 'upload'))) + include(ENG.'404.php'); + + $aNav = array( + 'help' => 'Техническая поддержка', + 'create' => 'Создание вопроса', + 'dialog' => 'Решение вопроса', + 'open' => 'Список открытых вопросов', + 'close' => 'Список закрытых вопросов' + ); + + $title = isset($aNav[$section]) ? $aNav[$section] : $section; + + include(SEC.'help/'.$section.'.php'); + } +?> \ No newline at end of file diff --git a/system/engine/megp/index.php b/system/engine/megp/index.php new file mode 100644 index 0000000..4e44c1d --- /dev/null +++ b/system/engine/megp/index.php @@ -0,0 +1,25 @@ +query('SELECT `text`, `date` FROM `logs` WHERE `user`="'.$user['id'].'" ORDER BY `id` DESC LIMIT 5'); + while($aLog = $sql->get($qLog)) + { + $html->get('list', 'logs'); + $html->set('text', $aLog['text']); + $html->set('date', sys::today($aLog['date'], true)); + $html->pack('logs'); + } + + $html->get('index'); + $html->set('ip', $uip); + $html->set('login', $user['login']); + $html->set('balance', round($user['balance'], 2)); + $html->set('cur', $cfg['currency']); + $html->set('logs', isset($html->arr['main']) ? $html->arr['main'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/megp/news.php b/system/engine/megp/news.php new file mode 100644 index 0000000..10cd83a --- /dev/null +++ b/system/engine/megp/news.php @@ -0,0 +1,42 @@ +query('SELECT `id`, `name`, `full_text`, `views`, `tags`, `date` FROM `news` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + include(ENG.'404.php'); + + $news = $sql->get(); + + $title = $news['name']; + + $sql->query('UPDATE `news` set `views`="'.($news['views']+1).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $html->get('news', 'sections/news'); + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['full_text'])); + $html->set('date', sys::today($news['date'])); + $html->pack('main'); + }else{ + $title = 'Последние новости'; + + $sql->query('SELECT `id`, `name`, `text`, `views`, `tags`, `date` FROM `news` ORDER BY `id` DESC LIMIT 5'); + while($news = $sql->get()) + { + $html->get('list', 'sections/news'); + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['text'])); + $html->set('date', sys::today($news['date'])); + $html->pack('news'); + } + + $html->get('index', 'sections/news'); + $html->set('list', isset($html->arr['news']) ? $html->arr['news'] : ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/engine/megp/quit.php b/system/engine/megp/quit.php new file mode 100644 index 0000000..d9f863e --- /dev/null +++ b/system/engine/megp/quit.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/system/engine/megp/recovery.php b/system/engine/megp/recovery.php new file mode 100644 index 0000000..86e8950 --- /dev/null +++ b/system/engine/megp/recovery.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/system/engine/megp/replenish.php b/system/engine/megp/replenish.php new file mode 100644 index 0000000..e3a7645 --- /dev/null +++ b/system/engine/megp/replenish.php @@ -0,0 +1,30 @@ +query('SELECT `text`, `date` FROM `logs` WHERE `user`="'.$user['id'].'" AND `type`="replenish" ORDER BY `id` DESC LIMIT 5'); + while($aLog = $sql->get($qLog)) + { + $html->get('list', 'sections/user/replenish'); + $html->set('text', $aLog['text']); + $html->set('date', sys::today($aLog['date'], true)); + $html->pack('logs'); + } + + $html->get('replenish', 'sections/user'); + $html->set('id', $user['id']); + $html->set('wmr', $cfg['webmoney_wmr']); + $html->set('freekassa', $cfg['freekassa_id']); + $html->set('unitpay', $cfg['unitpay_pubkey']); + $html->set('balance', round($user['balance'], 2)); + $html->set('cur', $cfg['currency']); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/megp/servers.php b/system/engine/megp/servers.php new file mode 100644 index 0000000..739d4e0 --- /dev/null +++ b/system/engine/megp/servers.php @@ -0,0 +1,76 @@ +query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" LIMIT 1'); + $owners = $sql->query('SELECT `id` FROM `owners` WHERE `user`="'.$user['id'].'" LIMIT 1'); + + if(!$sql->num($servers) AND !$sql->num($owners)) + sys::back($cfg['http'].'services'); // Если нет игровых серверов отправить на страницу аренды + } + + if($id AND !$section) + $section = 'index'; + + $title = 'Управление игровыми серверами'; + + // Подключение раздела + if(in_array($section, array('action', 'scan', 'index', 'console', 'settings', 'tarif', 'boost'))) + { + if(!$id) + sys::back($cfg['http'].'servers'); + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'servers'); + + $owner = $sql->get(); + + $rights = sys::b64djs($owner['rights']); + + if($section == 'action') + { + if(!isset($rights[$url['action']]) || !$rights[$url['action']]) + sys::outjs(array('e' => sys::text('error', 'ser_owner'))); + }else{ + if(!in_array($section, array('index', 'scan')) AND (!isset($rights[$section]) || !$rights[$section])) + sys::back($cfg['http'].'servers/id/'.$owner['server']); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers'); // Если нет игрового сервера отправить на страницу списка + + $file_section = file_exists(SEC.'megp/servers/'.$section.'.php'); + if($file_section) + include(SEC.'megp/servers/'.$section.'.php'); + else + sys::back($cfg['http'].'servers/id/'.$id); + + }else{ + if($user['group'] == 'user' AND $mcache->get('servers_'.$user['id']) != '') + $html->arr['main'] = $mcache->get('servers_'.$user['id']); + else{ + include(SEC.'megp/servers/list.php'); + include(SEC.'megp/servers/owners_list.php'); + + $html->get('servers', 'sections/servers'); + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : 'У вас нет игровых серверов', true); + $html->set('wait_servers', $wait_servers); + $html->set('updates_servers', $updates_servers); + $html->pack('main'); + + $mcache->set('servers_'.$user['id'], $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/engine/monitoring.php b/system/engine/monitoring.php new file mode 100644 index 0000000..1314609 --- /dev/null +++ b/system/engine/monitoring.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/system/engine/pages.php b/system/engine/pages.php new file mode 100644 index 0000000..d95f8e0 --- /dev/null +++ b/system/engine/pages.php @@ -0,0 +1,24 @@ +query('SELECT `name`, `file` FROM `pages` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + include(ENG.'404.php'); + + $page = $sql->get(); + + $title = $page['name']; + + $html->nav($page['name']); + + $html->get('page'); + + $html->set('content', file_get_contents(FILES.'pages/'.$page['file'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/partners.php b/system/engine/partners.php new file mode 100644 index 0000000..5211206 --- /dev/null +++ b/system/engine/partners.php @@ -0,0 +1,10 @@ +nav($title); + + $html->get('partners'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/engine/pluginbuy.php b/system/engine/pluginbuy.php new file mode 100644 index 0000000..a49d1d6 --- /dev/null +++ b/system/engine/pluginbuy.php @@ -0,0 +1,27 @@ +query('SELECT `id` FROM `servers` WHERE `address`="'.$address.'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad server'); + + $server = $sql->get(); + + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `key`="'.$url['plugin'].'" AND `server`="'.$server['id'].'" LIMIT 1'); + if($sql->num()) + sys::out('true'); + + sys::out('false'); +?> \ No newline at end of file diff --git a/system/engine/plugins.php b/system/engine/plugins.php new file mode 100644 index 0000000..db45750 --- /dev/null +++ b/system/engine/plugins.php @@ -0,0 +1,171 @@ + 'Counter-Strike: 1.6', + 'cssold' => 'Counter-Strike: Source v34', + 'css' => 'Counter-Strike: Source', + 'csgo' => 'Counter-Strike: Global Offensive' + ); + + if(!isset($url['game']) || !array_key_exists($url['game'], $aGame)) + $url['game'] = 'cs'; + + $title = 'Доступные плагины для установки'; + + include(LIB.'games/plugins.php'); + + if($id) + { + $sql->query('SELECT `upd` FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'plugins/game/'.$url['game']); + + $update = $sql->get(); + + $sqlq = '`name`, `info`, `desc`, `images`, `upd`'; + + // Если установленно обновление + if($update['upd']) + { + $sql->query('SELECT '.$sqlq.' FROM `plugins_update` WHERE `id`="'.$update['upd'].'" LIMIT 1'); + + if(!$sql->num()) + $sql->query('SELECT '.$sqlq.' FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + }else + $sql->query('SELECT '.$sqlq.' FROM `plugins` WHERE `id`="'.$id.'" LIMIT 1'); + + $plugin = $sql->get(); + + $sql->query('SELECT `id`, `file` FROM `plugins_config` WHERE (`plugin`="'.$id.'" AND `update`="0") OR (`plugin`="'.$id.'" AND `update`="'.$update['upd'].'") ORDER BY `sort`, `id` ASC'); + while($config = $sql->get()) + { + // Исключить дублирование, путем проверки массива файлов + if(in_array($config['file'], $aConf)) + continue; + + $aConf[] = $config['file']; + + // Данные файла + $file = explode('/', $config['file']); + + $html->get('config_list', 'sections/plugins'); + + $html->set('game', $url['game']); + $html->set('fid', $config['id']); + $html->set('name', end($file)); + $html->set('file', $config['file']); + + $html->pack('configs'); + } + + $images = plugins::images($plugin['images'], $pid); + + $html->get('configs', 'sections/plugins'); + + $html->set('game', $url['game']); + $html->set('name', $plugin['name']); + $html->set('info', htmlspecialchars_decode($plugin['info'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + // Картинки + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + // Редактируемые файлы + if(isset($html->arr['configs'])) + { + $html->set('configs', $html->arr['configs']); + $html->unit('configs', 1); + }else + $html->unit('configs'); + + $html->pack('main'); + + $plugin['name'] = strip_tags($plugin['name']); + + $title = $plugin['name']; + $html->nav('Доступные плагины для установки', $cfg['http'].'plugins/game/'.$url['game']); + $html->nav($plugin['name']); + } + + if(!isset($html->arr['main'])) + { + $html->nav('Доступные плагины для установки'); + + // Если есть кеш + if($mcache->get('plugins_list_view_'.$url['game']) != '') + $html->arr['main'] = $mcache->get('plugins_list_view_'.$url['game']); + else{ + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$url['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + $images = plugins::images($plugin['images'], $plugin['id']); + + // Шаблон плагина + $html->get('plugin', 'sections/plugins'); + + $html->set('plugin', $plugin['id']); + $html->set('game', $url['game']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + $html->get('plugins', 'sections/plugins'); + + $html->set('game', $aGame[$url['game']]); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + + $html->pack('main'); + + $mcache->set('plugins_list_view_'.$url['game'], $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/engine/replenish.php b/system/engine/replenish.php new file mode 100644 index 0000000..3970cd3 --- /dev/null +++ b/system/engine/replenish.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/system/engine/servers.php b/system/engine/servers.php new file mode 100644 index 0000000..0afc822 --- /dev/null +++ b/system/engine/servers.php @@ -0,0 +1,113 @@ +query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" LIMIT 1'); + $owners = $sql->query('SELECT `id` FROM `owners` WHERE `user`="'.$user['id'].'" LIMIT 1'); + + if(!$sql->num($servers) AND !$sql->num($owners)) + sys::back($cfg['http'].'services'); // Если нет игровых серверов отправить на страницу аренды + } + + if($id AND !$section) + $section = 'index'; + + $title = 'Управление игровыми серверами'; + + // Подключение раздела + if(in_array($section, array('action', 'scan', 'index', 'console', 'settings', 'plugins', 'maps', 'owners', 'filetp', 'tarif', 'copy', 'graph', 'web', 'boost', 'rcon'))) + { + if(!$id) + sys::back($cfg['http'].'servers'); + + if($user['group'] == 'admin' || ($user['group'] == 'support' AND $user['level'])) + { + if($user['group'] == 'support' AND $user['level'] < 2) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `id` FROM `help` WHERE `type`="server" AND `service`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'servers'); + + $owner = $sql->get(); + + $rights = sys::b64djs($owner['rights']); + + if($section == 'action') + { + if(!isset($rights[$url['action']]) || !$rights[$url['action']]) + sys::outjs(array('e' => 'У вас нет доступа к данному серверу')); + }else{ + if(!in_array($section, array('index', 'scan')) AND (!isset($rights[$section]) || !$rights[$section])) + sys::back($cfg['http'].'servers'); + } + } + } + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + }else{ + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'servers'); + + $owner = $sql->get(); + + $rights = sys::b64djs($owner['rights']); + + if($section == 'action') + { + if(!isset($rights[$url['action']]) || !$rights[$url['action']]) + sys::outjs(array('e' => sys::text('error', 'ser_owner'))); + }else{ + if(!in_array($section, array('index', 'scan')) AND (!isset($rights[$section]) || !$rights[$section])) + sys::back($cfg['http'].'servers/id/'.$owner['server']); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + } + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers'); // Если нет игрового сервера отправить на страницу списка + + $html->nav($title, $cfg['http'].'servers'); + + $file_section = file_exists(SEC.'servers/'.$section.'.php'); + if($file_section) + include(SEC.'servers/'.$section.'.php'); + else + sys::back($cfg['http'].'servers/id/'.$id); + + }else{ + $html->nav($title); + + if($user['group'] == 'user' AND $mcache->get('servers_'.$user['id']) != '') + $html->arr['main'] = $mcache->get('servers_'.$user['id']); + else{ + include(SEC.'servers/list.php'); + include(SEC.'servers/owners_list.php'); + + $html->get('servers', 'sections/servers'); + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : 'У вас нет игровых серверов', true); + $html->set('wait_servers', $wait_servers); + $html->set('updates_servers', $updates_servers); + $html->pack('main'); + + $mcache->set('servers_'.$user['id'], $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/engine/services.php b/system/engine/services.php new file mode 100644 index 0000000..ece74c0 --- /dev/null +++ b/system/engine/services.php @@ -0,0 +1,35 @@ +nav($title); + + $html->get('index', 'sections/services'); + $html->pack('main'); + }else{ + $aNav = array( + 'cs' => 'Counter-Srike: 1.6', + 'css' => 'Counter-Srike: Source', + 'csgo' => 'Counter-Srike: Global Offensive', + 'cssold' => 'Counter-Srike: Source v34', + 'mc' => 'MineCraft', + 'mta' => 'GTA: MTA', + 'samp' => 'GTA: SA-MP', + 'crmp' => 'GTA: CR-MP', + 'hosting' => 'виртуального хостинга', + 'privileges' => 'привилегий на игровом сервере', + 'control' => 'услуги "контроль"', + ); + + $title = 'Аренда '.$aNav[$section]; + + $html->nav('Список услуг', $cfg['http'].'services'); + $html->nav($title); + + include(SEC.'services/'.$section.'.php'); + } +?> \ No newline at end of file diff --git a/system/engine/unitpay.php b/system/engine/unitpay.php new file mode 100644 index 0000000..c608146 --- /dev/null +++ b/system/engine/unitpay.php @@ -0,0 +1,130 @@ + array('message' => 'Некорректный адрес сервера'))); + + $secretKey = $cfg['unitpay_key']; + $params = $_GET['params']; + + if($params['signature'] != getSignature($_GET['method'], $params, $secretKey)) + sys::outjs(array('error' => array('message' => 'Некорректная цифровая подпись'))); + + if(!in_array($_GET['method'], array('pay', 'check', 'error'))) + sys::outjs(array('error' => array('message' => 'Некорректный метод'))); + + // Оплата по ключу + if(!sys::valid($params['account'], 'md5')) + { + $sql->query('SELECT `id`, `server`, `price` FROM `privileges_buy` WHERE `key`="'.$params['account'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad key: '.$params['account']))); + + $privilege = $sql->get(); + + $money = round($params['sum']*$cfg['curinrub'], 2); + + if($money < $privilege['price']) + sys::outjs(array('error' => array('message' => 'bad sum'))); + + $sql->query('SELECT `user` FROM `servers` WHERE `id`="'.$privilege['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad server'))); + + $server = $sql->get(); + + $sql->query('SELECT `id`, `balance`, `part_money` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad owner'))); + + if(isset($_GET['method']) AND $_GET['method'] == 'check') + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + $user = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'profit'), + array('server' => $privilege['server'], 'money' => $money)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$money.'"'); + + $sql->query('UPDATE `privileges_buy` set `status`="1" WHERE `id`="'.$privilege['id'].'" LIMIT 1'); + + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + } + + switch($_GET['method']) + { + case 'pay': + $sum = round($params['sum'], 2); + + $user = intval($params['account']); + + $sql->query('SELECT `id`, `balance`, `part` FROM `users` WHERE `id`="'.$user.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('result' => array('message' => 'Пользователь c ID: '.$user.' не найден'))); + + $user = $sql->get(); + + $money = round($user['balance']+$sum*$cfg['curinrub'], 2); + + if($cfg['part']) + { + $part_sum = round($sum/100*$cfg['part_proc'], 2); + + $sql->query('SELECT `balance`, `part_money` FROM `users` WHERE `id`="'.$user['part'].'" LIMIT 1'); + if($sql->num()) + { + $part = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($part['part_money']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($part['balance']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['part'].'", `text`="'.sys::updtext(sys::text('logs', 'part'), + array('part' => $uid, 'money' => $part_sum)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$part_sum.'"'); + } + } + + $sql->query('UPDATE `users` set `balance`="'.$money.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="Пополнение баланса на сумму: '.$sum.' '.$cfg['currency'].'", `date`="'.$start_point.'", `type`="replenish", `money`="'.$sum.'"'); + + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + case 'check': + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.intval($params['account']).'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + sys::outjs(array('jsonrpc' => "2.0", 'error' => array('code' => -32000, 'message' => 'Пользователь не найден'), 'id' => 1)); + + case 'error': + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + } +?> \ No newline at end of file diff --git a/system/engine/unitpay_entity.php b/system/engine/unitpay_entity.php new file mode 100644 index 0000000..dd779be --- /dev/null +++ b/system/engine/unitpay_entity.php @@ -0,0 +1,120 @@ + array('message' => 'Некорректный адрес сервера'))); + + $secretKey = $cfg['unitpay_key']; + $params = $_GET['params']; + + if ($params['signature'] != getSha256SignatureByMethodAndParams( + $_REQUEST["method"], $params, $GATEWAY['SecretKey'] + )); + + if(!in_array($_GET['method'], array('pay', 'check', 'error'))) + sys::outjs(array('error' => array('message' => 'Некорректный метод'))); + + // Оплата по ключу + if(!sys::valid($params['account'], 'md5')) + { + $sql->query('SELECT `id`, `server`, `price` FROM `privileges_buy` WHERE `key`="'.$params['account'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad key: '.$params['account']))); + + $privilege = $sql->get(); + + $money = round($params['sum']*$cfg['curinrub'], 2); + + if($money < $privilege['price']) + sys::outjs(array('error' => array('message' => 'bad sum'))); + + $sql->query('SELECT `user` FROM `servers` WHERE `id`="'.$privilege['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad server'))); + + $server = $sql->get(); + + $sql->query('SELECT `id`, `balance`, `part_money` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('error' => array('message' => 'bad owner'))); + + if(isset($_GET['method']) AND $_GET['method'] == 'check') + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + $user = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'profit'), + array('server' => $privilege['server'], 'money' => $money)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$money.'"'); + + $sql->query('UPDATE `privileges_buy` set `status`="1" WHERE `id`="'.$privilege['id'].'" LIMIT 1'); + + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + } + + switch($_GET['method']) + { + case 'pay': + $sum = round($params['sum'], 2); + + $user = intval($params['account']); + + $sql->query('SELECT `id`, `balance`, `part` FROM `users` WHERE `id`="'.$user.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('result' => array('message' => 'Пользователь c ID: '.$user.' не найден'))); + + $user = $sql->get(); + + $money = round($user['balance']+$sum*$cfg['curinrub'], 2); + + if($cfg['part']) + { + $part_sum = round($sum/100*$cfg['part_proc'], 2); + + $sql->query('SELECT `balance`, `part_money` FROM `users` WHERE `id`="'.$user['part'].'" LIMIT 1'); + if($sql->num()) + { + $part = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($part['part_money']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($part['balance']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['part'].'", `text`="'.sys::updtext(sys::text('logs', 'part'), + array('part' => $uid, 'money' => $part_sum)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$part_sum.'"'); + } + } + + $sql->query('UPDATE `users` set `balance`="'.$money.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="Пополнение баланса на сумму: '.$sum.' '.$cfg['currency'].'", `date`="'.$start_point.'", `type`="replenish", `money`="'.$sum.'"'); + + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + case 'check': + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.intval($params['account']).'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + + sys::outjs(array('jsonrpc' => "2.0", 'error' => array('code' => -32000, 'message' => 'Пользователь не найден'), 'id' => 1)); + + case 'error': + sys::outjs(array('result' => array('message' => 'Запрос успешно обработан'))); + } +?> \ No newline at end of file diff --git a/system/engine/user.php b/system/engine/user.php new file mode 100644 index 0000000..21851f8 --- /dev/null +++ b/system/engine/user.php @@ -0,0 +1,26 @@ + 'Авторизация', + 'recovery' => 'Восстановление', + 'replenish' => 'Пополнение баланса', + 'signup' => 'Регистрация', + 'lk' => 'Личный кабинет', + 'quit' => 'Выход' + ); + + $title = $aTitle[$section]; + + if($section == 'lk') + $html->nav($title, $cfg['http'].'user/section/lk'); + else + $html->nav($title); + + include(SEC.'user/'.$section.'.php'); +?> diff --git a/system/engine/webmoney.php b/system/engine/webmoney.php new file mode 100644 index 0000000..ed15de4 --- /dev/null +++ b/system/engine/webmoney.php @@ -0,0 +1,97 @@ +query('SELECT `id`, `server`, `price` FROM `privileges_buy` WHERE `key`="'.$_POST['us_user'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad key'); + + $privilege = $sql->get(); + + $money = round($sum*$cfg['curinrub'], 2); + + if($money < $privilege['price']) + sys::out('bad sum'); + + $sql->query('SELECT `user` FROM `servers` WHERE `id`="'.$privilege['server'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad server'); + + $server = $sql->get(); + + $sql->query('SELECT `id`, `balance`, `part_money` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad owner'); + + $user = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$money).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'profit'), + array('server' => $privilege['server'], 'money' => $money)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$money.'"'); + + $sql->query('UPDATE `privileges_buy` set `status`="1" WHERE `id`="'.$privilege['id'].'" LIMIT 1'); + + sys::out('success'); + } + + $user = intval($_POST['us_user']); + + $sql->query('SELECT `id`, `balance`, `part` FROM `users` WHERE `id`="'.$user.'" LIMIT 1'); + if(!$sql->num()) + sys::out('bad user'); + + $user = $sql->get(); + + $money = round($user['balance']+$sum*$cfg['curinrub'], 2); + + if($cfg['part']) + { + $part_sum = round($sum/100*$cfg['part_proc'], 2); + + $sql->query('SELECT `balance`, `part_money` FROM `users` WHERE `id`="'.$user['part'].'" LIMIT 1'); + if($sql->num()) + { + $part = $sql->get(); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($part['part_money']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($part['balance']+$part_sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['part'].'", `text`="'.sys::updtext(sys::text('logs', 'part'), + array('part' => $uid, 'money' => $part_sum)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$part_sum.'"'); + } + } + + $sql->query('UPDATE `users` set `balance`="'.$money.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="Пополнение баланса на сумму: '.$sum.' '.$cfg['currency'].'", `date`="'.$start_point.'", `type`="replenish", `money`="'.$sum.'"'); + + sys::out('success'); +?> \ No newline at end of file diff --git a/system/engine/wiki.php b/system/engine/wiki.php new file mode 100644 index 0000000..33b1205 --- /dev/null +++ b/system/engine/wiki.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/system/library/acpsystem.php b/system/library/acpsystem.php new file mode 100644 index 0000000..9ebbfd7 --- /dev/null +++ b/system/library/acpsystem.php @@ -0,0 +1,713 @@ +delete($cache); + + die(json_encode($val)); + } + + public static function out($val = '', $cache = false) + { + global $mcache; + + if($cache) + $mcache->delete($cache); + + die(''.$val.''); + } + + public static function valid($val, $type, $preg = '') + { + switch($type) + { + case 'promo': + if(!preg_match("/^[A-Za-z0-9]{2,20}$/", $val)) + return true; + + return false; + + case 'en': + if(!preg_match("/^[A-Za-z0-9]$/", $val)) + return true; + + return false; + + case 'ru': + if(!preg_match("/^[А-Яа-я]$/u", $val)) + return true; + + return false; + + case 'wm': + if(!preg_match('/^R[0-9]{12,12}$|^Z[0-9]{12,12}$|^U[0-9]{12,12}$/m', $val)) + return true; + + return false; + + case 'ip': + if(!preg_match("/^(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}$/", $val)) + return true; + + return false; + + case 'steamid': + if(!preg_match("/^STEAM_[0-9]:[0-9]:[0-9]{6,12}$|^HLTV$|^STEAM_ID_LAN$|^STEAM_ID_PENDING$|^VALVE_ID_LAN$|^VALVE_ID_PENDING$|^STEAM_666:88:666$/", $val)) + return true; + + return false; + + case 'steamid3': + if(!preg_match("/^\[U:[01]:[0-9]{3,12}\]$/i", $val)) + return true; + + return false; + + case 'num': + if(!preg_match('/[^0-9]/', $val)) + return true; + + return false; + + case 'md5': + if(!preg_match("/^[a-z0-9]{32,32}$/", $val)) + return true; + + return false; + + case 'other': + if(!preg_match($preg, $val)) + return true; + + return false; + } + + return true; + } + + public static function page($page, $nums, $num) + { + $ceil = ceil($nums/$num); + + if($page > $ceil) + $page = $ceil; + + $next = $page*$num; + + if($next <= $nums) + $next = $next-$num; + + if($next > $nums) + $next = $next-$num; + + if($next < 1) + $next = 0; + + $num_go = $next; + if($page == '') + $page = 1; + + $aPage = array( + 'page' => $page, + 'num' => $num_go, + 'ceil' => $ceil + ); + + return $aPage; + } + + public static function page_list($countnum, $actnum) + { + if($countnum == 0 || $countnum == 1) + return array(); + + if($countnum > 10) + { + if($actnum <= 4 || $actnum + 3 >= $countnum) + { + for($i = 0; $i <= 4; $i++) + $numlist[$i] = $i + 1; + + $numlist[5] = '...'; + for($j = 6, $k = 4; $j <= 10; $j+=1, $k-=1) + $numlist[$j] = $countnum - $k; + }else{ + $numlist[0] = 1; + $numlist[1] = 2; + $numlist[2] = '...'; + $numlist[3] = $actnum - 2; + $numlist[4] = $actnum - 1; + $numlist[5] = $actnum; + $numlist[6] = $actnum + 1; + $numlist[7] = $actnum + 2; + $numlist[8] = '...'; + $numlist[9] = $countnum - 1; + $numlist[10] = $countnum; + } + }else + for($n = 0; $n < $countnum; $n+=1) + $numlist[$n] = $n + 1; + + return $numlist; + } + + public static function page_gen($ceil, $page, $actnum, $section) + { + global $cfg, $html; + + $aNum = sys::page_list($ceil, $actnum); + + $pages = ''; + + $html->get('pages'); + + if($ceil) + { + if($page != 1) + { + $next = $page-1; + $pages .= ''; + } + + foreach($aNum as $v) + { + if($v != $page && $v != '...') + $pages .= ''.$v.''; + + if($v == $page) + $pages .= ''.$v.''; + + if($v == '...') + $pages .= '...'; + } + + if($ceil > $page) + { + if($page < $ceil) + { + $next = $page+1; + $pages .= ''; + }else + $pages .= ''; + } + } + + $html->set('pages', $pages); + + $html->pack('pages'); + + return NULL; + } + + public static function ago($time, $brackets = false) + { + global $start_point; + + $diff = $start_point-$time; + + if($diff < 0) + return ''; + + if(!$diff) + $diff = 1; + + $seconds = array('секунду', 'секунды', 'секунд'); + $minutes = array('минуту', 'минуты', 'минут'); + $hours = array('час', 'часа', 'часов'); + $days = array('день', 'дня', 'дней'); + $weeks = array('неделю', 'недели', 'недель'); + $months = array('месяц', 'месяца', 'месяцев'); + $years = array('год', 'года', 'лет'); + + $phrase = array($seconds, $minutes, $hours, $days, $weeks, $months, $years); + $length = array(1, 60, 3600, 86400, 604800, 2630880, 31570560); + + for($i = 6; ($i >= 0) AND (($no = $diff/$length[$i]) <= 1); $i-=1); + + if($i < 0) + $i = 0; + + $_time = $start_point-($diff % $length[$i]); + $no = ceil($no); + + if($brackets) + return '('.$no.' '.sys::parse_ago($no, $phrase[$i]).' назад)'; + + return $no.' '.sys::parse_ago($no, $phrase[$i]).' назад'; + } + + private static function parse_ago($number, $titles) + { + $cases = array(2, 0, 1, 1, 1, 2); + + return $titles[($number % 100 > 4 AND $number % 100 < 20 ) ? 2 : $cases[min($number % 10, 5)]]; + } + + public static function date($lenght, $date) + { + global $start_point; + + $check_time = $date-$start_point; + + if($check_time < 1) + return 'время истекло.'; + + $days = floor($check_time/86400); + $hours = floor(($check_time%86400)/3600); + $minutes = floor(($check_time%3600)/60); + $seconds = $check_time%60; + + $adata = array( + 'min' => array( + 'days' => array('день', 'дня', 'дней'), + 'hours' => array('ч.', 'ч.', 'ч.'), + 'minutes' => array('мин.', 'мин.', 'мин.'), + 'seconds' => array('сек.', 'сек.', 'сек.') + ), + 'max' => array( + 'days' => array('день', 'дня', 'дней'), + 'hours' => array('час', 'часа', 'часов'), + 'minutes' => array('минуту','минуты','минут'), + 'seconds' => array('секунду','секунды','секунд') + ) + ); + + $text = ''; + + if($days > 0) + $text .= sys::date_decl($days, $adata[$lenght]['days']); + + if($days < 1 AND $hours > 0) + $text .= ' '.sys::date_decl($hours, $adata[$lenght]['hours']); + + if($days < 1 AND $minutes > 0) + $text .= ' '.sys::date_decl($minutes, $adata[$lenght]['minutes']); + + if($days < 1 AND $seconds > 0) + $text .= ' '.sys::date_decl($seconds, $adata[$lenght]['seconds']); + + return $text; + } + + public static function date_decl($digit, $expr, $onlyword = false) + { + if(!is_array($expr)) + $expr = array_filter(explode(' ', $expr)); + + if(empty($expr[2])) + $expr[2] = $expr[1]; + + $i = sys::int($digit)%100; + + if($onlyword) + $digit = ''; + + if($i > 4 AND $i < 21) + $res = $digit.' '.$expr[2]; + else + $i%=10; + + if($i == 1) + $res = $digit.' '.$expr[0]; + elseif($i > 1 AND $i < 5) + $res = $digit.' '.$expr[1]; + else + $res = $digit.' '.$expr[2]; + + return trim($res); + } + + public static function today($time, $cp = false) + { + global $start_point; + + $today = date('d.m.Y', $start_point); + $day = date('d.m.Y', $time); + + if($day == $today) + { + if($cp) + return 'Сегодня '.date('H:i', $time); + + return 'Сегодня '.date('- H:i', $time); + } + + $yesterday_first = sys::int(sys::first(explode('.', $today)))-1; + $yesterday_full = date('m.Y', $time); + + if($day == $yesterday_first.'.'.$yesterday_full AND !$yesterday_first) + { + if($cp) + return 'Вчера '.date('H:i', $time); + + return 'Вчера '.date('- H:i', $time); + } + + if($cp) + return date('d.m.Y H:i', $time); + + return date('d.m.Y - H:i', $time); + } + + public static function browser($agent) + { + if(strpos($agent, 'Firefox') !== false) + return 'Mozilla Firefox'; + + if(strpos($agent, 'Opera') !== false) + return 'Opera'; + + if(strpos($agent, 'Chrome') !== false) + return 'Google Chrome'; + + if(strpos($agent, 'MSIE') !== false) + return 'Internet Explorer'; + + if(strpos($agent, 'Safari') !== false) + return 'Safari'; + + return 'Неизвестный'; + } + + public static function whois($ip) + { + $stack = fsockopen('whois.ripe.net', 43, $errno, $errstr); + + if(!$stack) + return 'не определена'; + + fputs($stack, $ip."\r\n"); + + $subnetwork = ''; + + while(!feof($stack)) + { + $str = fgets($stack, 128); + + if(strpos($str, 'route:') !== FALSE) + { + $subnetwork = trim(str_replace('route:', '', $str)); + + break; + } + } + + fclose($stack); + + return isset($subnetwork{0}) ? $subnetwork : 'не определена'; + } + + public static function uptime_load($time) + { + $uptime = ''; + + $day = floor($time/60/60/24); + if($day) + $uptime .= $day.'д. '; + + $hour = $time/60/60%24; + if($hour) + $uptime .= $hour.'ч. '; + + $min = $time/60%60; + if($min) + $uptime .= $min.'м. '; + + return $uptime.($time%60).'с.'; + } + + public static function ram_load($data) + { + $aData = explode(' ', $data); + + return ceil(($aData[0]-($aData[1]+$aData[2]+$aData[3]))*100/$aData[0]); + } + + public static function cpu_load($data) + { + $aData = explode(' ', $data); + + $load = ceil($aData[0]/$aData[1]); + + return $load > 100 ? 100 : $load; + } + + public static function cpu_idle($pros_stat = array(), $fcpu = false) + { + return sys::cpu_get_idle(sys::parse_cpu($pros_stat[0]), sys::parse_cpu($pros_stat[1]), $fcpu); + } + + public static function cpu_get_idle($first, $second, $fcpu) + { + if(count($first) !== count($second)) + return; + + $cpus = array(); + + for($i = 0, $l = count($first); $i < $l; $i+=1) + { + $dif = array(); + $dif['use'] = $second[$i]['use']-$first[$i]['use']; + $dif['nice'] = $second[$i]['nice']-$first[$i]['nice']; + $dif['sys'] = $second[$i]['sys']-$first[$i]['sys']; + $dif['idle'] = $second[$i]['idle']-$first[$i]['idle']; + $total = array_sum($dif); + $cpu = array(); + + foreach($dif as $x => $y) + $cpu[$x] = $y ? round($y/$total*100, 1) : 0; + + $cpus['cpu'.$i] = $cpu; + } + + if($fcpu) + return $cpus; + + $threads = array(); + + $l = count($first); + + for($i = 0; $i < $l; $i+=1) + $threads[$i] = $cpus['cpu'.$i]['idle']; + + if(count($first) > 1) + unset($threads[0]); + + $max = max($threads); + + return array_search($max, $threads); + } + + public static function parse_cpu($data) + { + $data = explode("\n", $data); + + $cpu = array(); + + foreach($data as $line) + { + if(preg_match('/^cpu[0-9]/', $line)) + { + $info = explode(' ', $line); + + $cpu[] = array( + 'use' => $info[1], + 'nice' => $info[2], + 'sys' => $info[3], + 'idle' => $info[4] + ); + } + } + + return $cpu; + } + + public static function checkdate($time) + { + $time = explode(' ', $time); + + if(count($time) != 2) + sys::outjs(array('e' => 'Указанная дата неправильная.')); + + $aDate = explode('/', $time[0]); + $aTime = explode(':', $time[1]); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Указанная дата неправильная.')); + + return mktime($aTime[0], $aTime[1], 0, $aDate[1], $aDate[0], $aDate[2]); + } + + public static function passwdkey($passwd) + { + return md5(sha1($passwd)); + } + + public static function mail($name, $text, $mail) + { + global $cfg; + + require_once(LIB.'smtp.php'); + + $tpl = file_get_contents(DATA.'mail.ini', "r"); + + $text = str_replace( + array('[name]', '[text]', '[http]', '[img]', '[css]'), + array($cfg['name'], $text, $cfg['http'], $cfg['http'].'template/images/', $cfg['http'].'template/css/'), + $tpl + ); + + $smtp = new smtp($cfg['smtp_login'], $cfg['smtp_passwd'], $cfg['smtp_url'], $cfg['smtp_mail'], 465); + + $headers = "MIME-Version: 1.0\r\n"; + $headers .= "Content-type: text/html; charset=utf-8\r\n"; + $headers .= "From: ".$cfg['smtp_name']." <".$cfg['smtp_mail'].">\r\n"; + + if($smtp->send($mail, $name, $text, $headers)) + return true; + + return false; + } + + public static function country($address) + { + global $SxGeo; + + if(sys::valid($address, 'ip')) + return 'не определена'; + + $data = $SxGeo->getCityFull($address); + + return $data['country']['name_ru'] != '' ? $data['country']['name_ru'] : 'не определена'; + } + + public static function ipproxy() + { + global $_SERVER; + + if(isset($_SERVER['HTTP_CF_CONNECTING_IP']) && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) + return $_SERVER['HTTP_CF_CONNECTING_IP']; + + return NULL; + } + + public static function ip() + { + $ip = sys::ipproxy(); + + if(sys::valid($ip, 'ip')) + return $_SERVER['REMOTE_ADDR']; + + return $ip; + } + + public static function status($data) + { + if(strpos($data, 'is running') || strpos($data, '(running)')) + return true; + + return false; + } + + public static function strlen($str) + { + return iconv_strlen($str, 'UTF-8'); + } + + public static function bbc($text) + { + global $cfg; + + $lines = explode("\n", $text); + + $str_search = array( + "#\[spoiler\](.+?)\[\/spoiler\]#is", + "#\[sp\](.+?)\[\/sp\]#is", + "#\[b\](.+?)\[\/b\]#is", + "#\[u\](.+?)\[\/u\]#is", + "#\[code\](.+?)\[\/code\]#is", + "#(.+?)<\/code>#isUe", + "#\[quote\](.+?)\[\/quote\]#is", + "#\[url=(.+?)\](.+?)\[\/url\]#is", + "#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is" + ); + + $str_replace = array( + "
    Посмотреть содержимое
    \\1
    ", + "
    Посмотреть содержимое
    \\1
    ", + "\\1", + "\\1", + "
    Посмотреть содержимое
    \\1
    ", + "''.htmlspecialchars('$1').''", + "

    \\1

    ", + "\\2", + "\\2" + ); + + $uptext = ''; + + foreach($lines as $line) + $uptext .= preg_replace($str_search, $str_replace, $line).PHP_EOL; + + return $uptext; + } + + public static function text($section, $name) + { + global $cfg, $user; + + $group = isset($user['group']) ? $user['group'] : 'user'; + + if($section != 'error' || !$cfg['text_group']) + $group = 'all'; + + include(DATA.'text/'.$section.'.php'); + + return isset($text[$name][$group]) ? $text[$name][$group] : $text[$name]; + } + + public static function updtext($text, $data) + { + foreach($data as $name => $val) + $text = str_replace('['.$name.']', $val, $text); + + return $text; + } + } +?> \ No newline at end of file diff --git a/system/library/api.php b/system/library/api.php new file mode 100644 index 0000000..478f980 --- /dev/null +++ b/system/library/api.php @@ -0,0 +1,95 @@ +query('SELECT `unit`, `tarif`, `address`, `game`, `slots_start`, `online`, `players`, `status`, `name`, `map`, `pack`, `fps`, `tickrate`, `ram`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + return array('e' => 'сервер не найден'); + + $server = $sql->get(); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + if(!$sql->num()) + return array('e' => 'локация не найдена'); + + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + if(!$sql->num()) + return array('e' => 'тариф не найден'); + + $tarif = $sql->get(); + $packs = sys::b64djs($tarif['packs']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + return array( + 'id' => $id, + 'address' => $server['address'], + 'unit' => $unit['name'], + 'tarif' => games::info_tarif($server['game'], $tarif['name'], array('fps' => $server['fps'], 'tickrate' => $server['tickrate'], 'ram' => $server['ram'])), + 'game' => $server['game'], + 'name' => $server['name'], + 'slots' => $server['slots_start'], + 'online' => $server['online'], + 'players' => $server['players'], + 'status' => sys::status($server['status'], $server['game'], $server['map']), + 'img' => sys::status($server['status'], $server['game'], $server['map'], 'img'), + 'time_end' => $time_end, + 'time' => sys::today($server['time']), + 'date' => sys::today($server['date']), + 'pack' => $packs[$server['pack']] + ); + } + + public function load($id) + { + global $sql, $cfg; + + $sql->query('SELECT `online`, `slots_start`, `ram_use`, `cpu_use`, `hdd_use` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + return array('e' => 'сервер не найден'); + + $server = $sql->get(); + + $online = 100/$server['slots_start']*$server['online']; + $online = $online > 100 ? 100: $online; + + return array( + 'id' => $id, + 'cpu' => $server['cpu_use'], + 'ram' => $server['ram_use'], + 'hdd' => $server['hdd_use'], + 'onl' => $online + ); + } + + public function console($id, $cmd) + { + global $sql, $cfg; + + $aGames = array('cs', 'css', 'cssold', 'csgo', 'mc', 'mta'); + + $sql->query('SELECT `game` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + return 'сервер не найден'; + + $server = $sql->get(); + + if(!in_array($server['game'], $aGames)) + return 'Игра не поддерживает команды'; + + $go = true; + + $_POST['command'] = isset($cmd{0}) ? urldecode($cmd) : ''; + + include(SEC.'servers/'.$server['game'].'/console.php'); + } + } +?> \ No newline at end of file diff --git a/system/library/captcha/text.ttf b/system/library/captcha/text.ttf new file mode 100644 index 0000000..14dbdc9 Binary files /dev/null and b/system/library/captcha/text.ttf differ diff --git a/system/library/control/actions.php b/system/library/control/actions.php new file mode 100644 index 0000000..2972f05 --- /dev/null +++ b/system/library/control/actions.php @@ -0,0 +1,360 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `name` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="off", `online`="0", `players`="", `stop`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function change($id, $map = false) + { + global $cfg, $sql, $html, $user, $mcache; + + // Если в кеше есть карты + if($mcache->get('ctrl_server_maps_change_'.$id) != '' && !$map) + return array('maps' => $mcache->get('ctrl_server_maps_change_'.$id)); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `online`, `players`, `name` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + // Массив карт игрового сервера (папка "maps") + $aMaps = explode("\n", $ssh->get('cd /servers/'.$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.')); + + // Удаление пустого элемента + unset($aMaps[count($aMaps)-1]); + + // Удаление ".bsp" + $aMaps = str_replace('.bsp', '', $aMaps); + + // Если выбрана карта + if($map) + { + // Проверка наличия выбранной карты + if(!in_array($map, $aMaps)) + return array('e' => sys::updtext(sys::text('servers', 'change'), array('map' => $map.'.bsp'))); + + // Отправка команды changelevel + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval '."'stuff \"changelevel ".sys::cmd($map)."\"\015'"); + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="change" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'], 'players' => base64_decode($server['players']))); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'])); + + return array('s' => 'ok'); + } + + // Сортировка списка карт + sort($aMaps); + reset($aMaps); + + // Генерация списка карт для выбора + foreach($aMaps as $map) + { + $html->get('change_list', 'sections/control/servers/games'); + $html->set('img', file_exists(DIR.'/maps/'.$server['game'].'/'.$map.'.jpg') ? $cfg['http'].'maps/'.$server['game'].'/'.$map.'.jpg' : $cfg['http'].'template/images/status/none.jpg'); + $html->set('name', $map); + $html->set('id', $server['unit']); + $html->set('server', $id); + $html->pack('maps'); + } + + // Запись карт в кеш + $mcache->set('ctrl_server_maps_change_'.$id, $html->arr['maps'], false, 30); + + return array('maps' => $html->arr['maps']); + } + + public static function reinstall($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `address`, `game`, `name`, `pack`, `ftp`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + $path = 'rm '.$server['pack'].'.zip; wget '.$cfg['control_server'].'/'.$server['pack'].'.zip; unzip '.$server['pack'].'.zip; rm '.$server['pack'].'.zip;'; + + if(in_array($server['game'], array('css', 'csgo'))) + $path = 'cd '.$cfg['steamcmd'].'; ./steamcmd.sh +login anonymous +force_install_dir "/servers/'.$uid.'" +app_update '.$cfg['control_steamcmd'][$game].' +quit;'; + + // Директория игрового сервера + $install = '/servers/'.$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('rm -r '.$install.';' // Удаление директории игрового сервера + .'mkdir '.$install.';' // Создание директории + .'chown server'.$server['uid'].':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$server['uid'].' '.$taskset.' screen -dmS r_'.$server['uid'].' sh -c "' + .$path // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + // Очистка записей в базе + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); // Список админов на сервере + $sql->query('DELETE FROM `control_plugins_install` WHERE `server`="'.$id.'"'); // Список установленных плагинов на сервере + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="reinstall", `core_use`="'.$core.'", `fastdl`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'reinstall', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'reinstall', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `address`, `game`, `name`, `pack`, `ftp` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + $path = 'rm '.$server['pack'].'_udp.zip; wget '.$cfg['control_server'].'/'.$server['pack'].'_udp.zip; unzip -u '.$server['pack'].'_udp.zip; rm '.$server['pack'].'_udp.zip;'; + + // Директория игрового сервера + $install = '/servers/'.$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$install.' && sudo -u server'.$server['uid'].' '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "'.$path // Копирование файлов обвновления сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="update", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function delete($id) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `slots`, `address` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$server['uid']) + return array('e' => 'uid 404'); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@:'.$server['address'].' | awk '."'{print $2}'".' | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + // Директория игрового сервера + $install = '/servers/'.$server['uid']; + + $copys = 'screen -dmS r_copy_'.$server['uid'].' sh -c "'; + + $scopy = $sql->query('SELECT `id`, `name` FROM `control_copy` WHERE `server`="'.$id.'"'); + while($copy = $sql->get($scopy)) + { + $copys .= 'rm /copy/'.$copy['name'].'.tar;'; + + $sql->query('DELETE FROM `control_copy` WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + + $copys .= '";'; + + $ssh->set($copys // Удаление резервных копий + .'screen -dmS r_'.$server['uid'].' sh -c "rm -r '.$install.';' // Удаление директории сервера + .'userdel server'.$server['uid'].'"'); // Удаление пользователя сервера c локации + + // Удаление ftp доступа + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';'; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + // Очистка правил FireWall + ctrl::iptables($id, 'remove', NULL, NULL, $server['unit'], false, $ssh); + + // Удаление заданий из crontab + $sql->query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + return array('e' => 'Неудалось создать связь с панелью'); + + $crons = $sql->query('SELECT `id`, `cron` FROM `control_crontab` WHERE `server`="'.$id.'"'); + while($cron = $sql->get($crons)) + { + $ssh->set('echo "" >> /etc/crontab && cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab"); + $ssh->set('crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `control_crontab` WHERE `id`="'.$cron['id'].'" LIMIT 1'); + } + + // Удаление различной информации игрового сервера + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `control_plugins_install` WHERE `server`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `control_plugins_buy` WHERE `server`="'.$id.'" LIMIT 1'); + $sql->query('DELETE FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + + return array('s' => 'ok'); + } + + public static function clmcache($id) + { + global $mcache; + + $mcache->delete('ctrl_server_index_'.$id); + $mcache->delete('ctrl_server_resources_'.$id); + $mcache->delete('ctrl_server_status_'.$id); + } + } \ No newline at end of file diff --git a/system/library/control/control.php b/system/library/control/control.php new file mode 100644 index 0000000..ad2b1a9 --- /dev/null +++ b/system/library/control/control.php @@ -0,0 +1,448 @@ +arr['btn'] = ''; + + if($status == 'working') + { + $html->get('restart', 'sections/control/buttons'); + $html->set('id', $id); + $html->pack('btn'); + + return $html->arr['btn']; + } + + return ''; + } + + public static function resources($id) + { + global $sql; + + include(LIB.'ssh.php'); + + $aData = array( + 'cpu' => '0%', + 'ram' => '0%', + 'hdd' => '0%' + ); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + if(!$ssh->auth($ctrl['passwd'], $ctrl['address'])) + sys::outjs($aData); + + $data = $ssh->get('echo `cat /proc/meminfo | grep MemTotal | awk \'{print $2}\'; cat /proc/meminfo | grep MemFree | awk \'{print $2}\'; cat /proc/meminfo | grep Buffers | awk \'{print $2}\'; cat /proc/meminfo | grep Cached | grep -v SwapCached | awk \'{print $2}\'`'); + $aData['ram'] = ceil(ctrl::ram_load($data)).'%'; + + $aData['hdd'] = trim($ssh->get('df -h | awk \'/rootfs/ {print $5}\'')); + + $aData['cpu'] = ctrl::cpu_load($ssh->get('echo "`ps -A -o pcpu | tail -n+2 | paste -sd+ | bc | awk \'{print $0}\'` `cat /proc/cpuinfo | grep processor | wc -l | awk \'{print $1}\'`"')).'%'; + + sys::outjs($aData); + } + + public static function update_info($id) + { + global $sql; + + include(LIB.'ssh.php'); + + $aData = array( + 'cpu' => 'произошла ошибка', + 'ram' => 'произошла ошибка', + 'hdd' => 'произошла ошибка' + ); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + if(!$ssh->auth($ctrl['passwd'], $ctrl['address'].':22')) + sys::outjs($aData); + + $data = $ssh->get('cat /proc/meminfo | grep MemTotal | cut -d \' \' -f 2-'); + $aData['ram'] = $data.' ('.(round(sys::int($data)/1024/1024, 2)).'Gb)'; + + $aData['hdd'] = trim($ssh->get('df -h | awk \'/rootfs/ {print $2}\'')); + + $aCPU = explode("\n", trim($ssh->get('cat /proc/cpuinfo | grep -c processor && cat /proc/cpuinfo | grep "MHz" | awk \'{print $4}\' | head -n 1'))); + + $aData['cpu'] = $aCPU[0].'x'.round($aCPU[1], 0).' MHz ['.trim($ssh->get('cat /proc/cpuinfo | grep -m 1 "model name" | cut -d \' \' -f 3-')).']'; + + sys::outjs($aData); + } + + public static function update_status($id, $ssh = false) + { + global $cfg, $sql, $start_point, $mcache; + + if(!$ssh) + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd`, `time`, `overdue`, `block`, `status` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + $status = $ctrl['status']; + + if($ctrl['status'] == 'blocked' && $ctrl['block'] < $start_point) + $sql->query('UPDATE `control` set `block`="0", `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($ctrl['status'] == 'blocked') + return 'blocked'; + + // Если аренда закончилась и сервер просрочен длительное время + if($ctrl['time'] < $start_point && $ctrl['status'] == 'overdue' && ($ctrl['overdue']+$cfg['control_delete']*86400) < $start_point) + { + $sql->query('UPDATE `control` set `user`="-1" WHERE `id`="'.$id.'" LIMIT 1'); + + return 'delete'; + } + + // Если аренда закончилась, а услуга не просрочена + if($ctrl['time'] < $start_point && !in_array($ctrl['status'], array('overdue', 'blocked'))) + { + $sql->query('UPDATE `control` set `status`="overdue" WHERE `id`="'.$id.'" LIMIT 1'); + + $status = 'overdue'; + } + + // Если аренда не закончилась, а услуга просрочена + if($ctrl['time'] > $start_point && $ctrl['status'] == 'overdue') + $sql->query('UPDATE `control` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($ctrl['status'], array('working', 'error'))) + { + $status = 'working'; + if(!$ssh->auth($ctrl['passwd'], $ctrl['address'])) + $status = 'error'; + + $sql->query('UPDATE `control` set `status`="'.$status.'" WHERE `id`="'.$id.'" LIMIT 1'); + } + + if($ctrl['status'] == 'reboot' && !$mcache->get('reboot_control_'.$id)) + { + if($ssh->auth($ctrl['passwd'], $ctrl['address'])) + { + $sql->query('UPDATE `control` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + $status = 'working'; + } + } + + $time_end = $ctrl['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $ctrl['overdue']+$cfg['control_delete']*86400) : 'Осталось: '.sys::date('min', $ctrl['time']); + + $aData = array( + 'time' => sys::today($ctrl['time']), + 'time_end' => $time_end, + 'buttons' => ctrl::buttons($id, $status), + 'status' => ctrl::status($status) + ); + + return $aData; + } + + public static function ram_load($data) + { + $aData = explode(' ', $data); + + return ceil(($aData[0]-($aData[1]+$aData[2]+$aData[3]))*100/$aData[0]); + } + + public static function cpu_load($data) + { + $aData = explode(' ', $data); + + $load = ceil($aData[0]/$aData[1]); + + return $load > 100 ? 100 : $load; + } + + public static function nav($server, $id, $sid, $active) + { + global $cfg, $html, $sql, $mcache, $start_point; + + $aUnit = array('index', 'console', 'settings', 'plugins', 'filetp', 'copy', 'boost'); + + $html->get('gmenu', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('home', $cfg['http']); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('main'); + + $html->get('vmenu', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('home', $cfg['http']); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('vmenu'); + + return NULL; + } + + public static function route($server, $inc, $go) + { + global $device, $start_point; + + if(in_array($server['status'], array('install', 'reinstall', 'update', 'recovery'))) + { + if($go) + sys::out('Раздел недоступен'); + + return SEC.'control/servers/noaccess.php'; + } + + if(!file_exists(SEC.'control/servers/'.$server['game'].'/'.$inc.'.php')) + return SEC.'control/servers/'.$server['game'].'/index.php'; + + return SEC.'control/servers/'.$server['game'].'/'.$inc.'.php'; + } + + public static function cpulist($unit, $core, $count = false) + { + global $device, $start_point; + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($count) + return 1; + + $out = $core ? '' : ''; + + sys::outjs(array('core_fix' => $core)); + } + + $n = sys::int($ssh->get('cat /proc/cpuinfo | grep "cpu MHz" | wc -l')); + + if($count) + return $n; + + $list = ''; + + for($i = 1; $i <= $n; $i+=1) + $list .= ''; + + sys::outjs(array('core_fix' => str_replace($core.'"', $core.'" selected="select"', $list))); + } + + public static function iptables($id, $action, $source, $dest, $unit, $snw = false, $ssh = false) + { + global $cfg, $sql, $start_point; + + if(!$ssh) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$unit.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('all', 'ssh')); + } + + switch($action) + { + case 'block': + if(sys::valid($source, 'ip')) + return array('e' => sys::text('servers', 'firewall')); + + // Если подсеть + if($snw) + { + $source = sys::whois($source); + + if($source == 'не определена') + return array('e' => 'Не удалось определить подсеть для указанного адреса.'); + } + + $sql->query('SELECT `id` FROM `control_firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если такое правило уже добавлено или указан адрес сайта (ПУ) + if($sql->num() || ($source == $cfg['ip'] || $source == $cfg['subnet'])) + return array('s' => 'ok'); + + $sql->query('INSERT INTO `control_firewall` set `sip`="'.$source.'", `dest`="'.$dest[0].':'.$dest[1].'", `server`="'.$id.'", `time`="'.$start_point.'"'); + + $line = $sql->id(); + + $rule = 'iptables -I INPUT -s '.$source.' -p udp -d '.$dest[0].' --dport '.$dest[1].' -j DROP;'; + + $ssh->set($rule.' echo -e "#'.$line.';\n'.$rule.'" >> /root/'.$cfg['iptables']); + + return array('s' => 'ok'); + + case 'unblock': + if(!is_numeric($source) AND sys::valid($source, 'ip')) + return array('e' => sys::text('servers', 'firewall')); + + if(is_numeric($source)) + { + $sql->query('SELECT `id`, `sip` FROM `control_firewall` WHERE `id`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если такое правило отсутствует + if(!$sql->num()) + return array('s' => 'ok'); + }else{ + $sql->query('SELECT `id`, `sip` FROM `control_firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если одиночный адрес не найден, проверить на блокировку подсети + if(!$sql->num()) + { + $source = sys::whois($source); + + $sql->query('SELECT `id` FROM `control_firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + { + $firewall = $sql->get(); + + return array('i' => 'Указанный адрес входит в заблокированную подсеть, разблокировать подсеть?', 'id' => $firewall['id']); + } + + return array('s' => 'ok'); + } + } + + $firewall = $sql->get(); + + $ssh->set('iptables -D INPUT -s '.$firewall['sip'].' -p udp -d '.$dest[0].' --dport '.$dest[1].' -j DROP;' + .'sed "`nl '.$cfg['iptables'].' | grep \"#'.$firewall['id'].'\" | awk \'{print $1","$1+1}\'`d" '.$cfg['iptables'].' > '.$cfg['iptables'].'_temp; cat '.$cfg['iptables'].'_temp > '.$cfg['iptables'].'; rm '.$cfg['iptables'].'_temp'); + + $sql->query('DELETE FROM `control_firewall` WHERE `id`="'.$firewall['id'].'" LIMIT 1'); + + return array('s' => 'ok'); + + case 'remove': + $sql->query('SELECT `id`, `sip`, `dest` FROM `control_firewall` WHERE `server`="'.$id.'"'); + + $aRule = array(); + + while($firewall = $sql->get()) + { + list($ip, $port) = explode(':', $firewall['dest']); + + $aRule[$firewall['id']] = 'iptables -D INPUT -s '.$firewall['sip'].' -p udp -d '.$ip.' --dport '.$port.' -j DROP;'; + } + + $nRule = count($aRule); + + if(!$nRule) + return NULL; + + $cmd = ''; + + foreach($aRule as $line => $rule) + $cmd .= $rule.'sed "`nl '.$cfg['iptables'].' | grep "#'.$line.'" | awk \'{print $1","$1+1}\'`d" '.$cfg['iptables'].' > '.$cfg['iptables'].'_temp; cat '.$cfg['iptables'].'_temp > '.$cfg['iptables'].'; rm '.$cfg['iptables'].'_temp'; + + $ssh->set($cmd); + + $sql->query('DELETE FROM `control_firewall` WHERE `server`="'.$id.'" LIMIT '.$nRule); + + return array('s' => 'ok'); + } + } + + public static function crontab($data = array(), $id, $cid) + { + global $cfg; + + if($data['allhour']) + $time = '0 * * * '; + else{ + $hour = array( + '00', '01', '02', + '03', '04', '05', + '06', '07', '08', + '09', '10', '11', + '12', '13', '14', + '15', '16', '17', + '18', '19', '20', + '21', '22', '23' + ); + + $minute = array( + '00', '05', '10', + '15', '20', '25', + '30', '35', '40', + '45', '50', '55' + ); + + if(!in_array($data['hour'], $hour)) + $data['hour'] = '00'; + + if(!in_array($data['minute'], $minute)) + $data['minute'] = '00'; + + $time = $data['minute'].' '.$data['hour'].' * * '; + } + + $week = array(); + $week[1] = isset($data['week']['\'1\'']) ? 1 : 0; + $week[2] = isset($data['week']['\'2\'']) ? 2 : 0; + $week[3] = isset($data['week']['\'3\'']) ? 3 : 0; + $week[4] = isset($data['week']['\'4\'']) ? 4 : 0; + $week[5] = isset($data['week']['\'5\'']) ? 5 : 0; + $week[6] = isset($data['week']['\'6\'']) ? 6 : 0; + $week[7] = isset($data['week']['\'7\'']) ? 7 : 0; + + $check = 0; + + foreach($week as $index => $val) + $check+= $val; + + if($check == 28 || !$check) + $week = '*'; + else{ + $weeks = $week[1].','.$week[2].','.$week[3].','.$week[4].','.$week[5].','.$week[6].','.$week[7]; + $weeks = str_replace(array(',0', '0'), '', $weeks); + $week = $weeks{0} == ',' ? substr($weeks, 1) : $weeks; + } + + $cron_task = $time.$week.' screen -dmS s'.$id.' bash -c \'cd /var/enginegp && php cron.php '.$cfg['cron_key'].' control_server_cron '.$id.' '.$cid.'\''; + + return $cron_task; + } + } +?> \ No newline at end of file diff --git a/system/library/control/cs/action.php b/system/library/control/cs/action.php new file mode 100644 index 0000000..492e689 --- /dev/null +++ b/system/library/control/cs/action.php @@ -0,0 +1,109 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `slots`, `name`, `fps`, `map_start`, `vac`, `pingboost`, `time_start`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd /servers/'.$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // Значение PingBoost + $pingboost = $server['pingboost'] ? '-pingboost '.$pingboost : ''; + + // Значение sys_ticrate (FPS) + $fps = $server['fps']; + + // Параметры запуска + $bash = './hlds_run -debug -game cstrike -norestart -condebug -sys_ticrate '.$fps.' +servercfgfile server.cfg +sys_ticrate '.$fps.' +map \''.$server['map_start'].'\' +maxplayers '.$server['slots'].' +ip '.$ip.' +port '.$port.' +sv_lan 0 '.$vac.' '.$pingboost; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, '/servers/'.$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd /servers/'.$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/qconsole.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/qconsole.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c ./start.sh'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/control/cs/rcon.php b/system/library/control/cs/rcon.php new file mode 100644 index 0000000..08717ed --- /dev/null +++ b/system/library/control/cs/rcon.php @@ -0,0 +1,107 @@ +Connect($ip, $port, 3, SourceQuery::GOLDSOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[1]); + $ip = trim(sys::first(explode(':', $aData[6]))); + + if(sys::valid($steamid, 'steamid') || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['frags'] = trim($aData[2]); + $aPlayers[$n]['time'] = trim($aData[3]); + $aPlayers[$n]['ping'] = trim($aData[4]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $ssh->set('cat /servers/'.$server['uid'].'/cstrike/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'control/id/'.$server['unit'].'/server/'.$server['unit'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/control/cs/scan.php b/system/library/control/cs/scan.php new file mode 100644 index 0000000..20e3fe1 --- /dev/null +++ b/system/library/control/cs/scan.php @@ -0,0 +1,133 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `unit`, `game`, `name`, `map`, `online`, `players`, `status` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game'], $server['unit']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game'], $server['unit']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `control_servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `control_servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::GOLDSOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/control/csgo/action.php b/system/library/control/csgo/action.php new file mode 100644 index 0000000..0232e54 --- /dev/null +++ b/system/library/control/csgo/action.php @@ -0,0 +1,282 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `slots`, `name`, `tickrate`, `map_start`, `vac`, `time_start`, `core_fix`, `pingboost` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd /servers/'.$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\''); + + include_once(LIB.'games/games.php'); + + if(games::map($server['map_start'], $ssh->get())) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 30 +tv_port '.($port+10000) : '-nohltv'; + + $check = explode('/', $server['map_start']); + + // Стартовая карта + $map = $check[0] == 'workshop' ? '+workshop_start_map '.$check[1] : '+map \''.$server['map_start'].'\''; + + // Игровой режим + $mods = array( + 1 => '+game_type 0 +game_mode 0', + 2 => '+game_type 0 +game_mode 1', + 3 => '+game_type 1 +game_mode 0', + 4 => '+game_type 1 +game_mode 1', + 5 => '+game_type 1 +game_mode 2' + ); + + $mod = !$server['pingboost'] ? $mods[2] : $mods[$server['pingboost']]; + + // Параметры запуска + $bash = './srcds_run -debug -game csgo -norestart -condebug console.log -usercon -tickrate '.$server['tickrate'].' '.$mod.' +servercfgfile server.cfg '.$map.' -maxplayers_override '.$server['slots'].' +ip '.$ip.' +net_public_adr '.$ip.' +port '.$port.' -sv_lan 0 '.$vac.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, '/servers/'.$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd /servers/'.$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p csgo/oldstart;' // Создание папки логов + .'cat csgo/console.log >> csgo/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm csgo/console.log; rm csgo/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function change($id, $map = false) + { + global $cfg, $sql, $html, $user, $mcache; + + // Если в кеше есть карты + if($mcache->get('ctrl_server_maps_change_'.$id) != '' AND !$map) + return array('maps' => $mcache->get('ctrl_server_maps_change_'.$id)); + + include(LIB.'ssh.php'); + + include(LIB.'games/games.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `online`, `players`, `name` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + // Массив карт игрового сервера (папка "maps") + $aMaps = explode("\n", $ssh->get('cd /servers/'.$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\'')); + + // Удаление пустого элемента + unset($aMaps[count($aMaps)-1]); + + // Удаление ".bsp" + $aMaps = str_ireplace(array('./', '.bsp'), '', $aMaps); + + // Если выбрана карта + if($map) + { + $map = str_replace('|', '/', $map); + + // Проверка наличия выбранной карты + if(games::map($map, $aMaps)) + return array('e' => sys::updtext(sys::text('servers', 'change'), array('map' => $map.'.bsp'))); + + // Отправка команды changelevel + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval '."'stuff \"changelevel ".sys::cmd($map)."\"\015'"); + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="change" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'], 'players' => base64_decode($server['players']))); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'])); + + return array('s' => 'ok'); + } + + // Сортировка списка карт + sort($aMaps); + reset($aMaps); + + // Генерация списка карт для выбора + foreach($aMaps as $map) + { + $aName = explode('/', $map); + $name = end($aName); + + $html->get('change_list', 'sections/control/servers/csgo'); + + $html->set('img', file_exists(DIR.'/maps/'.$server['game'].'/'.$name.'.jpg') ? $cfg['http'].'maps/'.$server['game'].'/'.$name.'.jpg' : $cfg['http'].'template/images/status/none.jpg'); + $html->set('map', str_replace('/', '|', $map)); + $html->set('name', $name); + $html->set('id', $server['unit']); + $html->set('server', $id); + + if(count($aName) > 1) + $html->unit('workshop', true); + else + $html->unit('workshop'); + + $html->pack('maps'); + } + + // Запись карт в кеш + $mcache->set('ctrl_server_maps_change_'.$id, $html->arr['maps'], false, 60); + + return array('maps' => $html->arr['maps']); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `name`, `ftp`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория игрового сервера + $install = '/servers/'.$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$cfg['steamcmd'].' && '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "' + .'./steamcmd.sh +login anonymous +force_install_dir "'.$install.'" +app_update 740 +quit;' + .'cd '.$install.';' + .'chown -R server'.$server['uid'].':servers .;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="update", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/control/csgo/rcon.php b/system/library/control/csgo/rcon.php new file mode 100644 index 0000000..cfaf75c --- /dev/null +++ b/system/library/control/csgo/rcon.php @@ -0,0 +1,109 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if((sys::valid($steamid, 'steamid') AND sys::valid($steamid, 'steamid3')) || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $ssh->set('cat /servers/'.$server['uid'].'/csgo/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'control/id/'.$server['unit'].'/server/'.$server['unit'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/control/csgo/scan.php b/system/library/control/csgo/scan.php new file mode 100644 index 0000000..3c89854 --- /dev/null +++ b/system/library/control/csgo/scan.php @@ -0,0 +1,135 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `unit`, `game`, `name`, `map`, `online`, `players`, `status` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game'], $server['unit']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game'], $server['unit']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `control_servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `control_servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $map = explode('/', $data['Map']); + + $server['name'] = $data['HostName']; + $server['map'] = end($map); + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/control/css/action.php b/system/library/control/css/action.php new file mode 100644 index 0000000..638b854 --- /dev/null +++ b/system/library/control/css/action.php @@ -0,0 +1,177 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `slots`, `name`, `tickrate`, `map_start`, `vac`, `time_start`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd /servers/'.$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 255 +tv_port '.($port+10000) : '-nohltv'; + + // Параметры запуска + $bash = './srcds_run -debug -game cstrike -norestart -condebug console.log -tickrate '.$server['tickrate'].' +servercfgfile server.cfg +map \''.$server['map_start'].'\' +maxplayers '.$server['slots'].' +ip '.$ip.' +port '.$port.' -sv_lan 0 '.$vac.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, '/servers/'.$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd /servers/'.$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/console.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/console.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `name`, `ftp`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория игрового сервера + $install = '/servers/'.$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$cfg['steamcmd'].' && '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "' + .'./steamcmd.sh +login anonymous +force_install_dir "'.$install.'" +app_update 232330 +quit;' + .'cd '.$install.';' + .'chown -R server'.$server['uid'].':servers .;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="update", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/control/css/rcon.php b/system/library/control/css/rcon.php new file mode 100644 index 0000000..1dff675 --- /dev/null +++ b/system/library/control/css/rcon.php @@ -0,0 +1,109 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if((sys::valid($steamid, 'steamid') AND sys::valid($steamid, 'steamid3')) || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $ssh->set('cat /servers/'.$server['uid'].'/cstrike/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'control/id/'.$server['unit'].'/server/'.$server['unit'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/control/css/scan.php b/system/library/control/css/scan.php new file mode 100644 index 0000000..f736d83 --- /dev/null +++ b/system/library/control/css/scan.php @@ -0,0 +1,133 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `unit`, `game`, `name`, `map`, `online`, `players`, `status` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game'], $server['unit']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game'], $server['unit']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `control_servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `control_servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/control/cssold/action.php b/system/library/control/cssold/action.php new file mode 100644 index 0000000..392f4f2 --- /dev/null +++ b/system/library/control/cssold/action.php @@ -0,0 +1,110 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `slots`, `name`, `tickrate`, `fps`, `map_start`, `vac`, `time_start`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if(!$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd /servers/'.$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 255 +tv_port '.($port+10000) : '-nohltv'; + + // FPS + $fps = $server['fps']; + + // Параметры запуска + $bash = './srcds_run -debug -game cstrike -norestart -condebug console.log -tickrate '.$server['tickrate'].' +fps_egp '.$fps.' +servercfgfile server.cfg +map \''.$server['map_start'].'\' +maxplayers '.$server['slots'].' +ip '.$ip.' +port '.$port.' +sv_lan 0 -nomaster -localcser '.$vac.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, '/servers/'.$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd /servers/'.$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'mv console.log oldstart.log;' // Перемещение лога предыдущего запуска в файл oldstart.log + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/console.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/console.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `control_servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/control/cssold/rcon.php b/system/library/control/cssold/rcon.php new file mode 100644 index 0000000..97607e6 --- /dev/null +++ b/system/library/control/cssold/rcon.php @@ -0,0 +1,109 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if(sys::valid($steamid, 'steamid') || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $ssh->set('cat /servers/'.$server['uid'].'/cstrike/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'control/id/'.$server['unit'].'/server/'.$server['unit'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/control/cssold/scan.php b/system/library/control/cssold/scan.php new file mode 100644 index 0000000..f736d83 --- /dev/null +++ b/system/library/control/cssold/scan.php @@ -0,0 +1,133 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `unit`, `game`, `name`, `map`, `online`, `players`, `status` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game'], $server['unit']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game'], $server['unit']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `control_servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `control_servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/control/plugins.php b/system/library/control/plugins.php new file mode 100644 index 0000000..96700cd --- /dev/null +++ b/system/library/control/plugins.php @@ -0,0 +1,181 @@ +arr['images'])) + unset($html->arr['images']); + + $aImg = explode("\n", $images); + + foreach($aImg as $img) + { + $html->get('plugin_images', 'sections/control/servers/games/plugins'); + + $html->set('id', $plugin); + $html->set('img', $img); + + $html->pack('images'); + } + + return isset($html->arr['images']) ? $html->arr['images'] : ''; + } + + public static function status($status) + { + global $html; + + if(!$status) + { + $html->unit('unstable'); + $html->unit('stable', 1); + $html->unit('testing'); + }elseif($status == 2){ + $html->unit('unstable'); + $html->unit('stable'); + $html->unit('testing', 1); + }else{ + $html->unit('unstable', 1); + $html->unit('stable'); + $html->unit('testing'); + } + + return NULL; + } + + public static function required($id, $required, $choice, $mcache) + { + global $sql; + + if($required == '') + return NULL; + + $aRequi = explode(':', $required); + + foreach($aRequi as $pl) + { + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pl.'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$pl.'" LIMIT 1'); + $plRequi = $sql->get(); + + if($choice != '') + { + $aChoice = explode(' ', $choice); + + foreach($aChoice as $plugins) + { + $aPlugins = explode(':', $plugins); + + if(in_array($pl, $aPlugins)) + { + $options = ''; + foreach($aPlugins as $plugin) + { + $sql->query('SELECT `name`, `upd` FROM `plugins` WHERE `id`="'.$plugin.'" LIMIT 1'); + $data = $sql->get(); + + if($data['upd']) + { + $sql->query('SELECT `name` FROM `plugins_update` WHERE `plugin`="'.$plugin.'" ORDER BY `id` DESC LIMIT 1'); + $data = $sql->get(); + } + + $options .= ''; + } + + if($options != '') + sys::outjs(array('e' => 'Для данного плагина требуется установка одного из родителя', 'required' => true, 'pid' => $pl, 'select' => $options), $mcache); + } + } + } + + sys::outjs(array('e' => 'Для данного плагина требуется установка родителя', 'required' => true, 'pid' => $pl, 'pname' => htmlspecialchars_decode($plRequi['name'])), $mcache); + } + } + + return NULL; + } + + public static function incompatible($id, $incompatible, $mcache) + { + global $sql; + + if($incompatible == '') + return NULL; + + $aIncomp = explode(':', $incompatible); + + foreach($aIncomp as $pl) + { + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pl.'" LIMIT 1'); + if($sql->num()) + { + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$pl.'" LIMIT 1'); + $plIncomp = $sql->get(); + + sys::outjs(array('e' => 'Данный плагин несовместим с уже установленным плагином', 'pid' => $pl, 'pname' => htmlspecialchars_decode($plIncomp['name'])), $mcache); + } + } + + return NULL; + } + + public static function clear($clear, $uid, $dir) + { + global $ssh; + + // Если регулярное выражение + if(isset($clear['regex']) AND $clear['regex']) + { + $file = preg_replace($clear['text'], '', $ssh->get('sudo -u server'.$uid.' cat '.$dir.$clear['file'])); + + // Временный файл + $temp = sys::temp($file); + + $ssh->setfile($temp, $dir.$clear['file'], 0644); + + unlink($temp); + + $query = 'chown server'.$uid.':servers '.$dir.$clear['file'].';'; + + }else + // Удаление текста из файла + $query = 'sudo -u server'.$uid.' sed -i '."'s/".str_replace('/', '\/', htmlspecialchars_decode($clear['text']))."//g'".' '.$dir.$clear['file'].';'; + + $ssh->set($query.'sudo -u server'.$uid.' sed -i '."'/./!d'".' '.$dir.$clear['file']); + + return NULL; + } + + public static function write($write, $uid, $dir) + { + global $ssh; + + // Костыль (добавить пустую строку на всякий случай) + $query = 'sudo -u server'.$uid.' echo "" >> '.$dir.$write['file'].';'; + + // Исключить дублирование, путем удаления добавляемого текста + $query .= 'sudo -u server'.$uid.' sed -i '."'s/".str_replace('/', '\/', htmlspecialchars_decode($write['text']))."//g'".' '.$dir.$write['file'].';'; + + // Добавление текста в начало файла + if($write['top']) + $query .= 'sudo -u server'.$uid.' touch '.$dir.$write['file'].'; sudo -u server'.$uid.' sed -i '."'1i ".str_replace(array('/', "'", '\"'), array('\/', "\'", '"'), htmlspecialchars_decode($write['text']))."'".' '.$dir.$write['file'].';'; + else + // Добавление текста в конец файла + $query .= 'sudo -u server'.$uid.' touch '.$dir.$write['file'].'; sudo -u server'.$uid.' echo "'.str_replace('"', '\"', htmlspecialchars_decode($write['text'])).'" >> '.$dir.$write['file'].';'; + + $ssh->set($query.'sudo -u server'.$uid.' sed -i '."'/./!d'".' '.$dir.$clear['file']); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/control/scans.php b/system/library/control/scans.php new file mode 100644 index 0000000..9b94376 --- /dev/null +++ b/system/library/control/scans.php @@ -0,0 +1,186 @@ + 'hlds_', + 'cssold' => 'srcds_i686', + 'css' => 'srcds_', + 'csgo' => 'srcds_', + 'samp' => 'samp', + 'crmp' => 'samp', + 'mta' => 'mta', + 'mc' => 'java' + ); + + public static function resources($id) + { + global $cfg, $sql, $mcache; + + $nmch = 'ctrl_server_resources_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $sql->query('SELECT `uid`, `unit`, `game`, `slots`, `status`, `online`, `hdd_use` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $server = $sql->get(); + + $resources = array( + 'usr' => 0, + 'cpu' => 0, + 'ram' => 0, + 'hdd' => $server['hdd_use'] + ); + + $sql->query('SELECT `address`, `passwd`, `ram`, `hdd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return $resources; + + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + return $resources; + + $resources['usr'] = ceil(100/$server['slots']*$server['online']); + $resources['usr'] = $resources['usr'] > 100 ? 100 : $resources['usr']; + + $cr = explode('|', $ssh->get('top -u '.$server['uid'].' -b -n 1 | grep '.(scans::$process[$server['game']]).' | sort | tail -1 | awk \'{print $9"|"$10}\'')); + + if(isset($cr[0])) + $resources['cpu'] = str_replace(',', '.', $cr[0]); + + $resources['cpu'] = $resources['cpu'] > 100 ? 100 : round($resources['cpu']); + + if(isset($cr[1])) + $resources['ram'] = str_replace(',', '.', $cr[1]); + + // ram на сервер + $ram = $server['ram'] ? $server['ram'] : $server['slots']*$cfg['ram'][$server['game']]; + + $resources['ram'] = $unit['ram']/100*$resources['ram']/($ram/100); + + $resources['ram'] = $resources['ram'] > 100 ? 100 : round($resources['ram']); + + $resources['hdd'] = ceil(sys::int($ssh->get('cd /servers/'.$server['uid'].' && du -ms'))/($unit['hdd']/100)); + $resources['hdd'] = $resources['hdd'] > 100 ? 100 : $resources['hdd']; + + $sql->query('UPDATE `control_servers` set `ram_use`="'.$resources['ram'].'", `cpu_use`="'.$resources['cpu'].'", `hdd_use`="'.$resources['hdd'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $resources, false, $cfg['mcache_server_resources']); + + return $resources; + } + + public static function status($id) + { + global $start_point, $cfg, $sql, $mcache; + + $nmch = 'ctrl_server_status_'.$id; + + if($mcache->get($nmch)) + return 'mcache -> system_block_operation'; + + $mcache->set($nmch, true, false, $cfg['mcache_server_status']); + + $sql->query('SELECT `uid`, `unit`, `game`, `address`, `status`, `name`, `online`, `players` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return 'unit error connect'; + + switch($server['status']) + { + case 'working': case 'change': case 'start': case 'restart': + if(!sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off", `online`="0", `players`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> working -> off'; + } + + break; + + case 'off': + if(sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'working', 'online' => $server['online'], 'players' => $server['players'])); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'working', 'online' => $server['online'])); + + return 'server -> off -> working'; + } + + break; + + case 'reinstall': + if(!sys::int($ssh->get('ps aux | grep r_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> reinstall -> end'; + } + + break; + + case 'update': + if(!sys::int($ssh->get('ps aux | grep u_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> update -> end'; + } + + break; + + case 'install': + if(!sys::int($ssh->get('ps aux | grep i_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> install -> end'; + } + + break; + + case 'recovery': + if(!sys::int($ssh->get('ps aux | grep rec_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> recovery -> end'; + } + } + + return 'server -> no change -> end scan'; + } + } +?> \ No newline at end of file diff --git a/system/library/cron.php b/system/library/cron.php new file mode 100644 index 0000000..cac5f93 --- /dev/null +++ b/system/library/cron.php @@ -0,0 +1,77 @@ + 0, 'group' => 'admin'); + + class cron + { + public static $seping = 5; + + public static $process = array( + 'cs' => 'hlds_', + 'cssold' => 'srcds_i686', + 'css' => 'srcds_', + 'csgo' => 'srcds_', + 'samp' => 'samp', + 'crmp' => 'samp', + 'mta' => 'mta', + 'mc' => 'java' + ); + + public static $quakestat = array( + 'cs' => 'a2s', + 'cssold' => 'a2s', + 'css' => 'a2s', + 'csgo' => 'a2s', + 'mta' => 'eye' + ); + + public static $admins_file = array( + 'cs' => 'cstrike/addons/amxmodx/configs/users.ini', + 'cssold' => 'cstrike/addons/sourcemod/configs/admins_simple.ini', + 'css' => 'cstrike/addons/sourcemod/configs/admins_simple.ini', + 'csgo' => 'csgo/addons/sourcemod/configs/admins_simple.ini' + ); + + public static function thread($num, $type, $aData) + { + $threads = array(); + + for($n = 1; $n <= $num; $n+=1) + { + $data = ''; + + $i = 0; + + foreach($aData as $key => $val) + { + if($i == cron::$seping) + break; + + $data .= $val.' '; + + unset($aData[$key]); + + $i+=1; + } + + $aData = array_values($aData); + + $threads[] = $type.' '.substr($data, 0, -1); + } + + return $threads; + } + } + + include(CRON.$task.'.php'); + + new $task(); +?> \ No newline at end of file diff --git a/system/library/cron/control_delete.php b/system/library/cron/control_delete.php new file mode 100644 index 0000000..3adc903 --- /dev/null +++ b/system/library/cron/control_delete.php @@ -0,0 +1,36 @@ +query('SELECT `id` FROM `control` WHERE `user`="-1" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $servers = $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$unit['id'].'"'); + while($server = $sql->get($servers)) + { + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `control_copy` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `control_firewall` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `control_plugins_install` WHERE `server`="'.$server['id'].'"'); + } + + // Удаление различной информации игрового сервера + $sql->query('DELETE FROM `control_servers` WHERE `unit`="'.$unit['id'].'"'); + $sql->query('DELETE FROM `control` WHERE `id`="'.$unit['id'].'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `control`="'.$unit['id'].'", `text`="Удаление подключенного сервера #'.$unit['id'].' ('.$unit['address'].') passwd: #'.$unit['passwd'].'", `time`="'.$start_point.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_install.php b/system/library/cron/control_install.php new file mode 100644 index 0000000..ee0f604 --- /dev/null +++ b/system/library/cron/control_install.php @@ -0,0 +1,35 @@ +query('SELECT `id`, `address`, `passwd` FROM `control` WHERE `status`="install" AND `install`="0" LIMIT 1'); + + if(!$sql->num()) + exit('not found'); + + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + exit('error connect'); + + $ssh->set('apt-get update; apt-get install -y wget screen'); + + sleep(20); + + $ssh->set('screen -dmS install bash -c "cd /tmp; rm script.sh; wget -O script.sh [home]autocontrol/action/script --no-check-certificate; chmod 500 script.sh;./script.sh"'); + + $sql->query('UPDATE `control` set install="1" WHERE `id`="'.$unit['id'].'" LIMIT 1'); + + exit('install'); + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_scan_servers.php b/system/library/cron/control_scan_servers.php new file mode 100644 index 0000000..5657515 --- /dev/null +++ b/system/library/cron/control_scan_servers.php @@ -0,0 +1,105 @@ +query('SELECT `address` FROM `control` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `control_servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid`, `address`, `status`, `stop` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + switch($server['status']) + { + case 'working': case 'change': case 'start': case 'restart': + if(!sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `control_servers` set `status`="off", `online`="0", `players`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запуск сервера (если он был выключен не через панель) + if($server['stop']) + { + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' control_server_action start '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="[Контроль] Включение сервера: сервер выключен не через панель", `time`="'.$start_point.'"'); + } + }else + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' control_server_scan '.$game.' '.$id.'"'); + + break; + + case 'off': + if(sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_servers` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + else{ + // Запуск сервера (если он был выключен не через панель) + if($server['stop']) + { + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' control_server_action start '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="[Контроль] Включение сервера: сервер выключен не через панель", `time`="'.$start_point.'"'); + + continue; + } + } + + break; + + case 'reinstall': + if(!sys::int($ssh->get('ps aux | grep r_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'update': + if(!sys::int($ssh->get('ps aux | grep u_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'install': + if(!sys::int($ssh->get('ps aux | grep i_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'recovery': + if(!sys::int($ssh->get('ps aux | grep rec_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_scan_servers_admins.php b/system/library/cron/control_scan_servers_admins.php new file mode 100644 index 0000000..a9c64ed --- /dev/null +++ b/system/library/cron/control_scan_servers_admins.php @@ -0,0 +1,68 @@ +query('SELECT `address` FROM `control` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `control_servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $admins = $sql->query('SELECT `id`, `text` FROM `control_admins_'.$game.'` WHERE `server`="'.$id.'" AND `active`="1" AND `time`<"'.$start_point.'"'); + + if(!$sql->num($admins)) + continue; + + $cmd = 'cd /servers/'.$server['uid'].';'; + + while($admin = $sql->get($admins)) + { + $cmd .= 'sed -i -e \'s/'.escapeshellcmd(htmlspecialchars_decode($admin['text'])).'//g\' '.cron::$admins_file[$game].';'; + + $sql->query('UPDATE `admins_'.$game.'` set `active`="0" WHERE `id`="'.$admin['id'].'" LIMIT 1'); + } + + $cmd .= 'sed -i '."'/./!d'".' '.cron::$admins_file[$game].'; echo -e "\n" >> '.cron::$admins_file[$game].';'; + $cmd .= 'chown server'.$server['uid'].':1000 '.cron::$admins_file[$game]; + + $ssh->set($cmd); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_scan_servers_copy.php b/system/library/cron/control_scan_servers_copy.php new file mode 100644 index 0000000..9a643e3 --- /dev/null +++ b/system/library/cron/control_scan_servers_copy.php @@ -0,0 +1,53 @@ +query('SELECT `address` FROM `control` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `control_servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $copys = $sql->query('SELECT `id` FROM `control_copy` WHERE `status`="0"'); + while($copy = $sql->get($copys)) + { + $sql->query('SELECT `uid` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!sys::int($ssh->get('ps aux | grep copy_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_copy` set `status`="1" WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_scan_servers_down.php b/system/library/cron/control_scan_servers_down.php new file mode 100644 index 0000000..6cdd074 --- /dev/null +++ b/system/library/cron/control_scan_servers_down.php @@ -0,0 +1,62 @@ +query('SELECT `address` FROM `control` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + if(!array_key_exists($game, cron::$quakestat)) + return NULL; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `control_servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `ram` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid`, `address`, `status`, `autorestart` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$server['autorestart']) + continue; + + if($server['status'] != 'working') + continue; + + if(!in_array(trim($ssh->get('quakestat -'.(cron::$quakestat[$game]).' '.$server['address'].' -retry 5 -interval 2 | grep -v frags | tail -1 | awk \'{print $2}\'')), array('DOWN', 'no'))) + continue; + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' control_server_action restart '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="[Контроль] Перезагрука сервера: сервер завис", `time`="'.$start_point.'"'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_scan_servers_route.php b/system/library/cron/control_scan_servers_route.php new file mode 100644 index 0000000..2822cfa --- /dev/null +++ b/system/library/cron/control_scan_servers_route.php @@ -0,0 +1,104 @@ +query('SELECT `address` FROM `control` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `control_servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + $first = $ssh->get('cat /proc/stat'); + + sleep(1); + + $aCpu = sys::cpu_idle(array($first, $ssh->get('cat /proc/stat')), $unit['fcpu'], true); + + array_shift($aCpu); + + $idle = array(); + $uses = array(); + + foreach($aCpu as $cpu => $data) + { + $core = sys::int($cpu)+1; + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$server['unit'].'" AND `core_fix`="'.$core.'" AND `core_fix`="1" LIMIT 1'); + if($sql->num()) + { + unset($aCpu[$cpu]); + + continue; + } + + if($data['idle'] > 50) + $idle[$core] = $data['idle']; + else + $uses[$core] = 100-$data['idle']; + } + + if(!count($idle)) + return NULL; + + foreach($uses as $use_core => $use) + { + if(!count($idle)) + break; + + $sql->query('SELECT `id`, `uid` FROM `control_servers` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$game.'" AND `core_use`="'.$use_core.'" AND `status`="working" AND `core_fix`="0" ORDER BY `slots_start` DESC, `online` DESC LIMIT 3'); + if($sql->num() > 1) + { + $server = $sql->get(); + + $core = array_search(max($idle), $idle); + + $aPid = explode("\n", $ssh->get('ps aux | grep -v grep | grep '.$server['uid'].' | awk \'{print $2}\'')); + + if(count($aPid) < 2) + continue; + + array_pop($aPid); + + $taskset = ''; + + foreach($aPid as $pid) + $taskset .= 'taskset -cp '.($core-1).' '.$pid.';'; + + $ssh->set($taskset); + + unset($idle[$core]); + + $sql->query('UPDATE `control_servers` set `core_use`="'.$core.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_server_action.php b/system/library/cron/control_server_action.php new file mode 100644 index 0000000..4582fdc --- /dev/null +++ b/system/library/cron/control_server_action.php @@ -0,0 +1,55 @@ +get($nmch)) + return NULL; + + $mcache->set($nmch, true, false, 10); + + if($argv[3] == 'console') + { + global $sql; + + $sql->query('SELECT `uid`, `unit` FROM `control_servers` WHERE `id`="'.$argv[5].'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + $sql->query('SELECT `commands` FROM `control_crontab` WHERE `id`="'.$argv[6].'" LIMIT 1'); + $cron = $sql->get(); + + $aCmd = explode("\n", base64_decode($cron['commands'])); + + foreach($aCmd as $cmd) + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.sys::cmd($cmd).'"\015\'; sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + return NULL; + } + + include(LIB.'control/'.$argv[4].'/action.php'); + + if($argv[3] == 'restart') + action::start($argv[5], 'restart'); + else + action::$argv[3]($argv[5]); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_server_cron.php b/system/library/cron/control_server_cron.php new file mode 100644 index 0000000..89aa18a --- /dev/null +++ b/system/library/cron/control_server_cron.php @@ -0,0 +1,24 @@ +query('SELECT `game` FROM `control_servers` WHERE `id`="'.$argv[3].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `task` FROM `control_crontab` WHERE `id`="'.$argv[4].'" LIMIT 1'); + $cron = $sql->get(); + + $cmd = $cron['task'] == 'console' ? ' '.$argv[4] : ''; + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' control_server_action '.$cron['task'].' '.$server['game'].' '.$argv[3].$cmd.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/control_server_scan.php b/system/library/cron/control_server_scan.php new file mode 100644 index 0000000..9dd6439 --- /dev/null +++ b/system/library/cron/control_server_scan.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/system/library/cron/control_threads.php b/system/library/cron/control_threads.php new file mode 100644 index 0000000..24fce18 --- /dev/null +++ b/system/library/cron/control_threads.php @@ -0,0 +1,63 @@ +query('SELECT `id` FROM `control` ORDER BY `id` ASC'); + + if(!$sql->num()) + return NULL; + + while($unit = $sql->get()) + $aUnit[$unit['id']] = ''; + + $sql->query('SELECT `id` FROM `control_servers` LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $sql->query('SELECT `id`, `unit`, `game` FROM `control_servers` ORDER BY `unit` DESC'); + + $all = $sql->num(); + + while($server = $sql->get()) + $aUnit[$server['unit']][$server['game']] .= $server['id'].' '; + + if($argv[3] == 'control_scan_servers_route') + cron::$seping = 50; + + foreach($aUnit as $unit => $aGame) + { + foreach($aGame as $game => $servers) + { + $aData = explode(' ', $servers); + + $num = count($aData)-1; + $sep = $num > 0 ? ceil($num/cron::$seping) : 1; + + unset($aData[end($aData)]); + + $threads[] = cron::thread($sep, $game.' '.$unit, $aData); + } + } + + $cmd = ''; + + foreach($threads as $thread) + { + foreach($thread as $screen => $servers) + $cmd .= 'sudo -u www-data screen -dmS scan_'.(sys::first(explode(' ', $servers))).'_'.$screen.' taskset -c '.$cfg['cron_taskset'].' sh -c \"cd /var/enginegp; php cron.php '.$cfg['cron_key'].' '.$argv[3].' '.$servers.'\"; sleep 1;'; + } + + exec('screen -dmS control_threads_'.date('His', $start_point).' sh -c "'.$cmd.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/graph_servers_day.php b/system/library/cron/graph_servers_day.php new file mode 100644 index 0000000..edf1fe6 --- /dev/null +++ b/system/library/cron/graph_servers_day.php @@ -0,0 +1,50 @@ +query('SELECT `id`, `date` FROM `servers` ORDER BY `id` ASC'); + + while($server = $sql->get($servers)) + { + if($server['date']+86400 > $start_point) + continue; + + $aGraph = array('online' => 0, 'cpu' => 0, 'ram' => 0, 'hdd' => 0, 'time' => 0); + + $sql->query('SELECT `online`, `cpu`, `ram`, `hdd` FROM `graph_hour` WHERE `server`="'.$server['id'].'" AND `time`>"'.($start_point-86400).'" ORDER BY `id` DESC LIMIT 24'); + + $n = $sql->num(); + + if(!$n) + continue; + + while($graph = $sql->get()) + { + $aGraph['online'] += $graph['online']; + $aGraph['cpu'] += $graph['cpu']; + $aGraph['ram'] += $graph['ram']; + $aGraph['hdd'] += $graph['hdd']; + } + + $aGraph['online'] = $aGraph['online']/$n; + $aGraph['cpu'] = $aGraph['cpu']/$n; + $aGraph['ram'] = $aGraph['ram']/$n; + $aGraph['hdd'] = $aGraph['hdd']/$n; + + $sql->query('INSERT INTO `graph_day` set `server`="'.$server['id'].'",' + .'`online`="'.$aGraph['online'].'",' + .'`cpu`="'.$aGraph['cpu'].'",' + .'`ram`="'.$aGraph['ram'].'",' + .'`hdd`="'.$aGraph['hdd'].'", `time`="'.$start_point.'"'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/graph_servers_hour.php b/system/library/cron/graph_servers_hour.php new file mode 100644 index 0000000..06cc145 --- /dev/null +++ b/system/library/cron/graph_servers_hour.php @@ -0,0 +1,28 @@ +query('SELECT `id`, `online`, `ram_use`, `cpu_use`, `hdd_use`, `date` FROM `servers` ORDER BY `id` ASC'); + + while($server = $sql->get($servers)) + { + if($server['date']+3600 > $start_point) + continue; + + $sql->query('INSERT INTO `graph_hour` set `server`="'.$server['id'].'",' + .'`online`="'.$server['online'].'",' + .'`cpu`="'.$server['cpu_use'].'",' + .'`ram`="'.$server['ram_use'].'",' + .'`hdd`="'.$server['hdd_use'].'", `time`="'.$start_point.'"'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/notice_help.php b/system/library/cron/notice_help.php new file mode 100644 index 0000000..6b5065f --- /dev/null +++ b/system/library/cron/notice_help.php @@ -0,0 +1,32 @@ +query('SELECT `id`, `user`, `time` FROM `help` WHERE `status`="0" AND `time`<"'.$time.'" AND `notice`="0" AND `close`="0"'); + while($help = $sql->get($helps)) + { + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$help['user'].'" AND `time`<"'.$help['time'].'" AND `notice_help`="1" LIMIT 1'); + + if(!$sql->num()) + continue; + + $user = $sql->get(); + + if(!sys::mail('Техническая поддержка', sys::updtext(sys::text('mail', 'notice_help'), array('site' => $cfg['name'], 'url' => $cfg['http'].'help/section/dialog/id/'.$help['id'])), $user['mail'])) + continue; + + $sql->query('UPDATE `help` set `notice`="1" WHERE `id`="'.$help['id'].'" LIMIT 1'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/notice_help_admin.php b/system/library/cron/notice_help_admin.php new file mode 100644 index 0000000..26e391c --- /dev/null +++ b/system/library/cron/notice_help_admin.php @@ -0,0 +1,37 @@ +query('SELECT `id`, `time`, `notice_admin` FROM `help` WHERE (`notice_admin`="0" OR `notice_admin`="2") AND `close`="0" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $help = $sql->get(); + + foreach($cfg['notice_admin'] as $id) + { + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$id.'" LIMIT 1'); + $admin = $sql->get(); + + if($help['notice_admin'] != 2) + { + if(!sys::mail('Техническая поддержка', sys::updtext(sys::text('mail', 'notice_help_admin_new'), array('url' => $cfg['http'].'help/section/dialog/id/'.$help['id'])), $admin['mail'])) + continue; + }else{ + if(!sys::mail('Техническая поддержка', sys::updtext(sys::text('mail', 'notice_help_admin'), array('url' => $cfg['http'].'help/section/dialog/id/'.$help['id'])), $admin['mail'])) + continue; + } + } + + $sql->query('UPDATE `help` set `notice_admin`="1" WHERE `id`="'.$help['id'].'" LIMIT 1'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/notice_server_overdue.php b/system/library/cron/notice_server_overdue.php new file mode 100644 index 0000000..ca3e4c0 --- /dev/null +++ b/system/library/cron/notice_server_overdue.php @@ -0,0 +1,30 @@ +query('SELECT `id`, `user`, `address` FROM `servers` WHERE `time`<"'.$start_point.'" AND `mail`="0"'); + while($server = $sql->get($servers)) + { + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + $user = $sql->get(); + + if(!sys::mail('Аренда сервера', sys::updtext(sys::text('mail', 'notice_server_overdue'), array('site' => $cfg['name'], 'id' => $server['id'], 'address' => $server['address'])), $user['mail'])) + continue; + + $sql->query('UPDATE `servers` set `mail`="1" WHERE `id`="'.$server['id'].'" LIMIT 1'); + } + + $servers = $sql->query('SELECT `id` FROM `servers` WHERE `time`>"'.$start_point.'" AND `mail`="1"'); + while($server = $sql->get($servers)) + $sql->query('UPDATE `servers` set `mail`="0" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/preparing_web_delete.php b/system/library/cron/preparing_web_delete.php new file mode 100644 index 0000000..73e240f --- /dev/null +++ b/system/library/cron/preparing_web_delete.php @@ -0,0 +1,18 @@ +query('SELECT `id` FROM `web` WHERE `user`="0"'); + while($web = $sql->get()) + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' web_delete '.$web['id'].'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/privileges.php b/system/library/cron/privileges.php new file mode 100644 index 0000000..df716cc --- /dev/null +++ b/system/library/cron/privileges.php @@ -0,0 +1,99 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return ': UNIT#'.$servers[4].' .'; + + $unit = $sql->get(); + + unset($servers[3], $servers[4]); + + foreach($servers as $i => $id) + { + $sql->query('SELECT `id` FROM `privileges_buy` WHERE `server`="'.$id.'" AND `status`="1" LIMIT 1'); + if(!$sql->num()) + unset($servers[$i]); + } + + if(!count($servers)) + return NULL; + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.end($servers).'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // ssh + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return ': UNIT#'.$server['unit'].' .'; + + $time = $start_point-172800; + + foreach($servers as $id) + { + $sql->query('DELETE FROM `privileges_buy` WHERE `date`<"'.$time.'" AND status`="0" LIMIT 5'); + + $aMail = array(); + + $sql->query('SELECT `uid`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $file = $tarif['install'].$server['uid'].'/'.cron::$admins_file[$game]; + + $text = $ssh->get('cat '.$file); + + $privileges = $sql->query('SELECT `id`, `text`, `sql`, `mail` FROM `privileges_buy` WHERE `server`="'.$id.'" AND `status`="1" LIMIT 3'); + while($privilege = $sql->get($privileges)) + { + $text .= base64_decode($privilege['text']).PHP_EOL; + + $sql->query(base64_decode($privilege['sql'])); + $sql->query('DELETE FROM `privileges_buy` WHERE `id`="'.$privilege['id'].'" LIMIT 1'); + + $aMail[] = $privilege['mail']; + } + + $temp = sys::temp($text); + + $ssh->setfile($temp, $file, 0644); + + unlink($temp); + + $cmd = $game == 'cs' ? 'amx_reloadadmins' : 'sm_reloadadmins'; + + $ssh->set('chown server'.$server['uid'].':servers '.$file); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"".$cmd."\"\015'"); + + foreach($aMail as $mail) + sys::mail(' ', sys::text('mail', 'success_privilege'), $mail); + + echo 'server#'.$id.' ('.$game.') -> add privileges '.PHP_EOL; + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_control.php b/system/library/cron/scan_control.php new file mode 100644 index 0000000..583a21c --- /dev/null +++ b/system/library/cron/scan_control.php @@ -0,0 +1,21 @@ +query('SELECT `id` FROM `control` ORDER BY `id` ASC'); + while($ctrl = $sql->get()) + ctrl::update_status($ctrl['id'], $ssh); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers.php b/system/library/cron/scan_servers.php new file mode 100644 index 0000000..3836246 --- /dev/null +++ b/system/library/cron/scan_servers.php @@ -0,0 +1,145 @@ +query('SELECT `address`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `user`, `uid`, `address`, `status`, `time`, `overdue`, `ftp`, `stop`, `block` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Если аренда не закончилась, а сервер просрочен + if($server['time'] > $start_point && $server['status'] == 'overdue') + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + continue; + } + + // Если аренда закончилась, а сервер не просрочен (и не заблокирован) + if($server['time'] < $start_point && !in_array($server['status'], array('overdue', 'blocked'))) + { + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + if($server['ftp']) + $ssh->set("mysql -P ".$unit['sql_port']." -u".$unit['sql_login']." -p".$unit['sql_passwd']." --database ".$unit['sql_ftp']." -e \"DELETE FROM ftp WHERE user='".$server['uid']."'\""); + + $sql->query('UPDATE `servers` set `status`="overdue", `online`="0", `players`="", `ftp`="0", `overdue`="'.$start_point.'" WHERE `id`="'.$id.'" LIMIT 1'); + + continue; + } + + // Если аренда закончилась и сервер просрочен длительное время или поставлен на удаление + if($server['user'] == -1 || ($server['time'] < $start_point && ($server['overdue']+$cfg['server_delete']*86400) < $start_point)) + { + if($server['user'] != -1) + $sql->query('UPDATE `servers` set `user`="-1" WHERE `id`="'.$id.'" LIMIT 1'); + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_delete '.$id.'"'); + + continue; + } + + switch($server['status']) + { + case 'working': case 'change': case 'start': case 'restart': + if(!sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off", `online`="0", `players`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запуск сервера (если он был выключен не через панель) + if($server['stop']) + { + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action start '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Включение сервера: сервер выключен не через панель", `time`="'.$start_point.'"'); + } + }else + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_scan '.$game.' '.$id.'"'); + + break; + + case 'off': + if(sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `servers` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + else{ + // Запуск сервера (если он был выключен не через панель) + if($server['stop']) + { + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action start '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Включение сервера: сервер выключен не через панель", `time`="'.$start_point.'"'); + + continue; + } + } + + break; + + case 'reinstall': + if(!sys::int($ssh->get('ps aux | grep r_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'update': + if(!sys::int($ssh->get('ps aux | grep u_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'install': + if(!sys::int($ssh->get('ps aux | grep i_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'recovery': + if(!sys::int($ssh->get('ps aux | grep rec_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + break; + + case 'blocked': + if($server['block'] < $start_point) + $sql->query('UPDATE `servers` set `status`="off", `block`="0" WHERE `id`="'.$id.'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_admins.php b/system/library/cron/scan_servers_admins.php new file mode 100644 index 0000000..7034e07 --- /dev/null +++ b/system/library/cron/scan_servers_admins.php @@ -0,0 +1,71 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $admins = $sql->query('SELECT `id`, `text` FROM `admins_'.$game.'` WHERE `server`="'.$id.'" AND `active`="1" AND `time`<"'.$start_point.'"'); + + if(!$sql->num($admins)) + continue; + + $cmd = 'cd '.$tarif['install'].$server['uid'].';'; + + while($admin = $sql->get($admins)) + { + $cmd .= 'sed -i -e \'s/'.escapeshellcmd(htmlspecialchars_decode($admin['text'])).'//g\' '.cron::$admins_file[$game].';'; + + $sql->query('UPDATE `admins_'.$game.'` set `active`="0" WHERE `id`="'.$admin['id'].'" LIMIT 1'); + } + + $cmd .= 'sed -i '."'/./!d'".' '.cron::$admins_file[$game].'; echo -e "\n" >> '.cron::$admins_file[$game].';'; + $cmd .= 'chown server'.$server['uid'].':1000 '.cron::$admins_file[$game]; + + $ssh->set($cmd); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_copy.php b/system/library/cron/scan_servers_copy.php new file mode 100644 index 0000000..f7259a7 --- /dev/null +++ b/system/library/cron/scan_servers_copy.php @@ -0,0 +1,53 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $copys = $sql->query('SELECT `id` FROM `copy` WHERE `status`="0"'); + while($copy = $sql->get($copys)) + { + $sql->query('SELECT `uid` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!sys::int($ssh->get('ps aux | grep copy_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `copy` set `status`="1" WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_down.php b/system/library/cron/scan_servers_down.php new file mode 100644 index 0000000..043956c --- /dev/null +++ b/system/library/cron/scan_servers_down.php @@ -0,0 +1,62 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + if(!array_key_exists($game, cron::$quakestat)) + return NULL; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `ram` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid`, `address`, `status`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$server['autorestart']) + continue; + + if($server['status'] != 'working') + continue; + + if(!in_array(trim($ssh->get('quakestat -'.(cron::$quakestat[$game]).' '.$server['address'].' -retry 5 -interval 2 | grep -v frags | tail -1 | awk \'{print $2}\'')), array('DOWN', 'no'))) + continue; + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action restart '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Перезагрука сервера: сервер завис", `time`="'.$start_point.'"'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_load.php b/system/library/cron/scan_servers_load.php new file mode 100644 index 0000000..a58e925 --- /dev/null +++ b/system/library/cron/scan_servers_load.php @@ -0,0 +1,96 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `ram` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + foreach($servers as $id) + { + $sql->query('SELECT `uid`, `slots`, `hdd`, `ram`, `ram_use_max`, `cpu_use_max`, `core_fix`, `core_fix_one` `status` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if($server['core_fix'] AND $server['core_fix_one']) + continue; + + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + echo 'server#'.$id.' ('.$game.') -> load average: cpu = 0% / ram = 0% (no working)'.PHP_EOL; + + continue; + } + + $resources = array(); + + for($n = 0; $n <= 2; $n+=1) + { + $cr = explode('|', $ssh->get('top -u '.$server['uid'].' -b -n 1 | grep '.(cron::$process[$game]).' | awk \'{print $9"|"$10}\'')); + + $resources[$n]['cpu'] = isset($cr[0]) ? round(str_replace(',', '.', $cr[0])) : 0; + + $resources[$n]['ram'] = isset($cr[1]) ? str_replace(',', '.', $cr[1]) : 0; + $ram = $server['ram'] ? $server['ram'] : $server['slots']*$cfg['ram'][$game]; + $resources[$n]['ram'] = round($unit['ram']/100*$resources[$n]['ram']/($ram/100)); + + sleep(1); + } + + $loads = array(); + + foreach($resources as $n => $load) + { + foreach($load as $type => $val) + $loads[$type] += $val; + } + + $average_cpu = isset($loads['cpu']) ? $loads['cpu']/2 : 0; + $average_ram = isset($loads['ram']) ? $loads['ram']/2 : 0; + + $max_cpu = $server['cpu_use_max'] ? $server['cpu_use_max'] : $cfg['cpu_use_max'][$game]; + $max_ram = $server['ram_use_max'] ? $server['ram_use_max'] : $cfg['ram_use_max'][$game]; + + if($average_cpu > $max_cpu) + { + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action restart '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Перезагрука сервера: OVERLOAD^cpu = '.$average_cpu.'%", `time`="'.$start_point.'"'); + }elseif($average_ram > $max_ram){ + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action restart '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Перезагрука сервера: OVERLOAD^ram = '.$average_ram.'%", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_route.php b/system/library/cron/scan_servers_route.php new file mode 100644 index 0000000..0c830e6 --- /dev/null +++ b/system/library/cron/scan_servers_route.php @@ -0,0 +1,104 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `ram` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + $first = $ssh->get('cat /proc/stat'); + + sleep(1); + + $aCpu = sys::cpu_idle(array($first, $ssh->get('cat /proc/stat')), false, true); + + array_shift($aCpu); + + $idle = array(); + $uses = array(); + + foreach($aCpu as $cpu => $data) + { + $core = sys::int($cpu)+1; + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `core_fix`="'.$core.'" AND `core_fix`="1" LIMIT 1'); + if($sql->num()) + { + unset($aCpu[$cpu]); + + continue; + } + + if($data['idle'] > 50) + $idle[$core] = $data['idle']; + else + $uses[$core] = 100-$data['idle']; + } + + if(!count($idle)) + return NULL; + + foreach($uses as $use_core => $use) + { + if(!count($idle)) + break; + + $sql->query('SELECT `id`, `uid` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$game.'" AND `core_use`="'.$use_core.'" AND `status`="working" AND `core_fix`="0" ORDER BY `slots_start` DESC, `online` DESC LIMIT 3'); + if($sql->num() > 1) + { + $server = $sql->get(); + + $core = array_search(max($idle), $idle); + + $aPid = explode("\n", $ssh->get('ps aux | grep -v grep | grep '.$server['uid'].' | awk \'{print $2}\'')); + + if(count($aPid) < 2) + continue; + + array_pop($aPid); + + $taskset = ''; + + foreach($aPid as $pid) + $taskset .= 'taskset -cp '.($core-1).' '.$pid.';'; + + $ssh->set($taskset); + + unset($idle[$core]); + + $sql->query('UPDATE `servers` set `core_use`="'.$core.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/scan_servers_stop.php b/system/library/cron/scan_servers_stop.php new file mode 100644 index 0000000..89b68c2 --- /dev/null +++ b/system/library/cron/scan_servers_stop.php @@ -0,0 +1,57 @@ +query('SELECT `address` FROM `units` WHERE `id`="'.$servers[4].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $unit = $sql->get(); + + $game = $servers[3]; + + unset($servers[3], $servers[4]); + + $sql->query('SELECT `unit` FROM `servers` WHERE `id`="'.$servers[5].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + $autostop = $start_point-$cfg['autostop']*60; + $teststop = $start_point-$cfg['teststop']*60; + + $sqlq = '(`test`="1" AND `time_start`<"'.$teststop.'" OR `autostop`="1" AND `time_start`<"'.$autostop.'")'; + + foreach($servers as $id) + { + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `status`="working" AND `online`="0" AND '.$sqlq.' LIMIT 1'); + + if(!$sql->num()) + continue; + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action stop '.$game.' '.$id.'"'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$id.'", `text`="Выключение сервера: на сервере нет игроков", `time`="'.$start_point.'"'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/server_action.php b/system/library/cron/server_action.php new file mode 100644 index 0000000..325aa71 --- /dev/null +++ b/system/library/cron/server_action.php @@ -0,0 +1,55 @@ +get($nmch)) + return NULL; + + $mcache->set($nmch, true, false, 10); + + if($argv[3] == 'console') + { + global $sql; + + $sql->query('SELECT `uid`, `unit` FROM `servers` WHERE `id`="'.$argv[5].'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + $sql->query('SELECT `commands` FROM `crontab` WHERE `id`="'.$argv[6].'" LIMIT 1'); + $cron = $sql->get(); + + $aCmd = explode("\n", base64_decode($cron['commands'])); + + foreach($aCmd as $cmd) + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.sys::cmd($cmd).'"\015\'; sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + return NULL; + } + + include(LIB.'games/'.$argv[4].'/action.php'); + + if($argv[3] == 'restart') + action::start($argv[5], 'restart'); + else + action::$argv[3]($argv[5]); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/server_cron.php b/system/library/cron/server_cron.php new file mode 100644 index 0000000..5825e83 --- /dev/null +++ b/system/library/cron/server_cron.php @@ -0,0 +1,24 @@ +query('SELECT `game` FROM `servers` WHERE `id`="'.$argv[3].'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `task` FROM `crontab` WHERE `id`="'.$argv[4].'" LIMIT 1'); + $cron = $sql->get(); + + $cmd = $cron['task'] == 'console' ? ' '.$argv[4] : ''; + + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action '.$cron['task'].' '.$server['game'].' '.$argv[3].$cmd.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/server_delete.php b/system/library/cron/server_delete.php new file mode 100644 index 0000000..fdac0c4 --- /dev/null +++ b/system/library/cron/server_delete.php @@ -0,0 +1,148 @@ +query('SELECT `id`, `uid`, `user`, `unit`, `tarif`, `game`, `slots`, `address`, `ddos` FROM `servers` WHERE `id`="'.$argv[3].'" AND `user`="-1" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $server = $sql->get(); + + if(!$server['uid']) + return NULL; + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return NULL; + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@:'.$server['address'].' | awk '."'{print $2}'".' | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + $copys = 'screen -dmS r_copy_'.$server['uid'].' sh -c "'; + + $scopy = $sql->query('SELECT `id`, `name` FROM `copy` WHERE `server`="'.$server['id'].'"'); + while($copy = $sql->get($scopy)) + { + $copys .= 'rm /copy/'.$copy['name'].'.tar;'; + + $sql->query('DELETE FROM `copy` WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + + $copys .= '";'; + + $ssh->set($copys // Удаление резервных копий + .'screen -dmS r_'.$server['uid'].' sh -c "rm -r '.$install.';' // Удаление директории сервера + .'userdel server'.$server['uid'].'"'); // Удаление пользователя сервера c локации + + // Удаление ftp доступа + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';' + .'DELETE FROM quotalimits WHERE name=\''.$server['uid'].'\';' + .'DELETE FROM quotatallies WHERE name=\''.$server['uid'].'\''; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + include(LIB.'games/games.php'); + + // Очистка правил FireWall + games::iptables($server['id'], 'remove', NULL, NULL, NULL, false, $ssh); + + // Очистка правил FireWall GEO + if($server['ddos']) + { + $geo = $cfg['iptables'].'_geo'; + + $country = $server['ddos'] == 2 ? 'AM,BY,UA,RU,KZ' : 'UA,RU'; + + $ssh->set('iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country '.$country.' -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'); + } + + // Удаление заданий из crontab + $sql->query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + return NULL; + + $crons = $sql->query('SELECT `id`, `cron` FROM `crontab` WHERE `server`="'.$server['id'].'"'); + while($cron = $sql->get($crons)) + { + $ssh->set('echo "" >> /etc/crontab && cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab"); + $ssh->set('crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `crontab` WHERE `id`="'.$cron['id'].'" LIMIT 1'); + } + + // Обновление данных выделенного адреса + $sql->query('SELECT `id`, `aid` FROM `address_buy` WHERE `server`="'.$server['id'].'" LIMIT 1'); + if($sql->num()) + { + $add = $sql->get(); + + $sql->query('UPDATE `address` set `buy`="0" WHERE `id`="'.$add['aid'].'" LIMIT 1'); + $sql->query('DELETE FROM `address_buy` WHERE `id`="'.$add['id'].'" LIMIT 1'); + } + + include(DATA.'web.php'); + + $sql->query('SELECT `id` FROM `servers` WHERE `id`!="'.$server['id'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + if($sql->num()) + { + $server_sec = $sql->get(); + + // Подготовка к удалению доп. услуги или обновление данных + $webs = $sql->query('SELECT `id`, `type` FROM `web` WHERE `server`="'.$server['id'].'"'); + while($web = $sql->get($webs)) + { + if($aWebInstall[$server['game']][$web['type']] == ('unit' || 'user')) + $sql->query('UPDATE `web` set `server`="'.$server_sec['id'].'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + else + $sql->query('UPDATE `web` set `user`="0" WHERE `id`="'.$web['id'].'" LIMIT 1'); + } + }else + $sql->query('UPDATE `web` set `user`="0" WHERE `server`="'.$server['id'].'"'); + + // Удаление различной информации игрового сервера + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `owners` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `graph` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `graph_day` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `graph_hour` WHERE `server`="'.$server['id'].'"'); + $sql->query('DELETE FROM `servers` WHERE `id`="'.$server['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs_sys` set `user`="0", `server`="'.$argv[3].'", `text`="Удаление игрового сервера #'.$argv[3].' ('.$server['game'].') unit: #'.$server['unit'].', tarif: #'.$server['tarif'].', slots: #'.$server['slots'].'", `time`="'.$start_point.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/server_scan.php b/system/library/cron/server_scan.php new file mode 100644 index 0000000..d00e14c --- /dev/null +++ b/system/library/cron/server_scan.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/system/library/cron/threads.php b/system/library/cron/threads.php new file mode 100644 index 0000000..e656b66 --- /dev/null +++ b/system/library/cron/threads.php @@ -0,0 +1,63 @@ +query('SELECT `id` FROM `units` ORDER BY `id` ASC'); + + if(!$sql->num()) + return NULL; + + while($unit = $sql->get()) + $aUnit[$unit['id']] = ''; + + $sql->query('SELECT `id` FROM `servers` LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $sql->query('SELECT `id`, `unit`, `game` FROM `servers` ORDER BY `unit` DESC'); + + $all = $sql->num(); + + while($server = $sql->get()) + $aUnit[$server['unit']][$server['game']] .= $server['id'].' '; + + if($argv[3] == 'scan_servers_route') + cron::$seping = 50; + + foreach($aUnit as $unit => $aGame) + { + foreach($aGame as $game => $servers) + { + $aData = explode(' ', $servers); + + $num = count($aData)-1; + $sep = $num > 0 ? ceil($num/cron::$seping) : 1; + + unset($aData[end($aData)]); + + $threads[] = cron::thread($sep, $game.' '.$unit, $aData); + } + } + + $cmd = ''; + + foreach($threads as $thread) + { + foreach($thread as $screen => $servers) + $cmd .= 'sudo -u www-data screen -dmS scan_'.(sys::first(explode(' ', $servers))).'_'.$screen.' taskset -c '.$cfg['cron_taskset'].' sh -c \"cd /var/enginegp; php cron.php '.$cfg['cron_key'].' '.$argv[3].' '.$servers.'\"; sleep 1;'; + } + + exec('screen -dmS threads_'.date('His', $start_point).' sh -c "'.$cmd.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/update_address.php b/system/library/cron/update_address.php new file mode 100644 index 0000000..7d8366b --- /dev/null +++ b/system/library/cron/update_address.php @@ -0,0 +1,44 @@ +query('SELECT `id`, `aid`, `server` FROM `address_buy` WHERE `time`<"'.$start_point.'"'); + + while($add_buy = $sql->get($add_buys)) + { + $sql->query('SELECT `unit`, `port`, `game`, `status` FROM `servers` WHERE `id`="'.$add_buy['server'].'" LIMIT 1'); + if($sql->num()) + { + $server = $sql->get(); + + if(!$cfg['buy_address'][$server['game']]) + continue; + + $sql->query('SELECT `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Очистка правил FireWall + games::iptables($add_buy['server'], 'remove', NULL, NULL, $server['unit'], false); + + $sql->query('UPDATE `servers` set `address`="'.(sys::first(explode(':', $unit['address']))).':'.$server['port'].'" WHERE `id`="'.$add_buy['server'].'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + exec('sh -c "cd /var/enginegp; php cron.php '.$cfg['cron_key'].' server_action restart '.$server['game'].' '.$add_buy['server'].'"'); + } + + $sql->query('UPDATE `address` set `buy`="0" WHERE `id`="'.$add_buy['aid'].'" LIMIT 1'); + $sql->query('DELETE FROM `address_buy` WHERE `id`="'.$add_buy['id'].'" LIMIT 1'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/users_recovery_signup.php b/system/library/cron/users_recovery_signup.php new file mode 100644 index 0000000..bc29f13 --- /dev/null +++ b/system/library/cron/users_recovery_signup.php @@ -0,0 +1,19 @@ +query('DELETE FROM `signup` WHERE `date`<"'.$time.'"'); + $sql->query('DELETE FROM `recovery` WHERE `date`<"'.$time.'"'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/cron/web_delete.php b/system/library/cron/web_delete.php new file mode 100644 index 0000000..d2386f9 --- /dev/null +++ b/system/library/cron/web_delete.php @@ -0,0 +1,36 @@ +query('SELECT `id`, `login`, `type`, `server`, `unit` FROM `web` WHERE `id`="'.$argv[3].'" LIMIT 1'); + $web = $sql->get(); + + if($web['type'] == 'hosting') + { + include(DATA.'web.php'); + + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['account']['delete'], array('login' => $web['login']))), true); + + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + continue; + + $sql->query('DELETE FROM `web` WHERE `id`="'.$web['id'].'" LIMIT 1'); + } + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $web['type'], + 'server' => array('id' => $web['server'], 'unit' => $web['unit'], 'user' => 0, 'game' => 'system') + ); + + web::delete($aData, false); + } + } +?> \ No newline at end of file diff --git a/system/library/ftp.php b/system/library/ftp.php new file mode 100644 index 0000000..2778dac --- /dev/null +++ b/system/library/ftp.php @@ -0,0 +1,516 @@ + 'Понедельник', + 'Tue' => 'Вторник', + 'Wed' => 'Среда', + 'Thu' => 'Четверг', + 'Fri' => 'Пятница', + 'Sat' => 'Суббота', + 'Sun' => 'Воскресенье' + ); + + var $mounthint = array( + 'Jan' => '01', + 'Feb' => '02', + 'Mar' => '03', + 'Apr' => '04', + 'May' => '05', + 'Jun' => '06', + 'Jul' => '07', + 'Aug' => '08', + 'Sep' => '09', + 'Oct' => '10', + 'Nov' => '11', + 'Dec' => '12' + ); + + var $mounthru = array( + 'Jan' => 'Янв', + 'Feb' => 'Фев', + 'Mar' => 'Мар', + 'Apr' => 'Апр', + 'May' => 'Май', + 'Jun' => 'Июн', + 'Jul' => 'Июл', + 'Aug' => 'Авг', + 'Sep' => 'Сен', + 'Oct' => 'Окт', + 'Nov' => 'Ноя', + 'Dec' => 'Дек' + ); + + var $aEdits = array( + 'txt', + 'cfg', + 'conf', + 'json', + 'xml', + 'ini', + 'gam', + 'php', + 'html', + 'inf', + 'js', + 'css', + 'sma', + 'log' + ); + + public function auth($host, $user, $password, $port = 21) + { + $ftp_connect = @ftp_connect($host, $port); + + if(!$ftp_connect) + return false; + + if(!@ftp_login($ftp_connect, $user, $password)) + return false; + + @ftp_pasv($ftp_connect, true); + + $this->steck = $ftp_connect; + + return true; + } + + public function read($path) + { + $path = ($path == '') ? '/' : $path; + + $path = str_replace('//', '/', $path); + + $aDir = array(); + $aFile = array(); + $aInfo = array(); + + $rawlist = array(); + + $data = ftp_rawlist($this->steck, $path); + + if(is_array($data)) + foreach($data as $index) + { + $vinfo = preg_split('/[\s]+/', $index, 9); + + if($vinfo[0] !== 'total') + { + $aInfo['chmod'] = $vinfo[0]; + $aInfo['num'] = $vinfo[1]; + $aInfo['owner'] = $vinfo[2]; + $aInfo['group'] = $vinfo[3]; + $aInfo['size'] = $vinfo[4]; + $aInfo['month'] = $vinfo[5]; + $aInfo['day'] = $vinfo[6]; + $aInfo['time'] = $vinfo[7]; + $aInfo['name'] = $vinfo[8]; + + $rawlist[$aInfo['name']] = $aInfo; + } + } + + foreach($rawlist as $name => $data) + { + if($data['chmod']{0} == 'd') + $aDir[$name] = $data; + + elseif($data['chmod']{0} == '-') + $aFile[$name] = $data; + } + + $aData = array( + 'folder' => $aDir, + 'file' => $aFile, + 'path' => $path + ); + + return $aData; + } + + public function view($view, $server) + { + global $html; + + if($view['path'] != '/') + { + $html->get('filetp_back', 'sections/servers/games/filetp'); + + $html->set('back', $this->path($view['path'])); + + $html->pack('list'); + } + + foreach($view as $type => $aVal) + { + if(!is_array($aVal)) + continue; + + foreach($aVal as $name => $info) + { + $html->get('filetp_list', 'sections/servers/games/filetp'); + + $html->set('id', $server); + $html->set('name', $name); + + $path = $view['path']; + + if($path{0} != '/') $path = '/'.$path; + + if($path != '/') $path = $path.'/'; + + $html->set('path', $path); + $html->set('chmod', $this->cti($info['chmod']).' '.$info['chmod']); + $html->set('owner', $info['owner']); + $html->set('group', $info['group']); + + if($type == 'folder') + { + $html->unit('folder', 1); + $html->unit('file'); + $html->set('size', ''); + }else{ + $type = explode('.', $name); + + if(in_array(end($type), $this->aEdits)) + $html->unit('edit', 1); + else + $html->unit('edit'); + + $html->unit('file', 1); + $html->unit('folder'); + $html->set('size', sys::size($info['size'])); + } + + $html->set('month', $this->mounthru[$info['month']]); + $html->set('day', $info['day']); + $html->set('time', $info['time']); + + $html->pack('list'); + } + } + + return isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + public function mkdir($path, $folders) + { + if(!@ftp_chdir($this->steck, $path)) + sys::outjs(array('e' => 'Ошибка: не удалось создать папку')); + + $aFolder = explode('/', $folders); + + foreach($aFolder as $folder) + { + if($folder == '') + continue; + + if(!@ftp_chdir($this->steck, $folder)) + { + if(!@ftp_mkdir($this->steck, $folder)) + sys::outjs(array('e' => 'Ошибка: не удалось создать папку '.$folder)); + + @ftp_chdir($this->steck, $folder); + } + } + + sys::outjs(array('s' => 'ok')); + } + + public function touch($path, $file, $text) + { + $aData = explode('/', $file); + + $path_file = ''; + + if(count($aData)) + { + $file = end($aData); + + unset($aData[count($aData)-1]); + + foreach($aData as $val) + $path_file .= $val.'/'; + } + + $dir = str_replace('//', '', $path.'/'.$path_file); + + $dir = ($dir == '') ? '/' : $dir; + + if(!@ftp_chdir($this->steck, $dir)) + sys::outjs(array('e' => 'Ошибка: не удалось создать файл')); + + $temp = sys::temp($text); + + if(@ftp_put($this->steck, $file, $temp, FTP_BINARY)) + { + unlink($temp); + + sys::outjs(array('s' => 'ok')); + } + + unlink($temp); + + sys::outjs(array('e' => 'Ошибка: не удалось создать файл')); + } + + public function edit_file($path, $file) + { + $name = md5(time().$file.'ftp'); + + if(@ftp_get($this->steck, TEMP.$name, $path.'/'.$file, FTP_BINARY)) + { + $data = file_get_contents(TEMP.$name); + + unlink(TEMP.$name); + + sys::outjs(array('s' => $data)); + } + + sys::outjs(array('e' => 'Не удалось открыть файл')); + } + + public function rename($path, $oldname, $newname) + { + if(@ftp_rename($this->steck, $path.'/'.$oldname, $path.'/'.$newname)) + sys::outjs(array('s' => 'ok')); + + sys::outjs(array('e' => 'Не удалось сменить имя')); + } + + public function rmdir($path, $folder) + { + if(@ftp_rmdir($this->steck, $path.'/'.$folder)) + sys::outjs(array('s' => 'ok')); + + sys::outjs(array('e' => 'Ошибка: не удалось удалить папку.')); + } + + public function rmfile($file) + { + if(@ftp_delete($this->steck, $file)) + sys::outjs(array('s' => 'ok')); + + sys::outjs(array('e' => 'Ошибка: не удалось удалить файл')); + } + + public function chmod($path, $name, $chmod) + { + if(ftp_site($this->steck, 'CHMOD 0'.$chmod.' '.$path.'/'.$name)) + sys::outjs(array('s' => 'ok')); + + sys::outjs(array('e' => 'Ошибка: не удалось изменить права.')); + } + + public function search($str, $server) + { + global $html, $mcache; + + $nmch = md5($str.$server); + + $cache = $mcache->get($nmch); + + if(!is_array($cache)) + { + $aData = ftp_rawlist($this->steck, '/', true); + + if(!is_array($aData)) + sys::out('Ничего не найдено'); + + // Файлы + $aFile = array(); + + // Файлы в корне + $end = array_search('', $aData); + + for($i = 0; $i < $end; $i+=1) + { + $aInfo = preg_split('/[\s]+/', $aData[$i], 9); + + $info = ''; + + for($n = 0; $n < 8; $n+=1) + $info .= $aInfo[$n].' '; + + $aFile['/'][] = array('info' => $info, 'name' => $aInfo[8]); + } + + // Перебор директорий и файлов в них + foreach($aData as $index) + { + $begin = array_search('', $aData); + unset($aData[$begin]); + + $end = array_search('', $aData); + + if(!$begin) + break; + + $dir = substr($aData[$begin+1], 0, -1); + + for($i = $begin+2; $i < $end; $i+=1) + { + $aInfo = preg_split('/[\s]+/', $aData[$i], 9); + + $info = ''; + + for($n = 0; $n < 8; $n+=1) + $info .= $aInfo[$n].' '; + + $aFile[$dir][] = array('info' => $info, 'name' => $aInfo[8]); + } + } + + $mcache->set($nmch, $aFile, false, 20); + }else + $aFile = $cache; + + $aFind = array(); + + // Поиск + foreach($aFile as $dir => $files) + { + foreach($files as $file) + { + $find = sys::first(explode('.', $file['name'])); + + if(preg_match('/'.$str.'/i', $find)) + $aFind[] = array('dir' => $dir, 'info' => $file['info'], 'file' => $file['name'], 'find' => sys::find($file['name'], $str)); + } + } + + unset($aFile); + + foreach($aFind as $data) + { + $info = preg_split('/[\s]+/', trim($data['info']), 8); + + $html->get('filetp_find', 'sections/servers/games/filetp'); + + $html->set('id', $server); + $html->set('find', $data['find']); + $html->set('name', $data['file']); + + $path = $data['dir']; + + if($path{0} != '/') $path = '/'.$path; + + if($path != '/') $path = $path.'/'; + + $html->set('path', $path); + $html->set('chmod', $this->cti($info[0]).' '.$info[0]); + $html->set('owner', $info[2]); + $html->set('group', $info[3]); + + if($info[0]{0} == 'd') + { + $html->unit('folder', 1); + $html->unit('file'); + $html->set('size', ''); + }else{ + $type = explode('.', $data['file']); + + if(in_array(end($type), $this->aEdits)) + $html->unit('edit', 1); + else + $html->unit('edit'); + + $html->unit('file', 1); + $html->unit('folder'); + $html->set('size', sys::size($info[4])); + } + + $html->set('month', $this->mounthru[$info[5]]); + $html->set('day', $info[6]); + $html->set('time', $info[7]); + + $html->pack('list'); + } + + if(isset($html->arr['list'])) + sys::out($html->arr['list']); + + sys::out('Ничего не найдено'); + } + + public function logs($data, $uid) + { + global $html; + + $aLine = explode("\n", $data); + + $actions = array('i' => 'загрузка', 'o' => 'скачивание', 'd' => 'удаление'); + $acticon = array('i' => '', 'o' => '', 'd' => ''); + + unset($aLine[count($aLine)-1]); + + rsort($aLine); + + foreach($aLine as $line) + { + $aData = explode('\\', $line); + + $html->get('filetp_logs', 'sections/servers/games/filetp'); + + $html->set('month', $this->mounthint[$aData[0]]); + $html->set('day', $aData[1]); + $html->set('time', $aData[2]); + $html->set('year', $aData[3]); + $html->set('who', $this->who($aData[4])); + $html->set('size', sys::size($aData[5])); + $html->set('file', str_replace('/servers/'.$uid.'/', '', $aData[6])); + $html->set('action', $actions[$aData[7]]); + $html->set('acticon', $acticon[$aData[7]]); + + $html->pack('logs'); + } + + return isset($html->arr['logs']) ? $html->arr['logs'] : 'Список логов отсутствует'; + } + + private function path($path) + { + $path = str_replace('//', '/', $path); + + $path = explode('/', $path); + + unset($path[count($path)-1]); + + $newpath = '/'; + + foreach($path as $index => $val) + if(count($path)-1 == $index) $newpath .= $val; else $newpath .= $val.'/'; + + return str_replace('//', '/', $newpath); + } + + private function cti($chmod) + { + $intchmod = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'); + + $chmod = substr(strtr($chmod, $intchmod), 1); + + $split = str_split($chmod, 3); + + return array_sum(str_split($split[0])).array_sum(str_split($split[1])).array_sum(str_split($split[2])); + } + + private function who($address) + { + global $cfg, $uip; + + if($address == $cfg['ip']) + return 'панель управления'; + + if($address == $uip) + return 'вы'; + + return $address; + } + } +?> \ No newline at end of file diff --git a/system/library/games/actions.php b/system/library/games/actions.php new file mode 100644 index 0000000..aa1a7b8 --- /dev/null +++ b/system/library/games/actions.php @@ -0,0 +1,316 @@ +query('SELECT `uid`, `unit`, `game`, `address`, `name` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="off", `online`="0", `players`="", `stop`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function change($id, $map = false) + { + global $cfg, $sql, $html, $user, $mcache; + + // Если в кеше есть карты + if($mcache->get('server_maps_change_'.$id) != '' && !$map) + return array('maps' => $mcache->get('server_maps_change_'.$id)); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `tarif`, `online`, `players`, `name` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + // Массив карт игрового сервера (папка "maps") + $aMaps = explode("\n", $ssh->get('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.')); + + // Удаление пустого элемента + unset($aMaps[count($aMaps)-1]); + + // Удаление ".bsp" + $aMaps = str_replace('.bsp', '', $aMaps); + + // Если выбрана карта + if($map) + { + // Проверка наличия выбранной карты + if(!in_array($map, $aMaps)) + return array('e' => sys::updtext(sys::text('servers', 'change'), array('map' => $map.'.bsp'))); + + // Отправка команды changelevel + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval '."'stuff \"changelevel ".sys::cmd($map)."\"\015'"); + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="change" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'], 'players' => base64_decode($server['players']))); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'])); + + return array('s' => 'ok'); + } + + // Сортировка списка карт + sort($aMaps); + reset($aMaps); + + // Генерация списка карт для выбора + foreach($aMaps as $map) + { + $html->get('change_list', 'sections/servers/games'); + $html->set('img', sys::img($map, $server['game'])); + $html->set('name', $map); + $html->set('id', $id); + $html->pack('maps'); + } + + // Запись карт в кеш + $mcache->set('server_maps_change_'.$id, $html->arr['maps'], false, 30); + + return array('maps' => $html->arr['maps']); + } + + public static function reinstall($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `tarif`, `address`, `game`, `name`, `pack`, `plugins_use`, `ftp`, `reinstall`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Проверка времени переустановки + $reinstall = $server['reinstall']+$cfg['reinstall'][$server['game']]*60; + + if($reinstall > $start_point && $user['group'] != 'admin') + return array('e' => sys::updtext(sys::text('servers', 'reinstall'), array('time' => sys::date('max', $reinstall)))); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `path`, `install`, `plugins_install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] && !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория сборки + $path = $tarif['path'].$server['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('rm -r '.$install.';' // Удаление директории игрового сервера + .'mkdir '.$install.';' // Создание директории + .'chown server'.$server['uid'].':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$server['uid'].' '.$taskset.' screen -dmS r_'.$server['uid'].' sh -c "' + .'cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + // Очистка записей в базе + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); // Список админов на сервере + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$id.'"'); // Список установленных плагинов на сервере + + // Запись установленных плагинов + if($server['plugins_use']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($tarif['plugins_install']); + + if(isset($aPlugins[$server['pack']])) + { + $plugins = explode(',', $aPlugins[$server['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="reinstall", `reinstall`="'.$start_point.'", `core_use`="'.$core.'", `fastdl`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Логирование + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'reinstall').'", `time`="'.$start_point.'"'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'reinstall', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'reinstall', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `tarif`, `address`, `game`, `name`, `pack`, `plugins_use`, `ftp`, `update` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Проверка времени обновления + $update = $server['update']+$cfg['update'][$server['game']]*60; + + if($update > $start_point && $user['group'] != 'admin') + return array('e' => sys::updtext(sys::text('servers', 'update'), array('time' => sys::date('max', $update)))); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `update`, `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] && !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория обновлений сборки + $path = $tarif['update'].$server['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$install.' && sudo -u server'.$server['uid'].' '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "cp -rv '.$path.'/. .;' // Копирование файлов обвновления сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="update", `update`="'.$start_point.'", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Логирование + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'update').'", `time`="'.$start_point.'"'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function clmcache($id) + { + global $mcache; + + $mcache->delete('server_index_'.$id); + $mcache->delete('server_resources_'.$id); + $mcache->delete('server_status_'.$id); + } + } \ No newline at end of file diff --git a/system/library/games/boost.php b/system/library/games/boost.php new file mode 100644 index 0000000..0d96409 --- /dev/null +++ b/system/library/games/boost.php @@ -0,0 +1,113 @@ +partner_key = $key; + $this->service_url = $url; + } + + public function def($data) + { + $aData = array( + 'service' => 'boost', + 'period' => $data['period'], + 'address' => $data['address'], + 'game' => 'cs16' + ); + + $out = json_decode($this->defaultcurl(json_encode($aData)), true); + + if($out['message'] == 'Услуга уже присутствует') + $out = json_decode($this->defaultcurl(json_encode($aData), 'prolong'), true); + + if(!array_key_exists('status', $out)) + array('error' => 'Не удалось приобрести услугу, повторите запрос позже.'); + + if(!$out['status']) + return true; + + return array('error' => $out['message']); + } + + private function defaultcurl($data, $action = 'buy') + { + if(!($curl = curl_init())) + array('error' => 'FAIL: curl_init().'); + + curl_setopt($curl, CURLOPT_URL, $this->service_url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, 'key='.$this->partner_key.'&action='.$action.'&data='.$data); + + $out = curl_exec($curl); + + curl_close($curl); + + return $out; + } + + public function vipms($data) + { + $aData = array( + 'format' => 'POST', + 'country' => 'RU', + 'hoster_id' => 1, + 'key' => $this->partner_key, + 'full_address' => $data['address'], + 'service_id' => $data['period'] + ); + + return $this->othercurl($aData); + } + + public function fulls($data) + { + $aData = array( + 'format' => 'POST', + 'country' => 'RU', + 'hoster_id' => 1, + 'key' => $this->partner_key, + 'full_address' => $data['address'], + 'service_id' => $data['period'] + ); + + return $this->othercurl($aData); + } + + private function othercurl($aData) + { + if(!($curl = curl_init())) + array('error' => 'FAIL: curl_init().'); + + curl_setopt($curl, CURLOPT_URL, $this->service_url.'?'.urldecode(http_build_query($aData))); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, urldecode(http_build_query($aData))); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + + $result = curl_exec($curl); + + curl_close($curl); + + if($result == 'OK') + return true; + + $aErr = array( + 1 => 'BAD_HOSTER_ID', + 2 => 'HOSTER_NOT_FOUND', + 3 => 'BAD_HOSTER_IP', + 4 => 'FORM_INVALID', + 5 => 'BAD_SERVICE_ID' + ); + + return array('error' => $aErr[$result]); + } + } +?> \ No newline at end of file diff --git a/system/library/games/crmp/action.php b/system/library/games/crmp/action.php new file mode 100644 index 0000000..9398e77 --- /dev/null +++ b/system/library/games/crmp/action.php @@ -0,0 +1,130 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `map_start`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe;'); + + // Временный файл + $temp = sys::temp(action::config($ip, $port, $server['slots_start'], $ssh->get('cat '.$tarif['install'].'/'.$server['uid'].'/server.cfg'))); + + // Обновление файла server.cfg + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.cfg', 0644); + + unlink($temp); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $ssh->set('cat /proc/stat'); + $proc_stat[1] = $ssh->get(); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Параметры запуска + $bash = './samp03svr-cr'; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p oldstart;' // Создание папки логов + .'cat server_log.txt >> oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm server_log.txt; rm oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 server.cfg start.sh;' // Обновление владельца файлов server.cfg start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function config($ip, $port, $slots, $config) + { + $aLine = explode("\n", $config); + + $eConfig = ''; + + foreach($aLine as $line) + { + $param = explode(' ', trim($line)); + + if(in_array(trim($param[0]), array('bind', 'port', 'maxplayers', 'query'))) + continue; + + $eConfig .= $line.PHP_EOL; + } + + $eConfig .= 'bind '.$ip.PHP_EOL + .'port '.$port.PHP_EOL + .'maxplayers '.$slots.PHP_EOL + .'query 1'; + + return $eConfig; + } + } +?> \ No newline at end of file diff --git a/system/library/games/crmp/scan.php b/system/library/games/crmp/scan.php new file mode 100644 index 0000000..5545de9 --- /dev/null +++ b/system/library/games/crmp/scan.php @@ -0,0 +1,115 @@ +query('SELECT `address`, `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + include(LIB.'games/query/SampQuery.php'); + + $sq = new SampQuery($ip, $port); + + if($players_get) + $nmch = 'server_scan_mon_pl_'.$id; + else + $nmch = 'server_scan_mon_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$sq->connect()) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + $info = $sq->getInfo(); + + if($players_get) + $players = scan::players($sq->getDetailedPlayers()); + + $info['map'] = htmlspecialchars(mb_convert_encoding($info['map'], 'UTF-8', 'WINDOWS-1251')); + $out['name'] = htmlspecialchars(mb_convert_encoding($info['hostname'], 'UTF-8', 'WINDOWS-1251')); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = sys::int($info['players']); + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', htmlspecialchars($player['name'])); + $html->set('ping', sys::int($player['ping'])); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function players($aPlayrs) + { + $i = 1; + $aData = array(); + + foreach($aPlayrs as $n => $player) + { + $aData[$i]['i'] = $i; + $aData[$i]['name'] = $player['nickname'] == '' ? 'Подключается' : htmlspecialchars($player['nickname']); + $aData[$i]['ping'] = sys::int($player['ping']); + + $i+=1; + } + + return $aData; + } + } +?> \ No newline at end of file diff --git a/system/library/games/crmp/service.php b/system/library/games/crmp/service.php new file mode 100644 index 0000000..32e2531 --- /dev/null +++ b/system/library/games/crmp/service.php @@ -0,0 +1,355 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `crmp`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'crmp') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['crmp']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['crmp']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 777 {} \;;' + .'chmod 500 '.params::$aFileGame['crmp'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="crmp", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `map_start`="'.sys::passwd(8).'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="crmp", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/crmp/tarif.php b/system/library/games/crmp/tarif.php new file mode 100644 index 0000000..a65da45 --- /dev/null +++ b/system/library/games/crmp/tarif.php @@ -0,0 +1,179 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $sum = $tarif['slots'] ? $tarif['price'] : $tarif['price']*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan() + { + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cs/action.php b/system/library/games/cs/action.php new file mode 100644 index 0000000..76ada82 --- /dev/null +++ b/system/library/games/cs/action.php @@ -0,0 +1,117 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `fps`, `map_start`, `vac`, `pingboost`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // Значение PingBoost + $pingboost = $server['pingboost'] == 0 ? $cfg['pingboost'] : $server['pingboost']; + + if(!$pingboost) + $pingboost = ''; + else + $pingboost = '-pingboost '.$pingboost; + + // Значение sys_ticrate (FPS) + $fps = $server['fps']+$cfg['fpsplus']; + + // Параметры запуска + $bash = './hlds_run -debug -game cstrike -norestart -condebug -sys_ticrate '.$fps.' +servercfgfile server.cfg +sys_ticrate '.$fps.' +map \''.$server['map_start'].'\' +maxplayers '.$server['slots_start'].' +ip '.$ip.' +port '.$port.' +sv_lan 0 '.$vac.' '.$pingboost; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/qconsole.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/qconsole.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c ./start.sh'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/games/cs/rcon.php b/system/library/games/cs/rcon.php new file mode 100644 index 0000000..0cf116a --- /dev/null +++ b/system/library/games/cs/rcon.php @@ -0,0 +1,110 @@ +Connect($ip, $port, 3, SourceQuery::GOLDSOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[1]); + $ip = trim(sys::first(explode(':', $aData[6]))); + + if(sys::valid($steamid, 'steamid') || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['frags'] = trim($aData[2]); + $aPlayers[$n]['time'] = trim($aData[3]); + $aPlayers[$n]['ping'] = trim($aData[4]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cat '.$tarif['install'].$server['uid'].'/cstrike/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'servers/id/'.$server['id'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/games/cs/scan.php b/system/library/games/cs/scan.php new file mode 100644 index 0000000..59b6507 --- /dev/null +++ b/system/library/games/cs/scan.php @@ -0,0 +1,140 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working'); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::GOLDSOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cs/service.php b/system/library/games/cs/service.php new file mode 100644 index 0000000..44655e0 --- /dev/null +++ b/system/library/games/cs/service.php @@ -0,0 +1,368 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `cs`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`fps`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`map`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + // Проверка FPS + if(!in_array($aData['fps'], explode(':', $tarif['fps']))) + sys::outjs(array('e' => 'Переданные данные fps неверны.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'cs') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение цены + $aPrice = explode(':', $tarif['price']); + $price = $aPrice[array_search($aData['fps'], explode(':', $tarif['fps']))]; + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'fps' => $aData['fps'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['cs']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['cs']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'fps' => $aData['fps'], // значение fps + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'map' => $tarif['map'], // Фиксированное значение слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame['cs'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="cs", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `fps`="'.$aSDATA['fps'].'", + `map_start`="'.$aSDATA['map'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="cs", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cs/tarif.php b/system/library/games/cs/tarif.php new file mode 100644 index 0000000..c571bc8 --- /dev/null +++ b/system/library/games/cs/tarif.php @@ -0,0 +1,225 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['fps'].' FPS'); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + $sum = $tarif['slots'] ? $aPrice[array_search($server['fps'], $aFPS)] : $aPrice[array_search($server['fps'], $aFPS)]*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['fps'].' FPS'); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan($server, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `fps`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $tarif = $sql->get(); + + $options = ''; + + $aPrice = explode(':', $tarif['price']); + $aFps = explode(':', $tarif['fps']); + + // Если есть выбор + if(count($aFps) > 1) + { + // Удалить при наличии fps сервера из выбора + if(in_array($server['fps'], $aFps)) + unset($aFps[array_search($server['fps'], $aFps)]); + + foreach($aFps as $index => $fps) + $options .= ''; + }else + return NULL; + + $html->get('plan', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('info', $server['fps'].' FPS'); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit`, `fps` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + if(!in_array($server['fps'], explode(':', $tarif['fps']))) + continue; + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', $server['fps'].' FPS'); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `vac`="1", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/csgo/action.php b/system/library/games/csgo/action.php new file mode 100644 index 0000000..ab3c467 --- /dev/null +++ b/system/library/games/csgo/action.php @@ -0,0 +1,302 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `tickrate`, `map_start`, `vac`, `time_start`, `core_fix`, `pingboost` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd '.$tarif['install'].$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\''); + + include_once(LIB.'games/games.php'); + + if(games::map($server['map_start'], $ssh->get())) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // Боты + $bots = $cfg['bots'][$server['game']] ? '' : '-nobots'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 30 +tv_port '.($port+10000) : '-nohltv'; + + $check = explode('/', $server['map_start']); + + // Стартовая карта + $map = $check[0] == 'workshop' ? '+workshop_start_map '.$check[1] : '+map \''.$server['map_start'].'\''; + + // Игровой режим + $mods = array( + 1 => '+game_type 0 +game_mode 0', + 2 => '+game_type 0 +game_mode 1', + 3 => '+game_type 1 +game_mode 0', + 4 => '+game_type 1 +game_mode 1', + 5 => '+game_type 1 +game_mode 2' + ); + + $mod = !$server['pingboost'] ? $mods[2] : $mods[$server['pingboost']]; + + // Параметры запуска + $bash = './srcds_run -debug -game csgo -norestart -condebug console.log -usercon -tickrate '.$server['tickrate'].' '.$mod.' +servercfgfile server.cfg '.$map.' -maxplayers_override '.$server['slots_start'].' +ip '.$ip.' +net_public_adr '.$ip.' +port '.$port.' -sv_lan 0 '.$vac.' '.$bots.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p csgo/oldstart;' // Создание папки логов + .'cat csgo/console.log >> csgo/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm csgo/console.log; rm csgo/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function change($id, $map = false) + { + global $cfg, $sql, $html, $user, $mcache; + + // Если в кеше есть карты + if($mcache->get('server_maps_change_'.$id) != '' AND !$map) + return array('maps' => $mcache->get('server_maps_change_'.$id)); + + include(LIB.'ssh.php'); + + include(LIB.'games/games.php'); + + $sql->query('SELECT `uid`, `unit`, `game`, `tarif`, `online`, `players`, `name` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + // Массив карт игрового сервера (папка "maps") + $aMaps = explode("\n", $ssh->get('cd '.$tarif['install'].$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\'')); + + // Удаление пустого элемента + unset($aMaps[count($aMaps)-1]); + + // Удаление ".bsp" + $aMaps = str_ireplace(array('./', '.bsp'), '', $aMaps); + + // Если выбрана карта + if($map) + { + $map = str_replace('|', '/', $map); + + // Проверка наличия выбранной карты + if(games::map($map, $aMaps)) + return array('e' => sys::updtext(sys::text('servers', 'change'), array('map' => $map.'.bsp'))); + + // Отправка команды changelevel + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval '."'stuff \"changelevel ".sys::cmd($map)."\"\015'"); + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="change" WHERE `id`="'.$id.'" LIMIT 1'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'], 'players' => base64_decode($server['players']))); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'])); + + return array('s' => 'ok'); + } + + // Сортировка списка карт + sort($aMaps); + reset($aMaps); + + // Генерация списка карт для выбора + foreach($aMaps as $map) + { + $aName = explode('/', $map); + $name = end($aName); + + $html->get('change_list', 'sections/servers/csgo'); + + $html->set('img', file_exists(DIR.'/maps/'.$server['game'].'/'.$name.'.jpg') ? $cfg['http'].'maps/'.$server['game'].'/'.$name.'.jpg' : $cfg['http'].'template/images/status/none.jpg'); + $html->set('map', str_replace('/', '|', $map)); + $html->set('name', $name); + $html->set('id', $id); + + if(count($aName) > 1) + $html->unit('workshop', true); + else + $html->unit('workshop'); + + $html->pack('maps'); + } + + // Запись карт в кеш + $mcache->set('server_maps_change_'.$id, $html->arr['maps'], false, 60); + + return array('maps' => $html->arr['maps']); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `tarif`, `game`, `name`, `ftp`, `update`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Проверка времени обновления + $update = $server['update']+$cfg['update'][$server['game']]*60; + + if($update > $start_point AND $user['group'] != 'admin') + return array('e' => sys::updtext(sys::text('servers', 'update'), array('time' => sys::date('max', $update)))); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `plugins_install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$cfg['steamcmd'].' && '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "' + .'./steamcmd.sh +login anonymous +force_install_dir "'.$install.'" +app_update 740 +quit;' + .'cd '.$install.';' + .'chown -R server'.$server['uid'].':servers .;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="update", `update`="'.$start_point.'", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Логирование + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'update').'", `time`="'.$start_point.'"'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/games/csgo/rcon.php b/system/library/games/csgo/rcon.php new file mode 100644 index 0000000..74182de --- /dev/null +++ b/system/library/games/csgo/rcon.php @@ -0,0 +1,112 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if((sys::valid($steamid, 'steamid') AND sys::valid($steamid, 'steamid3')) || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cat '.$tarif['install'].'/'.$server['uid'].'/csgo/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'servers/id/'.$server['id'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/games/csgo/scan.php b/system/library/games/csgo/scan.php new file mode 100644 index 0000000..5e498aa --- /dev/null +++ b/system/library/games/csgo/scan.php @@ -0,0 +1,142 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working'); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $map = explode('/', $data['Map']); + + $server['name'] = $data['HostName']; + $server['map'] = end($map); + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/games/csgo/service.php b/system/library/games/csgo/service.php new file mode 100644 index 0000000..6f3729c --- /dev/null +++ b/system/library/games/csgo/service.php @@ -0,0 +1,369 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `csgo`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`tickrate`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`map`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + // Проверка TickRate + if(!in_array($aData['tickrate'], explode(':', $tarif['tickrate']))) + sys::outjs(array('e' => 'Переданные данные tickrate неверны.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'csgo') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение цены + $aPrice = explode(':', $tarif['price']); + $price = $aPrice[array_search($aData['tickrate'], explode(':', $tarif['tickrate']))]; + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'tickrate' => $aData['tickrate'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['csgo']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['csgo']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'tickrate' => $aData['tickrate'], // значение tickrate + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'map' => $tarif['map'], // Фиксированное значение слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame['csgo'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="csgo", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `tickrate`="'.$aSDATA['tickrate'].'", + `map_start`="'.$aSDATA['map'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="csgo", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/csgo/tarif.php b/system/library/games/csgo/tarif.php new file mode 100644 index 0000000..0aba2f5 --- /dev/null +++ b/system/library/games/csgo/tarif.php @@ -0,0 +1,225 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + $sum = $tarif['slots'] ? $aPrice[array_search($server['tickrate'], $aTICK)] : $aPrice[array_search($server['tickrate'], $aTICK)]*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan($server, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $tarif = $sql->get(); + + $options = ''; + + $aPrice = explode(':', $tarif['price']); + $aTick = explode(':', $tarif['tickrate']); + + // Если есть выбор + if(count($aTick) > 1) + { + // Удалить при наличии tickrate сервера из выбора + if(in_array($server['tickrate'], $aTick)) + unset($aTick[array_search($server['tickrate'], $aTick)]); + + foreach($aTick as $index => $tickrate) + $options .= ''; + }else + return NULL; + + $html->get('plan', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit`, `tickrate` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + if(!in_array($server['tickrate'], explode(':', $tarif['tickrate']))) + continue; + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `vac`="1", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/css/action.php b/system/library/games/css/action.php new file mode 100644 index 0000000..334800b --- /dev/null +++ b/system/library/games/css/action.php @@ -0,0 +1,189 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `tickrate`, `map_start`, `vac`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // Боты + $bots = $cfg['bots'][$server['game']] ? '' : '-nobots'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 30 +tv_port '.($port+10000) : '-nohltv'; + + // Параметры запуска + $bash = './srcds_run -debug -game cstrike -norestart -condebug console.log -tickrate '.$server['tickrate'].' +servercfgfile server.cfg +map \''.$server['map_start'].'\' +maxplayers '.$server['slots_start'].' +ip '.$ip.' +port '.$port.' -sv_lan 0 '.$vac.' '.$bots.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/console.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/console.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function update($id) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `uid`, `unit`, `tarif`, `game`, `name`, `ftp`, `update`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Проверка времени обновления + $update = $server['update']+$cfg['update'][$server['game']]*60; + + if($update > $start_point AND $user['group'] != 'admin') + return array('e' => sys::updtext(sys::text('servers', 'update'), array('time' => sys::date('max', $update)))); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `plugins_install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => 'Не удается выполнить операцию, нет свободного потока.'); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + $ssh->set('cd '.$cfg['steamcmd'].' && sudo -u server'.$server['uid'].' '.$taskset.' sh -c "screen -dmS u_'.$server['uid'].' ./steamcmd.sh +login anonymous +force_install_dir "'.$install.'" +app_update 232330 +quit"'); + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="update", `update`="'.$start_point.'", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Логирование + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'update').'", `time`="'.$start_point.'"'); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/games/css/rcon.php b/system/library/games/css/rcon.php new file mode 100644 index 0000000..6a97e06 --- /dev/null +++ b/system/library/games/css/rcon.php @@ -0,0 +1,112 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if((sys::valid($steamid, 'steamid') AND sys::valid($steamid, 'steamid3')) || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cat '.$tarif['install'].'/'.$server['uid'].'/cstrike/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'servers/id/'.$server['id'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/games/css/scan.php b/system/library/games/css/scan.php new file mode 100644 index 0000000..ca76ba3 --- /dev/null +++ b/system/library/games/css/scan.php @@ -0,0 +1,140 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working'); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/games/css/service.php b/system/library/games/css/service.php new file mode 100644 index 0000000..efc9a89 --- /dev/null +++ b/system/library/games/css/service.php @@ -0,0 +1,369 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `css`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`tickrate`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`map`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + // Проверка TickRate + if(!in_array($aData['tickrate'], explode(':', $tarif['tickrate']))) + sys::outjs(array('e' => 'Переданные данные tickrate неверны.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'css') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение цены + $aPrice = explode(':', $tarif['price']); + $price = $aPrice[array_search($aData['tickrate'], explode(':', $tarif['tickrate']))]; + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'tickrate' => $aData['tickrate'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['css']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['css']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'tickrate' => $aData['tickrate'], // значение tickrate + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'map' => $tarif['map'], // Фиксированное значение слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame['css'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="css", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `tickrate`="'.$aSDATA['tickrate'].'", + `map_start`="'.$aSDATA['map'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="css", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/css/tarif.php b/system/library/games/css/tarif.php new file mode 100644 index 0000000..0aba2f5 --- /dev/null +++ b/system/library/games/css/tarif.php @@ -0,0 +1,225 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + $sum = $tarif['slots'] ? $aPrice[array_search($server['tickrate'], $aTICK)] : $aPrice[array_search($server['tickrate'], $aTICK)]*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan($server, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $tarif = $sql->get(); + + $options = ''; + + $aPrice = explode(':', $tarif['price']); + $aTick = explode(':', $tarif['tickrate']); + + // Если есть выбор + if(count($aTick) > 1) + { + // Удалить при наличии tickrate сервера из выбора + if(in_array($server['tickrate'], $aTick)) + unset($aTick[array_search($server['tickrate'], $aTick)]); + + foreach($aTick as $index => $tickrate) + $options .= ''; + }else + return NULL; + + $html->get('plan', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit`, `tickrate` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + if(!in_array($server['tickrate'], explode(':', $tarif['tickrate']))) + continue; + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate'); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `vac`="1", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cssold/action.php b/system/library/games/cssold/action.php new file mode 100644 index 0000000..3786d72 --- /dev/null +++ b/system/library/games/cssold/action.php @@ -0,0 +1,116 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `tickrate`, `fps`, `map_start`, `vac`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Проверка наличия стартовой карты + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep .bsp | grep -v .bsp.'); + + if($server['map_start'] != '' AND !in_array($server['map_start'], str_replace('.bsp', '', explode("\n", $ssh->get())))) + return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp'))); + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Античит VAC + $vac = $server['vac'] == 0 ? '-insecure' : '-secure'; + + // Боты + $bots = $cfg['bots'][$server['game']] ? '' : '-nobots'; + + // TV + $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 30 +tv_port '.($port+10000) : '-nohltv'; + + // FPS + $fps = $server['fps']+$cfg['fpsplus']; + + // Параметры запуска + $bash = './srcds_run -debug -game cstrike -norestart -condebug console.log -tickrate '.$server['tickrate'].' +fps_egp '.$fps.' +servercfgfile server.cfg +map \''.$server['map_start'].'\' +maxplayers '.$server['slots_start'].' +ip '.$ip.' +port '.$port.' +sv_lan 0 -nomaster -localcser '.$vac.' '.$bots.' '.$tv; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'mv console.log oldstart.log;' // Перемещение лога предыдущего запуска в файл oldstart.log + .'sudo -u server'.$server['uid'].' mkdir -p cstrike/oldstart;' // Создание папки логов + .'cat cstrike/console.log >> cstrike/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm cstrike/console.log; rm cstrike/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + } +?> \ No newline at end of file diff --git a/system/library/games/cssold/rcon.php b/system/library/games/cssold/rcon.php new file mode 100644 index 0000000..40627de --- /dev/null +++ b/system/library/games/cssold/rcon.php @@ -0,0 +1,112 @@ +Connect($ip, $port, 3, SourceQuery::SOURCE); + + $sq->SetRconPassword(rcon::rcon_passwd($server)); + + $out = $sq->Rcon($cmd); + + $sq->Disconnect(); + + return $out; + } + + public static function players($data) + { + $aPlayers = array(); + $n = 1; + + $lines = explode("\n", $data); + + foreach($lines as $line) + { + if(strpos($line, '#') === FALSE) + continue; + + $start = strpos($line, '"')+1; + $end = strrpos($line, '"'); + + $userid = sys::int(substr($line, 0, $start)); + + $name = htmlspecialchars(substr($line, $start, $end-$start)); + + $line = trim(substr($line, $end + 1)); + + $aData = array_values(array_diff(explode(' ', $line), array('', ' '))); + + $steamid = trim($aData[0]); + $ip = trim(sys::first(explode(':', $aData[5]))); + + if(sys::valid($steamid, 'steamid') || sys::valid($ip, 'ip')) + continue; + + $aPlayers[$n]['userid'] = $userid; + $aPlayers[$n]['name'] = $name; + $aPlayers[$n]['steamid'] = $steamid; + $aPlayers[$n]['time'] = trim($aData[1]); + $aPlayers[$n]['ping'] = trim($aData[2]); + $aPlayers[$n]['ip'] = $ip; + + $whois = rcon::country($ip); + + $aPlayers[$n]['ico'] = $whois['ico']; + $aPlayers[$n]['country'] = $whois['name']; + + $n+=1; + } + + return $aPlayers; + } + + public static function rcon_passwd($server) + { + global $cfg, $sql, $user; + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cat '.$tarif['install'].'/'.$server['uid'].'/cstrike/cfg/server.cfg | grep rcon_password'); + $get = explode(' ', str_replace('"', '', trim($ssh->get()))); + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'servers/id/'.$server['id'].'/section/settings/subsection/server'), $nmch); + + return $rcon; + } + + public static function country($ip) + { + global $SxGeo; + + $cData = $SxGeo->getCityFull($ip); + $ico = sys::country($cData['country']['iso']); + + return array('ico' => $ico, 'name' => empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + } + } +?> \ No newline at end of file diff --git a/system/library/games/cssold/scan.php b/system/library/games/cssold/scan.php new file mode 100644 index 0000000..ca76ba3 --- /dev/null +++ b/system/library/games/cssold/scan.php @@ -0,0 +1,140 @@ +get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $info = scan::info($sq, $id); + + $sql->query('SELECT `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$info['status']) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + if($players_get) + $players = scan::info($sq, $id, true); + + $out['name'] = htmlspecialchars($info['name']); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = $info['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working'); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('score', $player['score']); + $html->set('time', $player['time']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function info($sq, $id, $pl = false) + { + global $sql; + + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $sq->Connect($ip, $port, 1, SourceQuery::SOURCE); + + if($pl) + { + $players = $sq->GetPlayers(); + + $i = 1; + $data = array(); + + foreach($players as $n => $player) + { + $data[$i]['i'] = $i; + $data[$i]['name'] = $player['Name'] == '' ? 'Подключается' : $player['Name']; + $data[$i]['score'] = $player['Frags']; + $data[$i]['time'] = $player['TimeF']; + + $i+=1; + } + + return $data; + } + + $data = $sq->GetInfo(); + + $server['name'] = $data['HostName']; + $server['map'] = $data['Map']; + $server['online'] = $data['Players']; + $server['status'] = strlen($server['map']) > 3 ? true : false; + + return $server; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cssold/service.php b/system/library/games/cssold/service.php new file mode 100644 index 0000000..80cab04 --- /dev/null +++ b/system/library/games/cssold/service.php @@ -0,0 +1,378 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `cssold`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`fps`,' + .'`tickrate`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`map`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + // Проверка FPS + if(!in_array($aData['fps'], explode(':', $tarif['fps']))) + sys::outjs(array('e' => 'Переданные данные fps неверны.')); + + // Проверка TickRate + if(!in_array($aData['tickrate'], explode(':', $tarif['tickrate']))) + sys::outjs(array('e' => 'Переданные данные tickrate неверны.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'cssold') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + $aPrice = sys::b64djs($tarif['price'], true); + + // Определение цены + $price = $aPrice[$aData['tickrate'].'_'.$aData['fps']]; + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'tickrate' => $aData['tickrate'], + 'fps' => $aData['fps'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['cssold']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['cssold']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'tickrate' => $aData['tickrate'], // значение tickrate + 'fps' => $aData['fps'], // значение fps + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'map' => $tarif['map'], // Фиксированное значение слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame['cssold'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="cssold", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `tickrate`="'.$aSDATA['tickrate'].'", + `fps`="'.$aSDATA['fps'].'", + `map_start`="'.$aSDATA['map'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="cssold", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/cssold/tarif.php b/system/library/games/cssold/tarif.php new file mode 100644 index 0000000..c98df60 --- /dev/null +++ b/system/library/games/cssold/tarif.php @@ -0,0 +1,244 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate / '.$server['fps'].' FPS'); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $aPrice = sys::b64djs($tarif['price']); + + $sum = $tarif['slots'] ? $aPrice[$server['tickrate'].'_'.$server['fps']] : $aPrice[$server['tickrate'].'_'.$server['fps']]*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate / '.$server['fps'].' FPS'); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan($server, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `fps`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $tarif = $sql->get(); + + $options = ''; + + $aPrice = sys::b64djs($tarif['price']); + + unset($aPrice[$server['tickrate'].'_'.$server['fps']]); + + foreach($aPrice as $param => $price) + { + list($tickrate, $fps) = explode('_', $param); + + $options .= ''; + } + + if($options == '') + return NULL; + + $html->get('plan', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', ''.$options); + $html->set('info', $server['tickrate'].' TickRate / '.$server['fps'].' FPS'); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit`, `fps`, `tickrate`, `price` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + if(!array_key_exists($server['tickrate'].'_'.$server['fps'], sys::b64djs($tarif['price']))) + continue; + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', $server['tickrate'].' TickRate / '.$server['fps'].' FPS'); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `vac`="1", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + + public static function price($plan) + { + $aPrice = array_values(sys::b64djs($plan)); + + $check = $aPrice[0]; + + unset($aPrice[0]); + + if(!count($aPrice)) + return false; + + foreach($aPrice as $price) + { + if($check != $price) + return true; + } + + return false; + } + } +?> \ No newline at end of file diff --git a/system/library/games/games.php b/system/library/games/games.php new file mode 100644 index 0000000..ee0c2d2 --- /dev/null +++ b/system/library/games/games.php @@ -0,0 +1,810 @@ + 'устанавливается', + 'reinstall' => 'переустанавливается', + 'update' => 'обновляется', + 'recovery' => 'восстанавливается', + 'overdue' => 'не оплачен', + 'blocked' => 'заблокирован' + ); + + $msg = sys::updtext(sys::text('servers', 'determine'), array('status' => $aText[$status])); + + if($go) + sys::out($msg); + + $html->get('informer'); + + $html->set('[class]', 'info_red'); + $html->set('[text]', $msg); + + $html->pack($tpl); + + return false; + } + + public static function crontab_week($week) + { + $aWeek = array(); + $aWeek[1] = isset($week['\'1\'']) ? 'Пн., ' : ''; + $aWeek[2] = isset($week['\'2\'']) ? 'Вт., ' : ''; + $aWeek[3] = isset($week['\'3\'']) ? 'Ср., ' : ''; + $aWeek[4] = isset($week['\'4\'']) ? 'Чт., ' : ''; + $aWeek[5] = isset($week['\'5\'']) ? 'Пт., ' : ''; + $aWeek[6] = isset($week['\'6\'']) ? 'Сб., ' : ''; + $aWeek[7] = isset($week['\'7\'']) ? 'Вс., ' : ''; + + $days = ''; + + foreach($aWeek as $index => $val) + { + if($val == '') + continue; + + $days .= $val; + } + + $days = substr($days, 0, -2); + + if($days == '') + $days = 'Пн., Вт., Ср., Чт., Пт., Сб., Вс.'; + + return $days; + } + + public static function crontab_time($allhour, $hour, $minute) + { + if($allhour) + return 'Каждый час'; + + $aHour = array( + '00', '01', '02', + '03', '04', '05', + '06', '07', '08', + '09', '10', '11', + '12', '13', '14', + '15', '16', '17', + '18', '19', '20', + '21', '22', '23' + ); + + $aMinute = array( + '00', '05', '10', + '15', '20', '25', + '30', '35', '40', + '45', '50', '55' + ); + + if(!in_array($hour, $aHour)) + $hour = '00'; + + if(!in_array($minute, $aMinute)) + $minute = '00'; + + return $hour.':'.$minute; + } + + public static function crontab($data = array(), $id, $cid) + { + global $cfg; + + if($data['allhour']) + $time = '0 * * * '; + else{ + $hour = array( + '00', '01', '02', + '03', '04', '05', + '06', '07', '08', + '09', '10', '11', + '12', '13', '14', + '15', '16', '17', + '18', '19', '20', + '21', '22', '23' + ); + + $minute = array( + '00', '05', '10', + '15', '20', '25', + '30', '35', '40', + '45', '50', '55' + ); + + if(!in_array($data['hour'], $hour)) + $data['hour'] = '00'; + + if(!in_array($data['minute'], $minute)) + $data['minute'] = '00'; + + $time = $data['minute'].' '.$data['hour'].' * * '; + } + + $week = array(); + $week[1] = isset($data['week']['\'1\'']) ? 1 : 0; + $week[2] = isset($data['week']['\'2\'']) ? 2 : 0; + $week[3] = isset($data['week']['\'3\'']) ? 3 : 0; + $week[4] = isset($data['week']['\'4\'']) ? 4 : 0; + $week[5] = isset($data['week']['\'5\'']) ? 5 : 0; + $week[6] = isset($data['week']['\'6\'']) ? 6 : 0; + $week[7] = isset($data['week']['\'7\'']) ? 7 : 0; + + $check = 0; + + foreach($week as $index => $val) + $check+= $val; + + if($check == 28 || !$check) + $week = '*'; + else{ + $weeks = $week[1].','.$week[2].','.$week[3].','.$week[4].','.$week[5].','.$week[6].','.$week[7]; + $weeks = str_replace(array(',0', '0'), '', $weeks); + $week = $weeks{0} == ',' ? substr($weeks, 1) : $weeks; + } + + $cron_task = $time.$week.' screen -dmS s'.$id.' bash -c \'cd /var/enginegp && php cron.php '.$cfg['cron_key'].' server_cron '.$id.' '.$cid.'\''; + + return $cron_task; + } + + public static function parse_tarif($aTarif = array(), $aUnit = array()) + { + global $cfg, $mcache; + + $nmch = 'parse_tarif_'.$aTarif['id']; + + $cache = $mcache->get($nmch); + + if(is_array($cache)) + return $cache; + + if(isset($aTarif['fps'])) + $aFPS = explode(':', $aTarif['fps']); + + if(isset($aTarif['tickrate'])) + $aTICKRATE = explode(':', $aTarif['tickrate']); + + if(isset($aTarif['ram'])) + $aRAM = explode(':', $aTarif['ram']); + + $fps = ''; + + if(isset($aFPS)) + foreach($aFPS as $value) + $fps .= ''; + + $tickrate = ''; + + if(isset($aTICKRATE)) + foreach($aTICKRATE as $value) + $tickrate .= ''; + + $ram = ''; + + if(isset($aRAM)) + { + if($aTarif['param_fix']) + foreach($aRAM as $value) + $ram .= ''; + else + foreach($aRAM as $value) + $ram .= ''; + } + + $packs = ''; + $aPack = sys::b64djs($aTarif['packs'], true); + + if(is_array($aPack)) + foreach($aPack as $index => $name) + $packs .= ''; + + $slots = ''; + + for($i = $aTarif['slots_min']; $i <= $aTarif['slots_max']; $i+=1) + $slots .= ''; + + $aTime = explode(':', $aTarif['time']); + + $time = games::parse_time($aTime, $aTarif['discount'], $aTarif['id']); + + if($aTarif['test'] AND $aUnit['test']) + $time .= ''; + + $data = array( + 'packs' => $packs, + 'slots' => $slots, + 'time' => $time, + 'fps' => $fps, + 'tickrate' => $tickrate, + 'ram' => $ram + ); + + $mcache->set($nmch, $data, false, 60); + + return $data; + } + + public static function parse_time($aTime = array(), $discount, $tarif, $type = 'buy') + { + global $cfg; + + $time = ''; + + $arr = isset(params::$disconunt['service'][$tarif]) ? $tarif : 'time'; + + foreach($aTime as $value) + { + if(array_key_exists($value, params::$disconunt['service'][$arr][$type]) AND $discount) + { + $data = explode(':', params::$disconunt['service'][$arr][$type][$value]); + + // Если наценка + if($data[0] == '+') + { + // Если значение в процентах + if(substr($data[1], -1) == '%') + $time .= ''; + else + $time .= ''; + }else{ + // Если значение в процентах + if(substr($data[1], -1) == '%') + $time .= ''; + else + $time .= ''; + } + }else + $time .= ''; + } + + return $time; + } + + public static function define_period($type, $aD_M, $time = 0) + { + global $start_point; + + if($time < $start_point) + $time = $start_point; + + $day = $type == 'extend' ? date('d', $time) : date('d', $start_point); + $month = $type == 'extend' ? date('n', $time) : date('n', $start_point); + + $period = $aD_M[$month]-$day; + + if($day > 15) + $period += $month != 12 ? $aD_M[$month+1] : $aD_M[1]; + + return $period+1; + } + + public static function define_sum($discount, $price, $slots, $time, $type = 'buy') + { + global $sql, $user, $cfg, $start_point; + + if($cfg['settlement_period']) + { + if($time < $start_point) + $time = $start_point; + + $day = $type == 'extend' ? date('d', $time) : date('d', $start_point); + $month = $type == 'extend' ? date('n', $time) : date('n', $start_point); + + $period = params::$aDayMonth[$month]+1-$day; + + $new_month_sum = 0; + + if($day > 15) + $new_month_sum = ceil($price*$slots); + + $sum = params::$aDayMonth[$month] == $period ? $price*$slots : floor($price*$slots/30*$period)+$new_month_sum; + }else{ + $sum = floor($price*$slots/30*$time); + + if(array_key_exists($time, params::$disconunt['service']['time'][$type]) AND $discount) + { + $data = explode(':', params::$disconunt['service']['time'][$type][$time]); + + // Если наценка + if($data[0] == '+') + { + // Если значение в процентах + if(substr($data[1], -1) == '%') + $sum = ceil($sum+$sum/100*intval($data[1])); + else + $sum = $sum+intval($data[1]); + }else{ + // Если значение в процентах + if(substr($data[1], -1) == '%') + $sum = ceil($sum-$sum/100*intval($data[1])); + else + $sum = $sum-intval($data[1]); + } + } + } + + $sel = $type == 'buy' ? 'rental' : 'extend'; + + $sql->query('SELECT `'.$sel.'` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + $sum = strpos($user[$sel], '%') ? $sum-$sum/100*$user[$sel] : $sum-$user[$sel]; + + if($sum < 0) + sys::outjs(array('e' => 'Ошибка: сумма за услугу неверна')); + + return $sum; + } + + public static function define_promo($cod, $data = array(), $discount, $sum, $type = 'buy') + { + global $cfg, $sql, $go, $start_point; + + // Проверка формата кода + if(sys::valid($cod, 'promo')) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код имеет неверный формат.')); + + return NULL; + } + + $sql->query('SELECT `id`, `value`, `discount`, `data`, `hits`, `use`, `extend`, `user`, `server` FROM `promo` WHERE `cod`="'.$cod.'" AND `tarif`="'.$data['tarif'].'" AND `time`>"'.$start_point.'" LIMIT 1'); + + // Проверка наличия промо-кода + if(!$sql->num()) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код не найден.')); + + return NULL; + } + + $promo = $sql->get(); + + // Проверка типа при аренде + if($type == 'buy' AND $promo['extend']) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код для продления игрового сервера.')); + + return NULL; + } + + // Проверка типа при продлении + if($type != 'buy' AND !$promo['extend']) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код для аренды нового игрового сервера.')); + + return NULL; + } + + // Проверка доступности на пользователя + if($promo['user'] AND $data['user'] != $promo['user']) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код не найден.')); + + return NULL; + } + + // Проверка доступности на сервер + if($promo['server'] AND $data['server'] != $promo['server']) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код не найден.')); + + return NULL; + } + + $use = $promo['use'] < 1 ? '1' : $promo['use']; + + // Проверка доступности + $sql->query('SELECT `id` FROM `promo_use` WHERE `promo`="'.$promo['id'].'" LIMIT '.$use); + if($sql->num() >= $promo['use']) + { + if(!$go) + sys::outjs(array('e' => 'Промо-код использован максимальное количество раз.')); + + return NULL; + } + + // Данные для сравнения + $data_promo = sys::b64djs($promo['data'], true); + + $check = 0; + + // Проверка периода + if(in_array($data['time'], explode(':', $data_promo['time']))) + $check = 1; + + // Проверка значения FPS + if((isset($data['fps']) AND isset($data_promo['fps'])) AND in_array($data['fps'], explode(':', $data_promo['fps']))) + $check+= 1; + + // Проверка значения TICKRATE + if((isset($data['tickrate']) AND isset($data_promo['tickrate'])) AND in_array($data['tickrate'], explode(':', $data_promo['tickrate']))) + $check+= 1; + + // Проверка значения RAM + if((isset($data['ram']) AND isset($data_promo['ram'])) AND in_array($data['ram'], explode(':', $data_promo['ram']))) + $check+= 1; + + // Проверка кол-ва слот + if(isset($data_promo['slots'])) + { + // Если совпало по перечислению слот (через число:число:число ...) + if(in_array($data['slots'], explode(':', $data_promo['slots']))) + $check+= 1; + else{ + // Если указан диапозон слот + $aSl = explode('-', $data_promo['slots']); + if(count($aSl) == 2 AND ($data['slots'] >= $aSl[0] AND $data['slots'] <= $aSl[1])) + $check+= 1; + } + } + + // Проверка совпадений + if($check < $promo['hits']) + { + if(!$go) + sys::outjs(array('e' => 'Условия для данного промо-кода не выполнены.')); + + return NULL; + } + + // Если скидка + if($promo['discount']) + { + // Если не суммировать скидки + if(!$cfg['promo_discount']) + { + if(array_key_exists($data['time'], params::$disconunt['service']['time'][$type]) AND $discount) + { + $data = explode(':', params::$disconunt['service']['time'][$type][$data['time']]); + + // Если скидка + if($data[0] == '-') + { + // Если значение в процентах + if(substr($data[1], -1) == '%') + $sum = ceil($sum+$sum/100*intval($data[1])); + else + $sum = $sum+intval($data[1]); + } + } + } + + // Пересчет суммы + if(substr($promo['value'], -1) == '%') + $sum = $sum-ceil($sum/100*intval($promo['value'])); + else + $sum = $sum-intval($promo['value']); + + if(!$go) + sys::outjs(array('sum' => $sum, 'discount' => 1, 'cur' => $cfg['currency'])); + + return array('id' => $promo['id'], 'cod' => $cod, 'sum' => $sum); + + } + + // Подарочные дни + $days = intval($promo['value']); + + if(!$go) + sys::outjs(array('days' => games::parse_day($days))); + + return array('id' => $promo['id'], 'cod' => $cod, 'days' => $days); + } + + public static function info_tarif($game, $tarif, $param) + { + if($game == 'cs') + return $tarif.' / '.$param['fps'].' FPS'; + + if($game == 'mc') + return $tarif.' / '.$param['ram'].' RAM'; + + if($game == 'cssold') + return $tarif.' / '.$param['fps'].' FPS / '.$param['tickrate'].' TickRate'; + + if(in_array($game, array('css', 'csgo'))) + return $tarif.' / '.$param['tickrate'].' TickRate'; + + return $tarif; + } + + public static function maplist($id, $unit, $folder, $map, $go, $mcache = '', $ctrl = false) + { + global $user, $sql; + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + sys::outjs(array('maps', '')); + } + + // Генерация списка карт + $aMaps = array_diff(explode("\n", $ssh->get('cd '.$folder.' && du -ah | grep -e "\.bsp$" | awk \'{print $2}\'')), array('')); + + // Удаление ".bsp" + $aMaps = str_ireplace(array('./', '.bsp'), '', $aMaps); + + if($go) + { + $map = str_replace('|', '/', urldecode($map)); + + $sqlq = $ctrl ? 'control_' : ''; + + // Проверка наличия выбранной карты + if(in_array($map, $aMaps)) + $sql->query('UPDATE `'.$sqlq.'servers` set `map_start`="'.$map.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + sort($aMaps); + reset($aMaps); + + $ismap = in_array($map, $aMaps); + $maps = $ismap ? '' : ''; + + // Удаление стартовой карты + if($ismap) + unset($aMaps[array_search($map, $aMaps)]); + + foreach($aMaps as $map) + $maps .= ''; + + sys::outjs(array('maps' => $maps)); + } + + public static function owners($aRights) + { + if(array_search(0, $aRights)) + return 'Есть ограничения в доступе.'; + + return 'Выданы все права.'; + } + + public static function part($uid, $money) + { + global $cfg, $sql, $start_point; + + if($cfg['part']) + return NULL; + + $sql->query('SELECT `part` FROM `users` WHERE `id`="'.$uid.'" LIMIT 1'); + $user = $sql->get(); + + if(!$user['part']) + return NULL; + + $sql->query('SELECT `balance`, `part_money` FROM `users` WHERE `id`="'.$user['part'].'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $user = array_merge($user, $sql->get()); + + $sum = round($money/100*$cfg['part_proc'], 2); + + if($cfg['part_money']) + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']+$sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + else + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$sum).'" WHERE `id`="'.$user['part'].'" LIMIT 1'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['part'].'", `text`="'.sys::updtext(sys::text('logs', 'part'), + array('part' => $uid, 'money' => $sum)).'", `date`="'.$start_point.'", `type`="part", `money`="'.$sum.'"'); + + return NULL; + } + + public static function map($map, $aMaps) + { + if(!is_array($aMaps)) + $aMaps = explode("\n", str_ireplace(array('./', '.bsp'), '', $aMaps)); + + if(in_array($map, $aMaps)) + return false; + + return true; + } + + public static function mapsql($arr = array()) + { + $sql = 'AND ('; + + foreach($arr as $map) + $sql .= ' `name` REGEXP FROM_BASE64(\''.base64_encode('^'.$map.'\_').'\') OR'; + + return $sql == 'AND (' ? '' : substr($sql, 0, -3).')'; + } + + public static function iptables_whois($mcache) + { + $address = isset($_POST['address']) ? trim($_POST['address']) : sys::outjs(array('info' => 'Не удалось получить информацию.'), $mcache); + + if(sys::valid($address, 'ip')) + sys::outjs(array('e' => sys::text('servers', 'firewall')), $mcache); + + include(LIB.'geo.php'); + + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $data = $SxGeo->getCityFull($address); + + $info = 'Информация об IP адресе:'; + + if($data['country']['name_ru'] != '') + { + $info .= '

    Страна: '.$data['country']['name_ru']; + + if($data['city']['name_ru'] != '') + $info .= '

    Город: '.$data['city']['name_ru']; + + $info .= '

    Подсеть: '.sys::whois($address); + + }else + $info = 'Не удалось получить информацию.'; + + sys::outjs(array('info' => $info), $mcache); + } + + public static function iptables($id, $action, $source, $dest, $unit, $snw = false, $ssh = false) + { + global $cfg, $sql, $start_point; + + if(!$ssh) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$unit.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('all', 'ssh')); + } + + switch($action) + { + case 'block': + if(sys::valid($source, 'ip')) + return array('e' => sys::text('servers', 'firewall')); + + // Если подсеть + if($snw) + { + $source = sys::whois($source); + + if($source == 'не определена') + return array('e' => 'Не удалось определить подсеть для указанного адреса.'); + } + + $sql->query('SELECT `id` FROM `firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если такое правило уже добавлено или указан адрес сайта (ПУ) + if($sql->num() || ($source == $cfg['ip'] || $source == $cfg['subnet'])) + return array('s' => 'ok'); + + $sql->query('INSERT INTO `firewall` set `sip`="'.$source.'", `dest`="'.$dest[0].':'.$dest[1].'", `server`="'.$id.'", `time`="'.$start_point.'"'); + + $line = $sql->id(); + + $rule = 'iptables -I INPUT -s '.$source.' -p udp -d '.$dest[0].' --dport '.$dest[1].' -j DROP;'; + + $ssh->set($rule.' echo -e "#'.$line.';\n'.$rule.'" >> /root/'.$cfg['iptables']); + + return array('s' => 'ok'); + + case 'unblock': + if(!is_numeric($source) AND sys::valid($source, 'ip')) + return array('e' => sys::text('servers', 'firewall')); + + if(is_numeric($source)) + { + $sql->query('SELECT `id`, `sip` FROM `firewall` WHERE `id`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если такое правило отсутствует + if(!$sql->num()) + return array('s' => 'ok'); + }else{ + $sql->query('SELECT `id`, `sip` FROM `firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + // Если одиночный адрес не найден, проверить на блокировку подсети + if(!$sql->num()) + { + $source = sys::whois($source); + + $sql->query('SELECT `id` FROM `firewall` WHERE `sip`="'.$source.'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + { + $firewall = $sql->get(); + + return array('i' => 'Указанный адрес входит в заблокированную подсеть, разблокировать подсеть?', 'id' => $firewall['id']); + } + + return array('s' => 'ok'); + } + } + + $firewall = $sql->get(); + + $ssh->set('iptables -D INPUT -s '.$firewall['sip'].' -p udp -d '.$dest[0].' --dport '.$dest[1].' -j DROP;' + .'sed "`nl '.$cfg['iptables'].' | grep \"#'.$firewall['id'].'\" | awk \'{print $1","$1+1}\'`d" '.$cfg['iptables'].' > '.$cfg['iptables'].'_temp; cat '.$cfg['iptables'].'_temp > '.$cfg['iptables'].'; rm '.$cfg['iptables'].'_temp'); + + $sql->query('DELETE FROM `firewall` WHERE `id`="'.$firewall['id'].'" LIMIT 1'); + + return array('s' => 'ok'); + + case 'remove': + $sql->query('SELECT `id`, `sip`, `dest` FROM `firewall` WHERE `server`="'.$id.'"'); + + $aRule = array(); + + while($firewall = $sql->get()) + { + list($ip, $port) = explode(':', $firewall['dest']); + + $aRule[$firewall['id']] = 'iptables -D INPUT -s '.$firewall['sip'].' -p udp -d '.$ip.' --dport '.$port.' -j DROP;'; + } + + $nRule = count($aRule); + + if(!$nRule) + return NULL; + + $cmd = ''; + + foreach($aRule as $line => $rule) + $cmd .= $rule.'sed "`nl '.$cfg['iptables'].' | grep "#'.$line.'" | awk \'{print $1","$1+1}\'`d" '.$cfg['iptables'].' > '.$cfg['iptables'].'_temp; cat '.$cfg['iptables'].'_temp > '.$cfg['iptables'].'; rm '.$cfg['iptables'].'_temp'; + + $ssh->set($cmd); + + $sql->query('DELETE FROM `firewall` WHERE `server`="'.$id.'" LIMIT '.$nRule); + + return array('s' => 'ok'); + } + } + } +?> \ No newline at end of file diff --git a/system/library/games/graph.php b/system/library/games/graph.php new file mode 100644 index 0000000..493141a --- /dev/null +++ b/system/library/games/graph.php @@ -0,0 +1,404 @@ +addPoints($aOnline, 'ONLINE'); + + // CPU + $MyData->addPoints($aCPU, 'CPU'); + + // RAM + $MyData->addPoints($aRAM, 'RAM'); + + // HDD + $MyData->addPoints($aHDD, 'HDD'); + + // Время + $MyData->addPoints($aData['time'], 'TIME'); + + $MyData->setSerieOnAxis('CPU', 1); + $MyData->setSerieOnAxis('RAM', 1); + $MyData->setSerieOnAxis('HDD', 1); + $MyData->setAxisPosition(1, AXIS_POSITION_RIGHT); + + $MyData->setAxisName(0, 'Онлайн'); + $MyData->setAxisName(1, 'Нагрузка %'); + + $MyData->setAbscissa('TIME'); + + // Сечение линии + $MyData->setSerieTicks('ONLINE', 4); + + // Цвет линий + $MyData->setPalette('ONLINE', array('R' => 68, 'G' => 148, 'B' => 224)); + $MyData->setPalette('CPU', array('R' => 216, 'G' => 65, 'B' => 65)); + $MyData->setPalette('RAM', array('R' => 26, 'G' => 150, 'B' => 38)); + $MyData->setPalette('HDD', array('R' => 205, 'G' => 196, 'B' => 37)); + + $myPicture = new pImage(896, 220, $MyData); + + $myPicture->drawFilledRectangle(0, 0, 896, 220, array('R' => 255, 'G' => 255, 'B' => 255)); + + $myPicture->drawRectangle(0, 0, 895, 219, array('R' => 221, 'G' => 221, 'B' => 221)); + + $myPicture->setFontProperties(array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8)); + $myPicture->setGraphArea(40, 20, 616, 190); + $myPicture->drawFilledRectangle(40, 20, 616, 190, array('R' => 240, 'G' => 242, 'B' => 242, 'Alpha' => 100)); + $myPicture->drawScale(array('XMargin' => 5, 'YMargin' => 5, 'GridR' => 76, 'GridG' => 109, 'GridB' => 120, 'LabelSkip' => 0, 'DrawSubTicks' => TRUE, 'Mode' => SCALE_MODE_MANUAL, 'Factors' => array(0 => array($slots), 1 => array(25, 50, 75, 100)), 'ManualScale' => array(0 => array('Min' => 0, 'Max' => $slots), 1 => array('Min' => 0, 'Max' => 100)))); + + $myPicture->drawText(676, 34, 'Средний онлайн: '.graph::average($aOnline), array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 54, 'Средняя нагрузка (CPU): '.graph::average($aCPU).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 74, 'Средняя нагрузка (RAM): '.graph::average($aRAM).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 94, 'Средняя нагрузка (HDD): '.graph::average($aHDD).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + + $myPicture->drawText(676, 129, 'Максимальный онлайн: '.max($aOnline), array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 153, 'Максимальная нагрузка (CPU): '.max($aCPU).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 173, 'Максимальная нагрузка (RAM): '.max($aRAM).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + $myPicture->drawText(676, 193, 'Максимальная нагрузка (HDD): '.max($aHDD).'%', array('R' => 25, 'G' => 25, 'B' => 25, 'FontName' => LIB.'games/graph/fonts/arianamu.ttf', 'FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMLEFT)); + + $myPicture->setFontProperties(array('FontName'=> LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 7)); + $myPicture->drawSplineChart(); + $myPicture->setShadow(FALSE); + + $myPicture->drawLegend(466, 10, array('Style' => LEGEND_NOBORDER, 'Mode' => LEGEND_HORIZONTAL)); + + $myPicture->render(TEMP.(md5($key.'full_'.$time)).'.png'); + + unset($MyData, $myPicture); + + return NULL; + } + + public static function first($server, $aPoints, $aStyle, $style, $key) + { + global $cfg, $aGname; + + $MyData = new pData(); + + // Значения + $MyData->addPoints($aPoints, 'ONLINE'); + + $MyData->addPoints(array(VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID), 'NONE'); + $MyData->setAbscissa('NONE'); + + // Цвет линии + $MyData->setPalette('ONLINE', $aStyle[$style]['line']); + + // Размер баннера + $myPicture = new pImage(160, 248, $MyData); + + // Цвет фона + $myPicture->drawFilledRectangle(0, 0, 160, 248, $aStyle[$style]['fon']); + + // Обводка + $myPicture->drawRectangle(0, 0, 159, 247, $aStyle[$style]['border']); + + // Шрифт текста + $myPicture->setFontProperties(array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 5))); + + // Размер графика + $myPicture->setGraphArea(35, 160, 150, 210); + + // Цвет фона графика + $myPicture->drawFilledRectangle(35, 160, 150, 210, $aStyle[$style]['graph']); + + // График + $myPicture->drawScale(array('XMargin' => 5, 'YMargin' => 5, 'CycleBackground' => TRUE, 'LabelSkip' => 0, 'DrawSubTicks' => TRUE, 'Mode' => SCALE_MODE_MANUAL, 'Factors' => array(0 => array($server['slots_start'])), 'ManualScale' => array(0 => array('Min' => 0, 'Max' => $server['slots_start'])))); + + // Название игрового сервера + $myPicture->drawFilledRectangle(0, 0, 18, 248, $aStyle[$style]['leftbox']); + $myPicture->drawText(14, 245, $server['name'], array_merge($aStyle[$style]['boxcolor'], array('Angle' => 90, 'FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 10))); + $myPicture->drawFilledRectangle(0, 0, 18, 5, $aStyle[$style]['leftbox']); + + // Адрес игрового сервера + $myPicture->drawFilledRectangle(25, 5, 153, 18, $aStyle[$style]['box']); + $myPicture->drawText(28, 17, 'Адрес сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(26, 30, $server['address'], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Статус игрового сервера + $myPicture->drawFilledRectangle(25, 35, 153, 48, $aStyle[$style]['box']); + $myPicture->drawText(28, 47, 'Состояние сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(26, 62, graph::status($server['status'], $server['map']), array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Игроки на игровом сервере + $myPicture->drawFilledRectangle(25, 65, 153, 78, $aStyle[$style]['box']); + $myPicture->drawText(28, 77, 'Игроки на сервере', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(26, 92, $server['online'].' / '.$server['slots_start'], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Полоска загрузки + $myPicture->drawProgress(83, 82, ceil($server['slots_start']/100*$server['online']), array_merge($aStyle[$style]['progress'], array('Width' => 70, 'Height' => 8))); + + // Тип игрового сервера + $myPicture->drawFilledRectangle(25, 95, 153, 108, $aStyle[$style]['box']); + $myPicture->drawText(28, 107, 'Тип сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(26, 122, $aGname[$server['game']], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Хостинг игровых серверов + $myPicture->drawText(89, 230, $cfg['graph'], array_merge($aStyle[$style]['color'], array('FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMMIDDLE))); + $myPicture->drawText(89, 245, 'Хостинг игровых серверов', array_merge($aStyle[$style]['color'], array('FontSize' => 8, 'Align' => TEXT_ALIGN_BOTTOMMIDDLE))); + + $myPicture->drawSplineChart(); + + $myPicture->render(TEMP.(md5($key.$style.'first')).'.png'); + + unset($MyData, $myPicture); + + return NULL; + } + + public static function second($server, $aPoints, $aStyle, $style, $key) + { + global $cfg, $aGname; + + $MyData = new pData(); + + // Значения + $MyData->addPoints($aPoints, 'ONLINE'); + + $MyData->addPoints(array(VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID, VOID), 'NONE'); + $MyData->setAbscissa('NONE'); + + // Цвет линии + $MyData->setPalette('ONLINE', $aStyle[$style]['line']); + + // Размер баннера + $myPicture = new pImage(560, 95, $MyData); + + // Цвет фона + $myPicture->drawFilledRectangle(0, 0, 560, 95, $aStyle[$style]['fon']); + + // Название игрового сервера + $myPicture->drawFilledRectangle(5, 5, 410, 18, $aStyle[$style]['box']); + $myPicture->drawText(8, 17, 'Название сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(6, 31, $server['name'], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Костыль для "обрезания" названия сервера + $myPicture->drawFilledRectangle(405, 19, 560, 35, $aStyle[$style]['fon']); + + // Обводка + $myPicture->drawRectangle(0, 0, 559, 94, $aStyle[$style]['border']); + + // Шрифт текста + $myPicture->setFontProperties(array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 5))); + + // Размер графика + $myPicture->setGraphArea(430, 5, 554, 60); + + // Цвет фона графика + $myPicture->drawFilledRectangle(430, 5, 554, 60, $aStyle[$style]['graph']); + + // График + $myPicture->drawScale(array('XMargin' => 5, 'YMargin' => 5, 'CycleBackground' => TRUE, 'LabelSkip' => 0, 'DrawSubTicks' => TRUE, 'Mode' => SCALE_MODE_MANUAL, 'Factors' => array(0 => array($server['slots_start'])), 'ManualScale' => array(0 => array('Min' => 0, 'Max' => $server['slots_start'])))); + + // Адрес игрового сервера + $myPicture->drawFilledRectangle(5, 36, 210, 49, $aStyle[$style]['box']); + $myPicture->drawText(8, 48, 'Адрес сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(6, 62, $server['address'], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Статус игрового сервера + $myPicture->drawFilledRectangle(215, 36, 410, 49, $aStyle[$style]['box']); + $myPicture->drawText(218, 48, 'Состояние сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(216, 62, graph::status($server['status'], $server['map']), array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Игроки на игровом сервере + $myPicture->drawFilledRectangle(5, 67, 210, 80, $aStyle[$style]['box']); + $myPicture->drawText(8, 79, 'Игроки на сервере', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(6, 93, $server['online'].' / '.$server['slots_start'], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Полоска загрузки + $myPicture->drawProgress(90, 83, ceil($server['slots_start']/100*$server['online']), array_merge($aStyle[$style]['progress'], array('Width' => 120, 'Height' => 8))); + + // Тип игрового сервера + $myPicture->drawFilledRectangle(215, 67, 410, 80, $aStyle[$style]['box']); + $myPicture->drawText(218, 79, 'Тип сервера', array_merge($aStyle[$style]['boxcolor'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + $myPicture->drawText(216, 91, $aGname[$server['game']], array_merge($aStyle[$style]['color'], array('FontName' => LIB.'games/graph/fonts/tahoma.ttf', 'FontSize' => 8))); + + // Хостинг игровых серверов + $myPicture->drawText(490, 77, $cfg['graph'], array('FontSize' => 10, 'Align' => TEXT_ALIGN_BOTTOMMIDDLE)); + $myPicture->drawText(490, 90, 'Хостинг игровых серверов', array('FontSize' => 8, 'Align' => TEXT_ALIGN_BOTTOMMIDDLE)); + + $myPicture->drawSplineChart(); + + $myPicture->render(TEMP.(md5($key.$style.'second')).'.png'); + + unset($MyData, $myPicture); + + return NULL; + } + + public static function online_day($server, $max) + { + global $sql, $start_point; + + $time = $start_point-86400; + + $aOnline = array(); + + $aSel = array(); + + $sql->query('SELECT `online` FROM `graph_hour` WHERE `server`="'.$server.'" AND `time`>"'.$time.'" ORDER BY `id` DESC LIMIT 24'); + while($value = $sql->get()) + $aSel[] = $value['online']; + + $n = count($aSel); + + $n = $n > 1 ? $n-1 : 0; + + if($n) + { + for($i = $n; $i >= 0; $i-=1) + $aOnline[] = $aSel[$i] > $max ? $max : $aSel[$i]; + } + + $add = count($aOnline); + + if($add < 24) + { + for($i = $n; $i <= 23; $i+=1) + $aOnline[] = 0; + } + + return $aOnline; + } + + private static function graph_data($period, $server, $max) + { + global $sql, $start_point; + + $aData = array( + 'limit' => array( + 'day' => 24, + 'week' => 7, + 'month' => 30 + ), + + 'for' => array( + 'day' => 23, + 'week' => 6, + 'month' => 29 + ), + + 'from' => array( + 'day' => 'graph_hour', + 'week' => 'graph_day', + 'month' => 'graph_day' + ), + + 'time' => array( + 'day' => 86400, + 'week' => 604800, + 'month' => 2592000 + ) + ); + + $time = $start_point-$aData['time'][$period]; + + $aOnline = array(); + + $aCPU = array(); + $aRAM = array(); + $aHDD = array(); + $aTime = array(); + + $aSel = array(); + + $sql->query('SELECT `online`, `cpu`, `ram`, `hdd`, `time` FROM `'.$aData['from'][$period].'` WHERE `server`="'.$server.'" AND `time`>"'.$time.'" ORDER BY `id` DESC LIMIT '.$aData['limit'][$period]); + while($value = $sql->get()) + $aSel[] = array('online' => $value['online'], 'cpu' => $value['cpu'], 'ram' => $value['ram'], 'hdd' => $value['hdd'], 'time' => $value['time']); + + $n = count($aSel); + + $n = $n > 1 ? $n-1 : 0; + + $next = true; + + if(isset($aSel[$n]['online'])) + { + for($i = $n; $i >= 0; $i-=1) + { + $aOnline[] = $aSel[$i]['online'] > $max ? $max : $aSel[$i]['online']; + + $aCPU[] = $aSel[$i]['cpu']; + $aRAM[] = $aSel[$i]['ram']; + $aHDD[] = $aSel[$i]['hdd']; + + if($next) + { + $aTime[] = VOID; + + $next = false; + }else{ + $aTime[] = $period == 'day' ? date('H:i', $aSel[$i]['time']) : date('d.m', $aSel[$i]['time']); + + $next = true; + } + } + } + + $add = count($aOnline); + + for($i = $add; $i <= $aData['for'][$period]; $i+=1) + { + $aOnline[] = 0; + + $aCPU[] = 0; + $aRAM[] = 0; + $aHDD[] = 0; + + $aTime[] = VOID; + } + + return array('online' => $aOnline, 'cpu' => $aCPU, 'ram' => $aRAM, 'hdd' => $aHDD, 'time' => $aTime); + } + + private static function status($status, $map) + { + switch($status) + { + case 'working': + return 'Карта: '.$map; + case 'off': + return 'Статус: выключен'; + case 'start': + return 'Статус: запускается'; + case 'restart': + return 'Статус: перезапускается'; + case 'change': + return 'Статус: меняется карта'; + case 'install': + return 'Статус: устанавливается'; + case 'reinstall': + return 'Статус: переустанавливается'; + case 'update': + return 'Статус: обновляется'; + case 'recovery': + return 'Статус: восстанавливается'; + case 'overdue': + return 'Статус: просрочен'; + case 'blocked': + return 'Статус: заблокирован'; + } + } + + private static function average($arr) + { + return !count($arr) ? 0 : ceil(array_sum($arr)/count($arr)); + } + } +?> \ No newline at end of file diff --git a/system/library/games/graph/fonts/arianamu.ttf b/system/library/games/graph/fonts/arianamu.ttf new file mode 100644 index 0000000..96499aa Binary files /dev/null and b/system/library/games/graph/fonts/arianamu.ttf differ diff --git a/system/library/games/graph/fonts/tahoma.ttf b/system/library/games/graph/fonts/tahoma.ttf new file mode 100644 index 0000000..bd62e60 Binary files /dev/null and b/system/library/games/graph/fonts/tahoma.ttf differ diff --git a/system/library/games/graph/pData.php b/system/library/games/graph/pData.php new file mode 100644 index 0000000..dc79cb9 --- /dev/null +++ b/system/library/games/graph/pData.php @@ -0,0 +1,875 @@ +array('R'=>188,'G'=>224,'B'=>46,'Alpha'=>100), + '1'=>array('R'=>224,'G'=>100,'B'=>46,'Alpha'=>100), + '2'=>array('R'=>224,'G'=>214,'B'=>46,'Alpha'=>100), + '3'=>array('R'=>46,'G'=>151,'B'=>224,'Alpha'=>100), + '4'=>array('R'=>176,'G'=>46,'B'=>224,'Alpha'=>100), + '5'=>array('R'=>224,'G'=>46,'B'=>117,'Alpha'=>100), + '6'=>array('R'=>92,'G'=>224,'B'=>46,'Alpha'=>100), + '7'=>array('R'=>224,'G'=>176,'B'=>46,'Alpha'=>100)); + + function pData() + { + $this->Data = ''; + $this->Data['XAxisDisplay'] = AXIS_FORMAT_DEFAULT; + $this->Data['XAxisFormat'] = NULL; + $this->Data['XAxisName'] = NULL; + $this->Data['XAxisUnit'] = NULL; + $this->Data['Abscissa'] = NULL; + $this->Data['AbsicssaPosition'] = AXIS_POSITION_BOTTOM; + $this->Data['Axis'][0]['Display'] = AXIS_FORMAT_DEFAULT; + $this->Data['Axis'][0]['Position'] = AXIS_POSITION_LEFT; + $this->Data['Axis'][0]['Identity'] = AXIS_Y; + } + + function addPoints($Values, $SerieName = 'Serie1') + { + if(!isset($this->Data['Series'][$SerieName])) + $this->initialise($SerieName); + + if(is_array($Values)) + { + foreach($Values as $Key => $Value) + $this->Data['Series'][$SerieName]['Data'][] = $Value; + }else + $this->Data['Series'][$SerieName]['Data'][] = $Values; + + if($Values != VOID) + { + $StrippedData = $this->stripVOID($this->Data['Series'][$SerieName]['Data']); + + if(empty($StrippedData)) + { + $this->Data['Series'][$SerieName]['Max'] = 0; + $this->Data['Series'][$SerieName]['Min'] =0; + return(0); + } + + $this->Data['Series'][$SerieName]['Max'] = max($StrippedData); + $this->Data['Series'][$SerieName]['Min'] = min($StrippedData); + } + } + + function stripVOID($Values) + { + if(!is_array($Values)) + return(array()); + + $Result = array(); + + foreach($Values as $Key => $Value) + { + if($Value != VOID) + $Result[] = $Value; + } + + return($Result); + } + + function getSerieCount($Serie) + { + if(isset($this->Data['Series'][$Serie]['Data'])) + return(sizeof($this->Data['Series'][$Serie]['Data'])); + + return(0); + } + + function removeSerie($Series) + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie])) + unset($this->Data['Series'][$Serie]); + } + } + + function getValueAt($Serie,$Index=0) + { + if(isset($this->Data['Series'][$Serie]['Data'][$Index])) + return($this->Data['Series'][$Serie]['Data'][$Index]); + + return(NULL); + } + + function getValues($Serie) + { + if(isset($this->Data['Series'][$Serie]['Data'])) + return($this->Data['Series'][$Serie]['Data']); + + return(NULL); + } + + function reverseSerie($Series) + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie]['Data'])) + $this->Data['Series'][$Serie]['Data'] = array_reverse($this->Data['Series'][$Serie]['Data']); + } + } + + function getSum($Serie) + { + if(isset($this->Data['Series'][$Serie])) + return(array_sum($this->Data['Series'][$Serie]['Data'])); + + return(NULL); + } + + function getMax($Serie) + { + if(isset($this->Data['Series'][$Serie]['Max'])) + return($this->Data['Series'][$Serie]['Max']); + + return(NULL); + } + + function getMin($Serie) + { + if(isset($this->Data['Series'][$Serie]['Min'])) + return($this->Data['Series'][$Serie]['Min']); + + return(NULL); + } + + function setSerieShape($Series, $Shape = SERIE_SHAPE_FILLEDCIRCLE) + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie])) + $this->Data['Series'][$Serie]['Shape'] = $Shape; + } + } + + function setSerieDescription($Series, $Description = 'My serie') + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie])) + $this->Data['Series'][$Serie]['Description'] = $Description; + } + } + + function setSerieDrawable($Series, $Drawable = TRUE) + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie])) + $this->Data['Series'][$Serie]['isDrawable'] = $Drawable; + } + } + + function setSeriePicture($Series,$Picture=NULL) + { + if(!is_array($Series)) + $Series = $this->convertToArray($Series); + + foreach($Series as $Key => $Serie) + { + if(isset($this->Data['Series'][$Serie])) + $this->Data['Series'][$Serie]['Picture'] = $Picture; + } + } + + function setXAxisName($Name) + { + $this->Data['XAxisName'] = $Name; + } + + function setXAxisDisplay($Mode, $Format = NULL) + { + $this->Data['XAxisDisplay'] = $Mode; + $this->Data['XAxisFormat'] = $Format; + } + + function setXAxisUnit($Unit) + { + $this->Data['XAxisUnit'] = $Unit; + } + + function setAbscissa($Serie) + { + if(isset($this->Data['Series'][$Serie])) + $this->Data['Abscissa'] = $Serie; + } + + function setAbsicssaPosition($Position = AXIS_POSITION_BOTTOM) + { + $this->Data['AbsicssaPosition'] = $Position; + } + + function setAbscissaName($Name) + { + $this->Data['AbscissaName'] = $Name; + } + + function setScatterSerie($SerieX, $SerieY, $ID = 0) + { + if(isset($this->Data['Series'][$SerieX]) && isset($this->Data['Series'][$SerieY])) + { + $this->initScatterSerie($ID); + $this->Data['ScatterSeries'][$ID]['X'] = $SerieX; + $this->Data['ScatterSeries'][$ID]['Y'] = $SerieY; + } + } + + function setScatterSerieShape($ID, $Shape = SERIE_SHAPE_FILLEDCIRCLE) + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['Shape'] = $Shape; + } + + function setScatterSerieDescription($ID, $Description = 'My serie') + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['Description'] = $Description; + } + + function setScatterSeriePicture($ID, $Picture = NULL) + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['Picture'] = $Picture; + } + + function setScatterSerieDrawable($ID, $Drawable = TRUE) + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['isDrawable'] = $Drawable; + } + + function setScatterSerieTicks($ID, $Width = 0) + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['Ticks'] = $Width; + } + + function setScatterSerieWeight($ID, $Weight = 0) + { + if(isset($this->Data['ScatterSeries'][$ID])) + $this->Data['ScatterSeries'][$ID]['Weight'] = $Weight; + } + + function setScatterSerieColor($ID, $Format) + { + $R = isset($Format['R']) ? $Format['R'] : 0; + $G = isset($Format['G']) ? $Format['G'] : 0; + $B = isset($Format['B']) ? $Format['B'] : 0; + $Alpha = isset($Format['Alpha']) ? $Format['Alpha'] : 100; + + if(isset($this->Data['ScatterSeries'][$ID])) + { + $this->Data['ScatterSeries'][$ID]['Color']['R'] = $R; + $this->Data['ScatterSeries'][$ID]['Color']['G'] = $G; + $this->Data['ScatterSeries'][$ID]['Color']['B'] = $B; + $this->Data['ScatterSeries'][$ID]['Color']['Alpha'] = $Alpha; + } + } + + function limits() + { + $GlobalMin = ABSOLUTE_MAX; + $GlobalMax = ABSOLUTE_MIN; + + foreach($this->Data['Series'] as $Key => $Value) + { + if($this->Data['Abscissa'] != $Key && $this->Data['Series'][$Key]['isDrawable'] == TRUE) + { + if($GlobalMin > $this->Data['Series'][$Key]['Min']) + $GlobalMin = $this->Data['Series'][$Key]['Min']; + + if($GlobalMax < $this->Data['Series'][$Key]['Max']) + $GlobalMax = $this->Data['Series'][$Key]['Max']; + } + } + + $this->Data['Min'] = $GlobalMin; + $this->Data['Max'] = $GlobalMax; + + return(array($GlobalMin,$GlobalMax)); + } + + function drawAll() + { + foreach($this->Data['Series'] as $Key => $Value) + { + if($this->Data['Abscissa'] != $Key) + $this->Data['Series'][$Key]['isDrawable'] = TRUE; + } + } + + function getSerieAverage($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $SerieData = $this->stripVOID($this->Data['Series'][$Serie]['Data']); + + return(array_sum($SerieData)/sizeof($SerieData)); + } + + return(NULL); + } + + function getGeometricMean($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $SerieData = $this->stripVOID($this->Data['Series'][$Serie]['Data']); + $Seriesum = 1; + + foreach($SerieData as $Key => $Value) + $Seriesum = $Seriesum * $Value; + + return(pow($Seriesum,1/sizeof($SerieData))); + } + + return(NULL); + } + + function getHarmonicMean($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $SerieData = $this->stripVOID($this->Data['Series'][$Serie]['Data']); + $Seriesum = 0; + + foreach($SerieData as $Key => $Value) + $Seriesum = $Seriesum + 1/$Value; + + return(sizeof($SerieData)/$Seriesum); + } + + return(NULL); + } + + function getStandardDeviation($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $Average = $this->getSerieAverage($Serie); + $SerieData = $this->stripVOID($this->Data['Series'][$Serie]['Data']); + + $DeviationSum = 0; + + foreach($SerieData as $Key => $Value) + $DeviationSum = $DeviationSum + ($Value-$Average)*($Value-$Average); + + $Deviation = sqrt($DeviationSum/count($SerieData)); + + return($Deviation); + } + + return(NULL); + } + + function getCoefficientOfVariation($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $Average = $this->getSerieAverage($Serie); + $StandardDeviation = $this->getStandardDeviation($Serie); + + if($StandardDeviation != 0) + return($StandardDeviation/$Average); + } + + return(NULL); + } + + function getSerieMedian($Serie) + { + if(isset($this->Data['Series'][$Serie])) + { + $SerieData = $this->stripVOID($this->Data['Series'][$Serie]['Data']); + + sort($SerieData); + + $SerieCenter = floor(sizeof($SerieData)/2); + + if(isset($SerieData[$SerieCenter])) + return($SerieData[$SerieCenter]); + } + + return(NULL); + } + + function getSeriePercentile($Serie = 'Serie1', $Percentil = 95) + { + if(!isset($this->Data['Series'][$Serie]['Data'])) + return(NULL); + + $Values = count($this->Data['Series'][$Serie]['Data'])-1; + + if($Values < 0) + $Values = 0; + + $PercentilID = floor(($Values/100)*$Percentil+.5); + $SortedValues = $this->Data['Series'][$Serie]['Data']; + + sort($SortedValues); + + if(is_numeric($SortedValues[$PercentilID])) + return($SortedValues[$PercentilID]); + + return(NULL); + } + + function addRandomValues($SerieName = 'Serie1', $Options = '') + { + $Values = isset($Options['Values']) ? $Options['Values'] : 20; + $Min = isset($Options['Min']) ? $Options['Min'] : 0; + $Max = isset($Options['Max']) ? $Options['Max'] : 100; + $withFloat = isset($Options['withFloat']) ? $Options['withFloat'] : FALSE; + + for($i = 0; $i <= $Values; $i+=1) + { + if($withFloat) + $Value = rand($Min*100,$Max*100)/100; + else + $Value = rand($Min, $Max); + + $this->addPoints($Value,$SerieName); + } + } + + function containsData() + { + if(!isset($this->Data['Series'])) + return(FALSE); + + $Result = FALSE; + + foreach($this->Data['Series'] as $Key => $Value) + { + if($this->Data['Abscissa'] != $Key && $this->Data['Series'][$Key]['isDrawable'] == TRUE) + $Result=TRUE; + } + + return($Result); + } + + function setAxisDisplay($AxisID, $Mode = AXIS_FORMAT_DEFAULT, $Format = NULL) + { + if(isset($this->Data['Axis'][$AxisID])) + { + $this->Data['Axis'][$AxisID]['Display'] = $Mode; + + if($Format != NULL) + $this->Data['Axis'][$AxisID]['Format'] = $Format; + } + } + + function setAxisPosition($AxisID, $Position = AXIS_POSITION_LEFT) + { + if(isset($this->Data['Axis'][$AxisID])) + { + $this->Data['Axis'][$AxisID]['Position'] = $Position; + } + } + + /* Associate an unit to an axis */ + function setAxisUnit($AxisID,$Unit) + { if ( isset($this->Data['Axis'][$AxisID] ) ) { $this->Data['Axis'][$AxisID]['Unit'] = $Unit; } } + + /* Associate a name to an axis */ + function setAxisName($AxisID,$Name) + { if ( isset($this->Data['Axis'][$AxisID] ) ) { $this->Data['Axis'][$AxisID]['Name'] = $Name; } } + + /* Associate a color to an axis */ + function setAxisColor($AxisID,$Format) + { + $R = isset($Format['R']) ? $Format['R'] : 0; + $G = isset($Format['G']) ? $Format['G'] : 0; + $B = isset($Format['B']) ? $Format['B'] : 0; + $Alpha = isset($Format['Alpha']) ? $Format['Alpha'] : 100; + + if ( isset($this->Data['Axis'][$AxisID] ) ) + { + $this->Data['Axis'][$AxisID]['Color']['R'] = $R; + $this->Data['Axis'][$AxisID]['Color']['G'] = $G; + $this->Data['Axis'][$AxisID]['Color']['B'] = $B; + $this->Data['Axis'][$AxisID]['Color']['Alpha'] = $Alpha; + } + } + + + /* Design an axis as X or Y member */ + function setAxisXY($AxisID,$Identity=AXIS_Y) + { if ( isset($this->Data['Axis'][$AxisID] ) ) { $this->Data['Axis'][$AxisID]['Identity'] = $Identity; } } + + /* Associate one data serie with one axis */ + function setSerieOnAxis($Series,$AxisID) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) + { + $PreviousAxis = $this->Data['Series'][$Serie]['Axis']; + + /* Create missing axis */ + if ( !isset($this->Data['Axis'][$AxisID] ) ) + { $this->Data['Axis'][$AxisID]['Position'] = AXIS_POSITION_LEFT; $this->Data['Axis'][$AxisID]['Identity'] = AXIS_Y;} + + $this->Data['Series'][$Serie]['Axis'] = $AxisID; + + /* Cleanup unused axis */ + $Found = FALSE; + foreach($this->Data['Series'] as $SerieName => $Values) { if ( $Values['Axis'] == $PreviousAxis ) { $Found = TRUE; } } + if (!$Found) { unset($this->Data['Axis'][$PreviousAxis]); } + } + } + + /* define if a serie should be draw with ticks */ + function setSerieTicks($Series,$Width=0) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if ( isset($this->Data['Series'][$Serie]) ) { $this->Data['Series'][$Serie]['Ticks'] = $Width; } } + } + + /* define if a serie should be draw with a special weight */ + function setSerieWeight($Series,$Weight=0) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if ( isset($this->Data['Series'][$Serie]) ) { $this->Data['Series'][$Serie]['Weight'] = $Weight; } } + } + + /* Returns the palette of the given serie */ + function getSeriePalette($Serie) + { + if ( !isset($this->Data['Series'][$Serie]) ) { return(NULL); } + + $Result = ''; + $Result['R'] = $this->Data['Series'][$Serie]['Color']['R']; + $Result['G'] = $this->Data['Series'][$Serie]['Color']['G']; + $Result['B'] = $this->Data['Series'][$Serie]['Color']['B']; + $Result['Alpha'] = $this->Data['Series'][$Serie]['Color']['Alpha']; + + return($Result); + } + + /* Set the color of one serie */ + function setPalette($Series,$Format=NULL) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + + foreach($Series as $Key => $Serie) + { + $R = isset($Format['R']) ? $Format['R'] : 0; + $G = isset($Format['G']) ? $Format['G'] : 0; + $B = isset($Format['B']) ? $Format['B'] : 0; + $Alpha = isset($Format['Alpha']) ? $Format['Alpha'] : 100; + + if ( isset($this->Data['Series'][$Serie]) ) + { + $OldR = $this->Data['Series'][$Serie]['Color']['R']; $OldG = $this->Data['Series'][$Serie]['Color']['G']; $OldB = $this->Data['Series'][$Serie]['Color']['B']; + $this->Data['Series'][$Serie]['Color']['R'] = $R; + $this->Data['Series'][$Serie]['Color']['G'] = $G; + $this->Data['Series'][$Serie]['Color']['B'] = $B; + $this->Data['Series'][$Serie]['Color']['Alpha'] = $Alpha; + + /* Do reverse processing on the internal palette array */ + foreach ($this->Palette as $Key => $Value) + { if ($Value['R'] == $OldR && $Value['G'] == $OldG && $Value['B'] == $OldB) { $this->Palette[$Key]['R'] = $R; $this->Palette[$Key]['G'] = $G; $this->Palette[$Key]['B'] = $B; $this->Palette[$Key]['Alpha'] = $Alpha;} } + } + } + } + + /* Load a palette file */ + function loadPalette($FileName,$Overwrite=FALSE) + { + if ( !file_exists($FileName) ) { return(-1); } + if ( $Overwrite ) { $this->Palette = ''; } + + $fileHandle = @fopen($FileName, 'r'); + if (!$fileHandle) { return(-1); } + while (!feof($fileHandle)) + { + $buffer = fgets($fileHandle, 4096); + if ( preg_match('/,/',$buffer) ) + { + list($R,$G,$B,$Alpha) = preg_split('/,/',$buffer); + if ( $this->Palette == '' ) { $ID = 0; } else { $ID = count($this->Palette); } + $this->Palette[$ID] = array('R'=>$R,'G'=>$G,'B'=>$B,'Alpha'=>$Alpha); + } + } + fclose($fileHandle); + + /* Apply changes to current series */ + $ID = 0; + if ( isset($this->Data['Series'])) + { + foreach($this->Data['Series'] as $Key => $Value) + { + if ( !isset($this->Palette[$ID]) ) + $this->Data['Series'][$Key]['Color'] = array('R'=>0,'G'=>0,'B'=>0,'Alpha'=>0); + else + $this->Data['Series'][$Key]['Color'] = $this->Palette[$ID]; + $ID++; + } + } + } + + /* Initialise a given scatter serie */ + function initScatterSerie($ID) + { + if ( isset($this->Data['ScatterSeries'][$ID]) ) { return(0); } + + $this->Data['ScatterSeries'][$ID]['Description'] = 'Scatter '.$ID; + $this->Data['ScatterSeries'][$ID]['isDrawable'] = TRUE; + $this->Data['ScatterSeries'][$ID]['Picture'] = NULL; + $this->Data['ScatterSeries'][$ID]['Ticks'] = 0; + $this->Data['ScatterSeries'][$ID]['Weight'] = 0; + + if ( isset($this->Palette[$ID]) ) + $this->Data['ScatterSeries'][$ID]['Color'] = $this->Palette[$ID]; + else + { + $this->Data['ScatterSeries'][$ID]['Color']['R'] = rand(0,255); + $this->Data['ScatterSeries'][$ID]['Color']['G'] = rand(0,255); + $this->Data['ScatterSeries'][$ID]['Color']['B'] = rand(0,255); + $this->Data['ScatterSeries'][$ID]['Color']['Alpha'] = 100; + } + } + + /* Initialise a given serie */ + function initialise($Serie) + { + if ( isset($this->Data['Series']) ) { $ID = count($this->Data['Series']); } else { $ID = 0; } + + $this->Data['Series'][$Serie]['Description'] = $Serie; + $this->Data['Series'][$Serie]['isDrawable'] = TRUE; + $this->Data['Series'][$Serie]['Picture'] = NULL; + $this->Data['Series'][$Serie]['Max'] = NULL; + $this->Data['Series'][$Serie]['Min'] = NULL; + $this->Data['Series'][$Serie]['Axis'] = 0; + $this->Data['Series'][$Serie]['Ticks'] = 0; + $this->Data['Series'][$Serie]['Weight'] = 0; + $this->Data['Series'][$Serie]['Shape'] = SERIE_SHAPE_FILLEDCIRCLE; + + if ( isset($this->Palette[$ID]) ) + $this->Data['Series'][$Serie]['Color'] = $this->Palette[$ID]; + else + { + $this->Data['Series'][$Serie]['Color']['R'] = rand(0,255); + $this->Data['Series'][$Serie]['Color']['G'] = rand(0,255); + $this->Data['Series'][$Serie]['Color']['B'] = rand(0,255); + $this->Data['Series'][$Serie]['Color']['Alpha'] = 100; + } + } + + function normalize($NormalizationFactor=100,$UnitChange=NULL,$Round=1) + { + $Abscissa = $this->Data['Abscissa']; + + $SelectedSeries = ''; + $MaxVal = 0; + foreach($this->Data['Axis'] as $AxisID => $Axis) + { + if ( $UnitChange != NULL ) { $this->Data['Axis'][$AxisID]['Unit'] = $UnitChange; } + + foreach($this->Data['Series'] as $SerieName => $Serie) + { + if ($Serie['Axis'] == $AxisID && $Serie['isDrawable'] == TRUE && $SerieName != $Abscissa) + { + $SelectedSeries[$SerieName] = $SerieName; + + if ( count($Serie['Data'] ) > $MaxVal ) { $MaxVal = count($Serie['Data']); } + } + } + } + + for($i=0;$i<=$MaxVal-1;$i++) + { + $Factor = 0; + foreach ($SelectedSeries as $Key => $SerieName ) + { + $Value = $this->Data['Series'][$SerieName]['Data'][$i]; + if ( $Value != VOID ) + $Factor = $Factor + abs($Value); + } + + if ( $Factor != 0 ) + { + $Factor = $NormalizationFactor / $Factor; + + foreach ($SelectedSeries as $Key => $SerieName ) + { + $Value = $this->Data['Series'][$SerieName]['Data'][$i]; + + if ( $Value != VOID && $Factor != $NormalizationFactor ) + $this->Data['Series'][$SerieName]['Data'][$i] = round(abs($Value)*$Factor,$Round); + elseif ( $Value == VOID || $Value == 0 ) + $this->Data['Series'][$SerieName]['Data'][$i] = VOID; + elseif ( $Factor == $NormalizationFactor ) + $this->Data['Series'][$SerieName]['Data'][$i] = $NormalizationFactor; + } + } + } + + foreach ($SelectedSeries as $Key => $SerieName ) + { + $this->Data['Series'][$SerieName]['Max'] = max($this->stripVOID($this->Data['Series'][$SerieName]['Data'])); + $this->Data['Series'][$SerieName]['Min'] = min($this->stripVOID($this->Data['Series'][$SerieName]['Data'])); + } + } + + /* Load data from a CSV (or similar) data source */ + function importFromCSV($FileName,$Options='') + { + $Delimiter = isset($Options['Delimiter']) ? $Options['Delimiter'] : ','; + $GotHeader = isset($Options['GotHeader']) ? $Options['GotHeader'] : FALSE; + $SkipColumns = isset($Options['SkipColumns']) ? $Options['SkipColumns'] : array(-1); + $DefaultSerieName = isset($Options['DefaultSerieName']) ? $Options['DefaultSerieName'] : 'Serie'; + + $Handle = @fopen($FileName,'r'); + if ($Handle) + { + $HeaderParsed = FALSE; $SerieNames = ''; + while (!feof($Handle)) + { + $Buffer = fgets($Handle, 4096); + $Buffer = str_replace(chr(10),'',$Buffer); + $Buffer = str_replace(chr(13),'',$Buffer); + $Values = preg_split('/'.$Delimiter.'/',$Buffer); + + if ( $Buffer != '' ) + { + if ( $GotHeader && !$HeaderParsed ) + { + foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $Name; } } + $HeaderParsed = TRUE; + } + else + { + if ($SerieNames == '' ) { foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $DefaultSerieName.$Key; } } } + foreach($Values as $Key => $Value) { if ( !in_array($Key,$SkipColumns) ) { $this->addPoints($Value,$SerieNames[$Key]); } } + } + } + } + fclose($Handle); + } + } + + /* Create a dataset based on a formula */ + function createFunctionSerie($SerieName,$Formula='',$Options='') + { + $MinX = isset($Options['MinX']) ? $Options['MinX'] : -10; + $MaxX = isset($Options['MaxX']) ? $Options['MaxX'] : 10; + $XStep = isset($Options['XStep']) ? $Options['XStep'] : 1; + $AutoDescription = isset($Options['AutoDescription']) ? $Options['AutoDescription'] : FALSE; + $RecordAbscissa = isset($Options['RecordAbscissa']) ? $Options['RecordAbscissa'] : FALSE; + $AbscissaSerie = isset($Options['AbscissaSerie']) ? $Options['AbscissaSerie'] : 'Abscissa'; + + if ( $Formula == '' ) { return(0); } + + $Result = ''; $Abscissa = ''; + for($i=$MinX; $i<=$MaxX; $i=$i+$XStep) + { + $Expression = '\$return = \'!\'.('.str_replace('z',$i,$Formula).');'; + if ( @eval($Expression) === FALSE ) { $return = VOID; } + if ( $return == '!' ) { $return = VOID; } else { $return = $this->right($return,strlen($return)-1); } + if ( $return == 'NAN' ) { $return = VOID; } + if ( $return == 'INF' ) { $return = VOID; } + if ( $return == '-INF' ) { $return = VOID; } + + $Abscissa[] = $i; + $Result[] = $return; + } + + $this->addPoints($Result,$SerieName); + if ( $AutoDescription ) { $this->setSerieDescription($SerieName,$Formula); } + if ( $RecordAbscissa ) { $this->addPoints($Abscissa,$AbscissaSerie); } + } + + function negateValues($Series) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $SerieName) + { + if (isset($this->Data['Series'][$SerieName])) + { + $Data = ''; + foreach($this->Data['Series'][$SerieName]['Data'] as $Key => $Value) + { if ( $Value == VOID ) { $Data[] = VOID; } else { $Data[] = -$Value; } } + $this->Data['Series'][$SerieName]['Data'] = $Data; + + $this->Data['Series'][$SerieName]['Max'] = max($this->stripVOID($this->Data['Series'][$SerieName]['Data'])); + $this->Data['Series'][$SerieName]['Min'] = min($this->stripVOID($this->Data['Series'][$SerieName]['Data'])); + } + } + } + + function getData() + { return($this->Data); } + + function savePalette($ID,$Color) + { $this->Palette[$ID] = $Color; } + + function getPalette() + { return($this->Palette); } + + function saveAxisConfig($Axis) { $this->Data['Axis']=$Axis; } + + function saveYMargin($Value) { $this->Data['YMargin']=$Value; } + + function saveExtendedData($Tag,$Values) { $this->Data['Extended'][$Tag]=$Values; } + + function saveOrientation($Orientation) { $this->Data['Orientation']=$Orientation; } + + function convertToArray($Value) + { $Values = ''; $Values[] = $Value; return($Values); } + + function __toString() + { return('pData object.'); } + + function left($value,$NbChar) { return substr($value,0,$NbChar); } + function right($value,$NbChar) { return substr($value,strlen($value)-$NbChar,$NbChar); } + function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); } + } +?> \ No newline at end of file diff --git a/system/library/games/graph/pDraw.php b/system/library/games/graph/pDraw.php new file mode 100644 index 0000000..cc49e57 --- /dev/null +++ b/system/library/games/graph/pDraw.php @@ -0,0 +1,6205 @@ +DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) { $Results++; } } + + return($Results); + } + + /* Fix box coordinates */ + function fixBoxCoordinates($Xa,$Ya,$Xb,$Yb) + { + $X1 = min($Xa,$Xb); $Y1 = min($Ya,$Yb); + $X2 = max($Xa,$Xb); $Y2 = max($Ya,$Yb); + + return(array($X1,$Y1,$X2,$Y2)); + } + + /* Draw a polygon */ + function drawPolygon($Points,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $NoFill = isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $Alpha / 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $SkipX = isset($Format["SkipX"]) ? $Format["SkipX"] : OUT_OF_SIGHT; + $SkipY = isset($Format["SkipY"]) ? $Format["SkipY"] : OUT_OF_SIGHT; + + /* Calling the ImageFilledPolygon() function over the $Points array will round it */ + $Backup = $Points; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + if ( $SkipX != OUT_OF_SIGHT ) { $SkipX = floor($SkipX); } + if ( $SkipY != OUT_OF_SIGHT ) { $SkipY = floor($SkipY); } + + $RestoreShadow = $this->Shadow; + if ( !$NoFill ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + for($i=0;$i<=count($Points)-1;$i=$i+2) + { $Shadow[] = $Points[$i] + $this->ShadowX; $Shadow[] = $Points[$i+1] + $this->ShadowY; } + $this->drawPolygon($Shadow,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"NoBorder"=>TRUE)); + } + + $FillColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + + if ( count($Points) >= 6 ) + { ImageFilledPolygon($this->Picture,$Points,count($Points)/2,$FillColor); } + } + + if ( !$NoBorder ) + { + $Points = $Backup; + + if ( $NoFill ) + $BorderSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + else + $BorderSettings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); + + for($i=0;$i<=count($Points)-1;$i=$i+2) + { + if ( isset($Points[$i+2]) ) + { + if ( !($Points[$i] == $Points[$i+2] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[$i+3] && $Points[$i+1] == $SkipY ) ) + $this->drawLine($Points[$i],$Points[$i+1],$Points[$i+2],$Points[$i+3],$BorderSettings); + } + else + { + if ( !($Points[$i] == $Points[0] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[1] && $Points[$i+1] == $SkipY ) ) + $this->drawLine($Points[$i],$Points[$i+1],$Points[0],$Points[1],$BorderSettings); + } + } + } + + $this->Shadow = $RestoreShadow; + } + + /* Apply AALias correction to the rounded box boundaries */ + function offsetCorrection($Value,$Mode) + { + $Value = round($Value,1); + + if ( $Value == 0 && $Mode == 1 ) { return(.9); } + if ( $Value == 0 ) { return(0); } + + if ( $Mode == 1) + { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.9); }; if ( $Value == .2 ) { return(.8); }; if ( $Value == .3 ) { return(.8); }; if ( $Value == .4 ) { return(.7); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.6); }; if ( $Value == .9 ) { return(.9); }; } + + if ( $Mode == 2) + { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.8); }; if ( $Value == .9 ) { return(.9); }; } + + if ( $Mode == 3) + { if ( $Value == 1 ) { return(.1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.9); }; if ( $Value == .6 ) { return(.6); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.4); }; if ( $Value == .9 ) { return(.5); }; } + + if ( $Mode == 4) + { if ( $Value == 1 ) { return(-1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.1); }; if ( $Value == .5 ) { return(-.1); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.1); }; if ( $Value == .8 ) { return(.1); }; if ( $Value == .9 ) { return(.1); }; } + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); } + if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); + + if ( $Radius <= 0 ) { $this->drawRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } + + if ( $this->Antialias ) + { + $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); + $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); + $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); + $this->drawLine($X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); + } + else + { + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imageline($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); + imageline($this->Picture,$X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); + imageline($this->Picture,$X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); + imageline($this->Picture,$X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); + } + + $Step = 360 / (2 * PI * $Radius); + for($i=0;$i<=90;$i=$i+$Step) + { + $X = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+180)*PI/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+90)*PI/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos($i*PI/180) * $Radius + $X2 - $Radius; + $Y = sin($i*PI/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos(($i+270)*PI/180) * $Radius + $X2 - $Radius; + $Y = sin(($i+270)*PI/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + /* Temporary fix for AA issue */ + $Y1 = floor($Y1); $Y2 = floor($Y2); $X1 = floor($X1); $X2 = floor($X2); + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; } + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius*2 ) { $Radius = floor((($X2-$X1))/4); } + if ( $Y2 - $Y1 < $Radius*2 ) { $Radius = floor((($Y2-$Y1))/4); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); + + if ( $Radius <= 0 ) { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } + + $YTop = $Y1+$Radius; + $YBottom = $Y2-$Radius; + + $Step = 360 / (2 * PI * $Radius); + $Positions = ""; $Radius--; $MinY = ""; $MaxY = ""; + for($i=0;$i<=90;$i=$i+$Step) + { + $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius; + $Yp = floor(sin(($i+180)*PI/180) * $Radius + $YTop); + if ( $MinY == "" || $Yp > $MinY ) { $MinY = $Yp; } + + if ( $Xp1 <= floor($X1) ) { $Xp1++; } + if ( $Xp2 >= floor($X2) ) { $Xp2--; } + $Xp1++; + + if ( !isset($Positions[$Yp]) ) + { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } + else + { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; } + + $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius; + $Yp = floor(sin(($i+90)*PI/180) * $Radius + $YBottom); + if ( $MaxY == "" || $Yp < $MaxY ) { $MaxY = $Yp; } + + if ( $Xp1 <= floor($X1) ) { $Xp1++; } + if ( $Xp2 >= floor($X2) ) { $Xp2--; } + $Xp1++; + + if ( !isset($Positions[$Yp]) ) + { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } + else + { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; } + } + + $ManualColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + foreach($Positions as $Yp => $Bounds) + { + $X1 = $Bounds["X1"]; $X1Dec = $this->getFirstDecimal($X1); if ( $X1Dec != 0 ) { $X1 = floor($X1)+1; } + $X2 = $Bounds["X2"]; $X2Dec = $this->getFirstDecimal($X2); if ( $X2Dec != 0 ) { $X2 = floor($X2)-1; } + imageline($this->Picture,$X1,$Yp,$X2,$Yp,$ManualColor); + } + $this->drawFilledRectangle($X1,$MinY+1,floor($X2),$MaxY-1,$Color); + + $Radius++; + $this->drawRoundedRectangle($X1,$Y1,$X2+1,$Y2-1,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedFilledRectangle_deprecated($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; } + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1)+2)/2); } + if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1)+2)/2); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + if ( $this->getFirstDecimal($X2) >= 5 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($X1) <= 5 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + + if ( !$this->Antialias ) { $XOffset1 = 1; $XOffset2 = 1; } + + $YTop = floor($Y1+$Radius); + $YBottom = floor($Y2-$Radius); + + $this->drawFilledRectangle($X1-$XOffset1,$YTop,$X2+$XOffset2,$YBottom,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE)); + + $Step = 360 / (2 * PI * $Radius); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + $Color2 = $this->allocateColor($this->Picture,255,0,0,$Alpha); + $Drawn = ""; + + if ( $Alpha < 100 ) { $Drawn[$YTop] = FALSE; } + if ( $Alpha < 100 ) { $Drawn[$YBottom] = TRUE; } + + for($i=0;$i<=90;$i=$i+$Step) + { + $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius; + $Yp = sin(($i+180)*PI/180) * $Radius + $YTop; + + if ( $this->getFirstDecimal($Xp1) > 5 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + if ( $this->getFirstDecimal($Xp2) > 5 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($Yp) > 5 ) { $YOffset = 1; } else { $YOffset = 0; } + + if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 ) + imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color); + + $Drawn[$Yp+$YOffset] = $Xp2; + + $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius; + $Yp = sin(($i+90)*PI/180) * $Radius + $YBottom; + + if ( $this->getFirstDecimal($Xp1) > 7 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + if ( $this->getFirstDecimal($Xp2) > 7 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($Yp) > 5 ) { $YOffset = 1; } else { $YOffset = 0; } + + if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 ) + imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color); + + $Drawn[$Yp+$YOffset] = $Xp2; + } + + $this->drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangle */ + function drawRectangle($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE; + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + if ( $this->Antialias ) + { + if ( $NoAngle ) + { + $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2,$Y1+1,$X2,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X1,$Y1+1,$X1,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + else + { + $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2,$Y1,$X2,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X1,$Y1,$X1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + } + else + { + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagerectangle($this->Picture,$X1,$Y1,$X2,$Y2,$Color); + } + } + + /* Draw a filled rectangle */ + function drawFilledRectangle($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : NULL; + $Dash = isset($Format["Dash"]) ? $Format["Dash"] : FALSE; + $DashStep = isset($Format["DashStep"]) ? $Format["DashStep"] : 4; + $DashR = isset($Format["DashR"]) ? $Format["DashR"] : 0; + $DashG = isset($Format["DashG"]) ? $Format["DashG"] : 0; + $DashB = isset($Format["DashB"]) ? $Format["DashB"] : 0; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle)); + } + + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + if ( $NoAngle ) + { + imagefilledrectangle($this->Picture,ceil($X1)+1,ceil($Y1),floor($X2)-1,floor($Y2),$Color); + imageline($this->Picture,ceil($X1),ceil($Y1)+1,ceil($X1),floor($Y2)-1,$Color); + imageline($this->Picture,floor($X2),ceil($Y1)+1,floor($X2),floor($Y2)-1,$Color); + } + else + imagefilledrectangle($this->Picture,ceil($X1),ceil($Y1),floor($X2),floor($Y2),$Color); + + if ( $Dash ) + { + if ( $BorderR != -1 ) { $iX1=$X1+1; $iY1=$Y1+1; $iX2=$X2-1; $iY2=$Y2-1; } else { $iX1=$X1; $iY1=$Y1; $iX2=$X2; $iY2=$Y2; } + + $Color = $this->allocateColor($this->Picture,$DashR,$DashG,$DashB,$Alpha); + $Y=$iY1-$DashStep; + for($X=$iX1; $X<=$iX2+($iY2-$iY1); $X=$X+$DashStep) + { + $Y=$Y+$DashStep; + if ( $X > $iX2 ) { $Xa = $X-($X-$iX2); $Ya = $iY1+($X-$iX2); } else { $Xa = $X; $Ya = $iY1; } + if ( $Y > $iY2 ) { $Xb = $iX1+($Y-$iY2); $Yb = $Y-($Y-$iY2); } else { $Xb = $iX1; $Yb = $Y; } + imageline($this->Picture,$Xa,$Ya,$Xb,$Yb,$Color); + } + } + + if ( $this->Antialias && !$NoBorder ) + { + if ( $X1 < ceil($X1) ) + { + $AlphaA = $Alpha * (ceil($X1) - $X1); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1)-1,ceil($Y1),ceil($X1)-1,floor($Y2),$Color); + } + + if ( $Y1 < ceil($Y1) ) + { + $AlphaA = $Alpha * (ceil($Y1) - $Y1); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1),ceil($Y1)-1,floor($X2),ceil($Y1)-1,$Color); + } + + if ( $X2 > floor($X2) ) + { + $AlphaA = $Alpha * (.5-($X2 - floor($X2))); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,floor($X2)+1,ceil($Y1),floor($X2)+1,floor($Y2),$Color); + } + + if ( $Y2 > floor($Y2) ) + { + $AlphaA = $Alpha * (.5-($Y2 - floor($Y2))); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1),floor($Y2)+1,floor($X2),floor($Y2)+1,$Color); + } + } + + if ( $BorderR != -1 ) + $this->drawRectangle($X1,$Y1,$X2,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangular marker of the specified size */ + function drawRectangleMarker($X,$Y,$Format="") + { + $Size = isset($Format["Size"]) ? $Format["Size"] : 4; + + $HalfSize = floor($Size/2); + $this->drawFilledRectangle($X-$HalfSize,$Y-$HalfSize,$X+$HalfSize,$Y+$HalfSize,$Format); + } + + /* Drawn a spline based on the bezier function */ + function drawSpline($Coordinates,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Force = isset($Format["Force"]) ? $Format["Force"] : 30; + $Forces = isset($Format["Forces"]) ? $Format["Forces"] : NULL; + $ShowC = isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $PathOnly = isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + + $Cpt = NULL; $Mode = NULL; $Result = ""; + for($i=1;$i<=count($Coordinates)-1;$i++) + { + $X1 = $Coordinates[$i-1][0]; $Y1 = $Coordinates[$i-1][1]; + $X2 = $Coordinates[$i][0]; $Y2 = $Coordinates[$i][1]; + + if ( $Forces != NULL ) { $Force = $Forces[$i]; } + + /* First segment */ + if ( $i == 1 ) + { $Xv1 = $X1; $Yv1 = $Y1; } + else + { + $Angle1 = $this->getAngle($XLast,$YLast,$X1,$Y1); + $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2); + $XOff = cos($Angle2 * PI / 180) * $Force + $X1; + $YOff = sin($Angle2 * PI / 180) * $Force + $Y1; + + $Xv1 = cos($Angle1 * PI / 180) * $Force + $XOff; + $Yv1 = sin($Angle1 * PI / 180) * $Force + $YOff; + } + + /* Last segment */ + if ( $i == count($Coordinates)-1 ) + { $Xv2 = $X2; $Yv2 = $Y2; } + else + { + $Angle1 = $this->getAngle($X2,$Y2,$Coordinates[$i+1][0],$Coordinates[$i+1][1]); + $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2); + $XOff = cos(($Angle2+180) * PI / 180) * $Force + $X2; + $YOff = sin(($Angle2+180) * PI / 180) * $Force + $Y2; + + $Xv2 = cos(($Angle1+180) * PI / 180) * $Force + $XOff; + $Yv2 = sin(($Angle1+180) * PI / 180) * $Force + $YOff; + } + + $Path = $this->drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format); + if ($PathOnly) { $Result[] = $Path; } + + $XLast = $X1; $YLast = $Y1; + } + + return($Result); + } + + /* Draw a bezier curve with two controls points */ + function drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $ShowC = isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE; + $Segments = isset($Format["Segments"]) ? $Format["Segments"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoDraw = isset($Format["NoDraw"]) ? $Format["NoDraw"] : FALSE; + $PathOnly = isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $DrawArrow = isset($Format["DrawArrow"]) ? $Format["DrawArrow"] : FALSE; + $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 10; + $ArrowRatio = isset($Format["ArrowRatio"]) ? $Format["ArrowRatio"] : .5; + $ArrowTwoHeads = isset($Format["ArrowTwoHeads"]) ? $Format["ArrowTwoHeads"] : FALSE; + + if ( $Segments == NULL ) + { + $Length = $this->getLength($X1,$Y1,$X2,$Y2); + $Precision = ($Length*125)/1000; + } + else + $Precision = $Segments; + + $P[0]["X"] = $X1; $P[0]["Y"] = $Y1; + $P[1]["X"] = $Xv1; $P[1]["Y"] = $Yv1; + $P[2]["X"] = $Xv2; $P[2]["Y"] = $Yv2; + $P[3]["X"] = $X2; $P[3]["Y"] = $Y2; + + /* Compute the bezier points */ + $Q = ""; $ID = 0; $Path = ""; + for($i=0;$i<=$Precision;$i=$i+1) + { + $u = $i / $Precision; + + $C = ""; + $C[0] = (1 - $u) * (1 - $u) * (1 - $u); + $C[1] = ($u * 3) * (1 - $u) * (1 - $u); + $C[2] = 3 * $u * $u * (1 - $u); + $C[3] = $u * $u * $u; + + for($j=0;$j<=3;$j++) + { + if ( !isset($Q[$ID]) ) { $Q[$ID] = ""; } + if ( !isset($Q[$ID]["X"]) ) { $Q[$ID]["X"] = 0; } + if ( !isset($Q[$ID]["Y"]) ) { $Q[$ID]["Y"] = 0; } + + $Q[$ID]["X"] = $Q[$ID]["X"] + $P[$j]["X"] * $C[$j]; + $Q[$ID]["Y"] = $Q[$ID]["Y"] + $P[$j]["Y"] * $C[$j]; + } + $ID++; + } + $Q[$ID]["X"] = $X2; $Q[$ID]["Y"] = $Y2; + + if ( !$NoDraw ) + { + /* Display the control points */ + if ( $ShowC && !$PathOnly ) + { + $Xv1 = floor($Xv1); $Yv1 = floor($Yv1); $Xv2 = floor($Xv2); $Yv2 = floor($Yv2); + + $this->drawLine($X1,$Y1,$X2,$Y2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>30)); + + $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($Xv1,$Yv1,$MyMarkerSettings); + $this->drawText($Xv1+4,$Yv1,"v1"); + $MyMarkerSettings = array("R"=>0,"G"=>0,"B"=>255,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($Xv2,$Yv2,$MyMarkerSettings); + $this->drawText($Xv2+4,$Yv2,"v2"); + } + + /* Draw the bezier */ + $LastX = NULL; $LastY = NULL; $Cpt = NULL; $Mode = NULL; $ArrowS = NULL; + foreach ($Q as $Key => $Point) + { + $X = $Point["X"]; $Y = $Point["Y"]; + + /* Get the first segment */ + if ( $ArrowS == NULL && $LastX != NULL && $LastY != NULL ) + { $ArrowS["X2"] = $LastX; $ArrowS["Y2"] = $LastY; $ArrowS["X1"] = $X; $ArrowS["Y1"] = $Y; } + + if ( $LastX != NULL && $LastY != NULL && !$PathOnly) + list($Cpt,$Mode) = $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Cpt"=>$Cpt,"Mode"=>$Mode,"Weight"=>$Weight)); + + /* Get the last segment */ + $ArrowE["X1"] = $LastX; $ArrowE["Y1"] = $LastY; $ArrowE["X2"] = $X; $ArrowE["Y2"] = $Y; + + $LastX = $X; $LastY = $Y; + } + + if ( $DrawArrow && !$PathOnly ) + { + $ArrowSettings = array("FillR"=>$R,"FillG"=>$G,"FillB"=>$B,"Alpha"=>$Alpha,"Size"=>$ArrowSize,"Ratio"=>$ArrowRatio); + if ( $ArrowTwoHeads ) + $this->drawArrow($ArrowS["X1"],$ArrowS["Y1"],$ArrowS["X2"],$ArrowS["Y2"],$ArrowSettings); + + $this->drawArrow($ArrowE["X1"],$ArrowE["Y1"],$ArrowE["X2"],$ArrowE["Y2"],$ArrowSettings); + } + } + return($Q); + } + + /* Draw a line between two points */ + function drawLine($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $Cpt = isset($Format["Cpt"]) ? $Format["Cpt"] : 1; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : 1; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + if ( $this->Antialias == FALSE && $Ticks == NULL ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imageline($this->Picture,$X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$ShadowColor); + } + + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imageline($this->Picture,$X1,$Y1,$X2,$Y2,$Color); + return(0); + } + + $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1)); + if ( $Distance == 0 ) { return(-1); } + + /* Derivative algorithm for overweighted lines, re-route to polygons primitives */ + if ( $Weight != NULL ) + { + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2); + $PolySettings = array ("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderAlpha"=>$Alpha); + + if ( $Ticks == NULL ) + { + $Points = ""; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y1; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y1; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y2; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y2; + + $this->drawPolygon($Points,$PolySettings); + } + else + { + for($i=0;$i<=$Distance;$i=$i+$Ticks*2) + { + $Xa = (($X2-$X1)/$Distance) * $i + $X1; $Ya = (($Y2-$Y1)/$Distance) * $i + $Y1; + $Xb = (($X2-$X1)/$Distance) * ($i+$Ticks) + $X1; $Yb = (($Y2-$Y1)/$Distance) * ($i+$Ticks) + $Y1; + + $Points = ""; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Ya; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Ya; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Yb; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Yb; + + $this->drawPolygon($Points,$PolySettings); + } + } + + return(1); + } + + $XStep = ($X2-$X1) / $Distance; + $YStep = ($Y2-$Y1) / $Distance; + + for($i=0;$i<=$Distance;$i++) + { + $X = $i * $XStep + $X1; + $Y = $i * $YStep + $Y1; + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Parameters) + { + if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"]) + { + if ( isset($Parameters["R"]) ) { $RT = $Parameters["R"]; } else { $RT = 0; } + if ( isset($Parameters["G"]) ) { $GT = $Parameters["G"]; } else { $GT = 0; } + if ( isset($Parameters["B"]) ) { $BT = $Parameters["B"]; } else { $BT = 0; } + if ( isset($Parameters["Alpha"]) ) { $AlphaT = $Parameters["Alpha"]; } else { $AlphaT = 0; } + $Color = array("R"=>$RT,"G"=>$GT,"B"=>$BT,"Alpha"=>$AlphaT); + } + } + } + + if ( $Ticks != NULL ) + { + if ( $Cpt % $Ticks == 0 ) + { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } } + + if ( $Mode == 1 ) + $this->drawAntialiasPixel($X,$Y,$Color); + + $Cpt++; + } + else + $this->drawAntialiasPixel($X,$Y,$Color); + } + + return(array($Cpt,$Mode)); + } + + /* Draw a circle */ + function drawCircle($Xc,$Yc,$Height,$Width,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + + $Height = abs($Height); + $Width = abs($Width); + + if ( $Height == 0 ) { $Height = 1; } + if ( $Width == 0 ) { $Width = 1; } + $Xc = floor($Xc); $Yc = floor($Yc); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawCircle($Xc+$this->ShadowX,$Yc+$this->ShadowY,$Height,$Width,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks)); + } + + if ( $Width == 0 ) { $Width = $Height; } + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $Step = 360 / (2 * PI * max($Width,$Height)); + $Mode = 1; $Cpt = 1; + for($i=0;$i<=360;$i=$i+$Step) + { + $X = cos($i*PI/180) * $Height + $Xc; + $Y = sin($i*PI/180) * $Width + $Yc; + + if ( $Ticks != NULL ) + { + if ( $Cpt % $Ticks == 0 ) + { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } } + + if ( $Mode == 1 ) + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $Cpt++; + } + else + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + } + $this->Shadow = $RestoreShadow; + } + + /* Draw a filled circle */ + function drawFilledCircle($X,$Y,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + if ( $Radius == 0 ) { $Radius = 1; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + $X = floor($X); $Y = floor($Y); + + $Radius = abs($Radius); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawFilledCircle($X+$this->ShadowX,$Y+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks)); + } + + $this->Mask = ""; + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + for ($i=0; $i<=$Radius*2; $i++) + { + $Slice = sqrt($Radius * $Radius - ($Radius - $i) * ($Radius - $i)); + $XPos = floor($Slice); + $YPos = $Y + $i - $Radius; + $AAlias = $Slice - floor($Slice); + + $this->Mask[$X-$XPos][$YPos] = TRUE; + $this->Mask[$X+$XPos][$YPos] = TRUE; + imageline($this->Picture,$X-$XPos,$YPos,$X+$XPos,$YPos,$Color); + } + if ( $this->Antialias ) + $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + + $this->Mask = ""; + + if ( $BorderR != -1 ) + $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks)); + + $this->Shadow = $RestoreShadow; + } + + /* Write text */ + function drawText($X,$Y,$Text,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : $this->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->FontColorB; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $Align = isset($Format["Align"]) ? $Format["Align"] : TEXT_ALIGN_BOTTOMLEFT; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $ShowOrigine = isset($Format["ShowOrigine"]) ? $Format["ShowOrigine"] : FALSE; + $TOffset = isset($Format["TOffset"]) ? $Format["TOffset"] : 2; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : FALSE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : TRUE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 6; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : FALSE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 6; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 255; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 255; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 255; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxBorderG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxBorderB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxBorderAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50; + $NoShadow = isset($Format["NoShadow"]) ? $Format["NoShadow"] : FALSE; + + $Shadow = $this->Shadow; + if ( $NoShadow ) { $this->Shadow = FALSE; } + + if ( $BoxSurrounding != "" ) { $BoxBorderR = $BoxR - $BoxSurrounding; $BoxBorderG = $BoxG - $BoxSurrounding; $BoxBorderB = $BoxB - $BoxSurrounding; $BoxBorderAlpha = $BoxAlpha; } + + if ( $ShowOrigine ) + { + $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($X,$Y,$MyMarkerSettings); + } + + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,$Angle,$Text); + + if ( $DrawBox && ($Angle == 0 || $Angle == 90 || $Angle == 180 || $Angle == 270)) + { + $T[0]["X"]=0;$T[0]["Y"]=0;$T[1]["X"]=0;$T[1]["Y"]=0;$T[2]["X"]=0;$T[2]["Y"]=0;$T[3]["X"]=0;$T[3]["Y"]=0; + if ( $Angle == 0 ) { $T[0]["X"]=-$TOffset;$T[0]["Y"]=$TOffset;$T[1]["X"]=$TOffset;$T[1]["Y"]=$TOffset;$T[2]["X"]=$TOffset;$T[2]["Y"]=-$TOffset;$T[3]["X"]=-$TOffset;$T[3]["Y"]=-$TOffset; } + + $X1 = min($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) - $BorderOffset + 3; + $Y1 = min($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) - $BorderOffset; + $X2 = max($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) + $BorderOffset + 3; + $Y2 = max($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) + $BorderOffset - 3; + + $X1 = $X1 - $TxtPos[$Align]["X"] + $X + $T[0]["X"]; + $Y1 = $Y1 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"]; + $X2 = $X2 - $TxtPos[$Align]["X"] + $X + $T[0]["X"]; + $Y2 = $Y2 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"]; + + $Settings = array("R"=>$BoxR,"G"=>$BoxG,"B"=>$BoxB,"Alpha"=>$BoxAlpha,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"BorderAlpha"=>$BoxBorderAlpha); + + if ( $BoxRounded ) + { $this->drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$RoundedRadius,$Settings); } + else + { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Settings); } + } + + $X = $X - $TxtPos[$Align]["X"] + $X; + $Y = $Y - $TxtPos[$Align]["Y"] + $Y; + + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $C_ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imagettftext($this->Picture,$FontSize,$Angle,$X+$this->ShadowX,$Y+$this->ShadowY,$C_ShadowColor,$FontName,$Text); + } + + $C_TextColor = $this->AllocateColor($this->Picture,$R,$G,$B,$Alpha); + imagettftext($this->Picture,$FontSize,$Angle,$X,$Y,$C_TextColor,$FontName,$Text); + + $this->Shadow = $Shadow; + + return($TxtPos); + } + + /* Draw a gradient within a defined area */ + function drawGradientArea($X1,$Y1,$X2,$Y2,$Direction,$Format="") + { + $StartR = isset($Format["StartR"]) ? $Format["StartR"] : 90; + $StartG = isset($Format["StartG"]) ? $Format["StartG"] : 90; + $StartB = isset($Format["StartB"]) ? $Format["StartB"] : 90; + $EndR = isset($Format["EndR"]) ? $Format["EndR"] : 0; + $EndG = isset($Format["EndG"]) ? $Format["EndG"] : 0; + $EndB = isset($Format["EndB"]) ? $Format["EndB"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Levels = isset($Format["Levels"]) ? $Format["Levels"] : NULL; + + $Shadow = $this->Shadow; + $this->Shadow = FALSE; + + if ( $StartR == $EndR && $StartG == $EndG && $StartB == $EndB ) + { + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,array("R"=>$StartR,"G"=>$StartG,"B"=>$StartB,"Alpha"=>$Alpha)); + return(0); + } + + if ( $Levels != NULL ) + { $EndR=$StartR+$Levels; $EndG=$StartG+$Levels; $EndB=$StartB+$Levels; } + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + if ( $Direction == DIRECTION_VERTICAL ) { $Width = abs($Y2-$Y1); } + if ( $Direction == DIRECTION_HORIZONTAL ) { $Width = abs($X2-$X1); } + + $Step = max(abs($EndR-$StartR),abs($EndG-$StartG),abs($EndB-$StartB)); + $StepSize = $Width/$Step; + $RStep = ($EndR-$StartR)/$Step; + $GStep = ($EndG-$StartG)/$Step; + $BStep = ($EndB-$StartB)/$Step; + + $R=$StartR;$G=$StartG;$B=$StartB; + switch($Direction) + { + case DIRECTION_VERTICAL: + $StartY = $Y1; $EndY = floor($Y2)+1; $LastY2 = $StartY; + for($i=0;$i<=$Step;$i++) + { + $Y2 = floor($StartY + ($i * $StepSize)); + + if ($Y2 > $EndY) { $Y2 = $EndY; } + if (($Y1 != $Y2 && $Y1 < $Y2) || $Y2 == $EndY) + { + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); + $LastY2 = max($LastY2,$Y2); + $Y1 = $Y2+1; + } + $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep; + } + if ( $LastY2 < $EndY && isset($Color)) { for ($i=$LastY2+1;$i<=$EndY;$i++) { $this->drawLine($X1,$i,$X2,$i,$Color); } } + break; + + case DIRECTION_HORIZONTAL: + $StartX = $X1; $EndX = $X2; + for($i=0;$i<=$Step;$i++) + { + $X2 = floor($StartX + ($i * $StepSize)); + + if ($X2 > $EndX) { $X2 = $EndX; } + if (($X1 != $X2 && $X1 < $X2) || $X2 == $EndX) + { + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); + $X1 = $X2+1; + } + $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep; + } + if ( $X2 < $EndX && isset($Color)) { $this->drawFilledRectangle($X2,$Y1,$EndX,$Y2,$Color); } + break; + } + + $this->Shadow = $Shadow; + + } + + /* Draw an aliased pixel */ + function drawAntialiasPixel($X,$Y,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize ) + return(-1); + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( !$this->Antialias ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor); + } + + $PlotColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagesetpixel($this->Picture,$X,$Y,$PlotColor); + + return(0); + } + + $Plot = ""; + $Xi = floor($X); + $Yi = floor($Y); + + if ( $Xi == $X && $Yi == $Y) + { + if ( $Alpha == 100 ) + $this->drawAlphaPixel($X,$Y,100,$R,$G,$B); + else + $this->drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B); + } + else + { + $Alpha1 = (((1 - ($X - floor($X))) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha1 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi,$Alpha1,$R,$G,$B); } + + $Alpha2 = ((($X - floor($X)) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha2 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi,$Alpha2,$R,$G,$B); } + + $Alpha3 = (((1 - ($X - floor($X))) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha3 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi+1,$Alpha3,$R,$G,$B); } + + $Alpha4 = ((($X - floor($X)) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha4 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi+1,$Alpha4,$R,$G,$B); } + } + } + + /* Draw a semi-transparent pixel */ + function drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B) + { + if ( isset($this->Mask[$X])) { if ( isset($this->Mask[$X][$Y]) ) { return(0); } } + + if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize ) + return(-1); + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $AlphaFactor = floor(($Alpha / 100) * $this->Shadowa); + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$AlphaFactor); + imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor); + } + + $C_Aliased = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagesetpixel($this->Picture,$X,$Y,$C_Aliased); + } + + /* Convert apha to base 10 */ + function convertAlpha($AlphaValue) + { return((127/100)*(100-$AlphaValue)); } + + /* Allocate a color with transparency */ + function allocateColor($Picture,$R,$G,$B,$Alpha=100) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + if ( $Alpha < 0 ) { $Alpha = 0; } + if ( $Alpha > 100) { $Alpha = 100; } + + $Alpha = $this->convertAlpha($Alpha); + return(imagecolorallocatealpha($Picture,$R,$G,$B,$Alpha)); + } + + /* Load a PNG file and draw it over the chart */ + function drawFromPNG($X,$Y,$FileName) + { $this->drawFromPicture(1,$FileName,$X,$Y); } + + /* Load a GIF file and draw it over the chart */ + function drawFromGIF($X,$Y,$FileName) + { $this->drawFromPicture(2,$FileName,$X,$Y); } + + /* Load a JPEG file and draw it over the chart */ + function drawFromJPG($X,$Y,$FileName) + { $this->drawFromPicture(3,$FileName,$X,$Y); } + + function getPicInfo($FileName) + { + $Infos = getimagesize($FileName); + $Width = $Infos[0]; + $Height = $Infos[1]; + $Type = $Infos["mime"]; + + if ( $Type == "image/png") { $Type = 1; } + if ( $Type == "image/gif") { $Type = 2; } + if ( $Type == "image/jpeg ") { $Type = 3; } + + return(array($Width,$Height,$Type)); + } + + /* Generic loader function for external pictures */ + function drawFromPicture($PicType,$FileName,$X,$Y) + { + if ( file_exists($FileName)) + { + list($Width,$Height) = $this->getPicInfo($FileName); + + if ( $PicType == 1 ) + { $Raster = imagecreatefrompng($FileName); } + elseif ( $PicType == 2 ) + { $Raster = imagecreatefromgif($FileName); } + elseif ( $PicType == 3 ) + { $Raster = imagecreatefromjpeg($FileName); } + else + { return(0); } + + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + if ( $PicType == 3 ) + $this->drawFilledRectangle($X+$this->ShadowX,$Y+$this->ShadowY,$X+$Width+$this->ShadowX,$Y+$Height+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + else + { + $TranparentID = imagecolortransparent($Raster); + for ($Xc=0;$Xc<=$Width-1;$Xc++) + { + for ($Yc=0;$Yc<=$Height-1;$Yc++) + { + $RGBa = imagecolorat($Raster,$Xc,$Yc); + $Values = imagecolorsforindex($Raster,$RGBa); + if ( $Values["alpha"] < 120 ) + { + $AlphaFactor = floor(($this->Shadowa / 100) * ((100 / 127) * (127-$Values["alpha"]))); + $this->drawAlphaPixel($X+$Xc+$this->ShadowX,$Y+$Yc+$this->ShadowY,$AlphaFactor,$this->ShadowR,$this->ShadowG,$this->ShadowB); + } + } + } + } + } + $this->Shadow = $RestoreShadow; + + imagecopy($this->Picture,$Raster,$X,$Y,0,0,$Width,$Height); + imagedestroy($Raster); + } + } + + /* Draw an arrow */ + function drawArrow($X1,$Y1,$X2,$Y2,$Format="") + { + $FillR = isset($Format["FillR"]) ? $Format["FillR"] : 0; + $FillG = isset($Format["FillG"]) ? $Format["FillG"] : 0; + $FillB = isset($Format["FillB"]) ? $Format["FillB"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Size = isset($Format["Size"]) ? $Format["Size"] : 10; + $Ratio = isset($Format["Ratio"]) ? $Format["Ratio"] : .5; + $TwoHeads = isset($Format["TwoHeads"]) ? $Format["TwoHeads"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : FALSE; + + /* Calculate the line angle */ + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2); + + /* Override Shadow support, this will be managed internally */ + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawArrow($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("FillR"=>$this->ShadowR,"FillG"=>$this->ShadowG,"FillB"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Size"=>$Size,"Ratio"=>$Ratio,"TwoHeads"=>$TwoHeads,"Ticks"=>$Ticks)); + } + + /* Draw the 1st Head */ + $TailX = cos(($Angle-180)*PI/180)*$Size+$X2; + $TailY = sin(($Angle-180)*PI/180)*$Size+$Y2; + + $Points = ""; + $Points[] = $X2; $Points[] = $Y2; + $Points[] = cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY; + $Points[] = cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY; + $Points[] = $X2; $Points[] = $Y2; + + /* Visual correction */ + if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; } + if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; } + + $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha); + ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor); + + $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + /* Draw the second head */ + if ( $TwoHeads ) + { + $Angle = $this->getAngle($X2,$Y2,$X1,$Y1); + + $TailX2 = cos(($Angle-180)*PI/180)*$Size+$X1; + $TailY2 = sin(($Angle-180)*PI/180)*$Size+$Y1; + + $Points = ""; + $Points[] = $X1; $Points[] = $Y1; + $Points[] = cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY2; + $Points[] = cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY2; + $Points[] = $X1; $Points[] = $Y1; + + /* Visual correction */ + if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; } + if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; } + + $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha); + ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor); + + $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->drawLine($TailX,$TailY,$TailX2,$TailY2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + else + $this->drawLine($X1,$Y1,$TailX,$TailY,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + + /* Re-enable shadows */ + $this->Shadow = $RestoreShadow; + } + + /* Draw a label with associated arrow */ + function drawArrowLabel($X1,$Y1,$Text,$Format="") + { + $FillR = isset($Format["FillR"]) ? $Format["FillR"] : 0; + $FillG = isset($Format["FillG"]) ? $Format["FillG"] : 0; + $FillB = isset($Format["FillB"]) ? $Format["FillB"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Length = isset($Format["Length"]) ? $Format["Length"] : 50; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 315; + $Size = isset($Format["Size"]) ? $Format["Size"] : 10; + $Position = isset($Format["Position"]) ? $Format["Position"] : POSITION_TOP; + $RoundPos = isset($Format["RoundPos"]) ? $Format["RoundPos"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + + $Angle = $Angle % 360; + + $X2 = sin(($Angle+180)*PI/180)*$Length+$X1; + $Y2 = cos(($Angle+180)*PI/180)*$Length+$Y1; + + if ( $RoundPos && $Angle > 0 && $Angle < 180 ) { $Y2 = ceil($Y2); } + if ( $RoundPos && $Angle > 180 ) { $Y2 = floor($Y2); } + + $this->drawArrow($X2,$Y2,$X1,$Y1,$Format); + + $Size = imagettfbbox($FontSize,0,$FontName,$Text); + $TxtWidth = max(abs($Size[2]-$Size[0]),abs($Size[0]-$Size[6])); + $TxtHeight = max(abs($Size[1]-$Size[7]),abs($Size[3]-$Size[1])); + + if ( $Angle > 0 && $Angle < 180 ) + { + $this->drawLine($X2,$Y2,$X2-$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + if ( $Position == POSITION_TOP ) + $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_BOTTOMRIGHT)); + else + $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPRIGHT)); + } + else + { + $this->drawLine($X2,$Y2,$X2+$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + if ( $Position == POSITION_TOP ) + $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + else + $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPLEFT)); + } + } + + /* Draw a progress bar filled with specified % */ + function drawProgress($X,$Y,$Percent,$Format="") + { + if ( $Percent > 100 ) { $Percent = 100; } + if ( $Percent < 0 ) { $Percent = 0; } + + $Width = isset($Format["Width"]) ? $Format["Width"] : 200; + $Height = isset($Format["Height"]) ? $Format["Height"] : 20; + $Orientation = isset($Format["Orientation"]) ? $Format["Orientation"] : ORIENTATION_HORIZONTAL; + $ShowLabel = isset($Format["ShowLabel"]) ? $Format["ShowLabel"] : FALSE; + $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : LABEL_POS_INSIDE; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 10; + $R = isset($Format["R"]) ? $Format["R"] : 130; + $G = isset($Format["G"]) ? $Format["G"] : 130; + $B = isset($Format["B"]) ? $Format["B"] : 130; + $RFade = isset($Format["RFade"]) ? $Format["RFade"] : -1; + $GFade = isset($Format["GFade"]) ? $Format["GFade"] : -1; + $BFade = isset($Format["BFade"]) ? $Format["BFade"] : -1; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 0; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 0; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 0; + $BoxBackR = isset($Format["BoxBackR"]) ? $Format["BoxBackR"] : 255; + $BoxBackG = isset($Format["BoxBackG"]) ? $Format["BoxBackG"] : 255; + $BoxBackB = isset($Format["BoxBackB"]) ? $Format["BoxBackB"] : 255; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE; + + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $RFade = (($RFade-$R)/100)*$Percent+$R; + $GFade = (($GFade-$G)/100)*$Percent+$G; + $BFade = (($BFade-$B)/100)*$Percent+$B; + } + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + if ( $BoxSurrounding != NULL ) { $BoxBorderR = $BoxBackR + $Surrounding; $BoxBorderG = $BoxBackG + $Surrounding; $BoxBorderB = $BoxBackB + $Surrounding; } + + if ( $Orientation == ORIENTATION_VERTICAL ) + { + $InnerHeight = (($Height-2)/100)*$Percent; + $this->drawFilledRectangle($X,$Y,$X+$Width,$Y-$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $GradientOptions = array("StartR"=>$RFade,"StartG"=>$GFade,"StartB"=>$BFade,"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + $this->drawGradientArea($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,DIRECTION_VERTICAL,$GradientOptions); + + if ( $Surrounding ) + $this->drawRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding)); + } + else + $this->drawFilledRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $this->Shadow = $RestoreShadow; + + if ( $ShowLabel && $LabelPos == LABEL_POS_BOTTOM ) { $this->drawText($X+($Width/2),$Y+$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_TOPMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_TOP ) { $this->drawText($X+($Width/2),$Y-$Height-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE ) { $this->drawText($X+($Width/2),$Y-$InnerHeight-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT,"Angle"=>90)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER ) { $this->drawText($X+($Width/2),$Y-($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"Angle"=>90)); } + } + else + { + if ( $Percent == 100 ) + $InnerWidth = $Width-1; + else + $InnerWidth = (($Width-2)/100)*$Percent; + + $this->drawFilledRectangle($X,$Y,$X+$Width,$Y+$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $GradientOptions = array("StartR"=>$R,"StartG"=>$G,"StartB"=>$B,"EndR"=>$RFade,"EndG"=>$GFade,"EndB"=>$BFade); + $this->drawGradientArea($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,DIRECTION_HORIZONTAL,$GradientOptions); + + if ( $Surrounding ) + $this->drawRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding)); + } + else + $this->drawFilledRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $this->Shadow = $RestoreShadow; + + if ( $ShowLabel && $LabelPos == LABEL_POS_LEFT ) { $this->drawText($X-$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_RIGHT ) { $this->drawText($X+$Width+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER ) { $this->drawText($X+($Width/2),$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE ) { $this->drawText($X+$InnerWidth+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + } + } + + /* Get the legend box size */ + function getLegendSize($Format="") + { + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5; + $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5; + $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth; + $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight; + $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5; + + $Data = $this->DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"])) + { + list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $X=100; $Y=100; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Serie["Description"]); + $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; } + + $Width = ($Boundaries["R"]+$Margin) - ($Boundaries["L"]-$Margin); + $Height = ($Boundaries["B"]+$Margin) - ($Boundaries["T"]-$Margin); + + return(array("Width"=>$Width,"Height"=>$Height)); + } + + /* Draw the legend of the active series */ + function drawLegend($X,$Y,$Format="") + { + $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->FontColorR; + $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->FontColorG; + $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->FontColorB; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5; + $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5; + $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth; + $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight; + $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $R = isset($Format["R"]) ? $Format["R"] : 200; + $G = isset($Format["G"]) ? $Format["G"] : 200; + $B = isset($Format["B"]) ? $Format["B"] : 200; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + + $Data = $this->DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"])) + { + list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Serie["Description"]); + $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; } + + if ( $Style == LEGEND_ROUND ) + $this->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + elseif ( $Style == LEGEND_BOX ) + $this->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; + $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( isset($Serie["Picture"]) ) + { + $Picture = $Serie["Picture"]; + list($PicWidth,$PicHeight) = $this->getPicInfo($Picture); + $PicX = $X+$IconAreaWidth/2; $PicY = $Y+$IconAreaHeight/2; + + $this->drawFromPNG($PicX-$PicWidth/2,$PicY-$PicHeight/2,$Picture); + } + else + { + if ( $Family == LEGEND_FAMILY_BOX ) + { + if ( $BoxWidth != $IconAreaWidth ) { $XOffset = floor(($IconAreaWidth-$BoxWidth)/2); } else { $XOffset = 0; } + if ( $BoxHeight != $IconAreaHeight ) { $YOffset = floor(($IconAreaHeight-$BoxHeight)/2); } else { $YOffset = 0; } + + $this->drawFilledRectangle($X+1+$XOffset,$Y+1+$YOffset,$X+$BoxWidth+$XOffset+1,$Y+$BoxHeight+1+$YOffset,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->drawFilledRectangle($X+$XOffset,$Y+$YOffset,$X+$BoxWidth+$XOffset,$Y+$BoxHeight+$YOffset,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_CIRCLE ) + { + $this->drawFilledCircle($X+1+$IconAreaWidth/2,$Y+1+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->drawFilledCircle($X+$IconAreaWidth/2,$Y+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_LINE ) + { + $this->drawLine($X+1,$Y+1+$IconAreaHeight/2,$X+1+$IconAreaWidth,$Y+1+$IconAreaHeight/2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20,"Ticks"=>$Ticks,"Weight"=>$Weight)); + $this->drawLine($X,$Y+$IconAreaHeight/2,$X+$IconAreaWidth,$Y+$IconAreaHeight/2,array("R"=>$R,"G"=>$G,"B"=>$B,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + } + + if ( $Mode == LEGEND_VERTICAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + foreach($Lines as $Key => $Value) + $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName)); + + $Y=$Y+max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName)); + $Width[] = $BoxArray[1]["X"]; + } + $X=max($Width)+2+$XStep; + } + } + } + + + $this->Shadow = $RestoreShadow; + } + + function drawScale($Format="") + { + $Pos = isset($Format["Pos"]) ? $Format["Pos"] : SCALE_POS_LEFTRIGHT; + $Floating = isset($Format["Floating"]) ? $Format["Floating"] : FALSE; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING; + $RemoveXAxis = isset($Format["RemoveXAxis"]) ? $Format["RemoveXAxis"] : FALSE; + $MinDivHeight = isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20; + $Factors = isset($Format["Factors"]) ? $Format["Factors"] : array(1,2,5); + $ManualScale = isset($Format["ManualScale"]) ? $Format["ManualScale"] : array("0"=>array("Min"=>-100,"Max"=>100)); + $XMargin = isset($Format["XMargin"]) ? $Format["XMargin"] : AUTO; + $YMargin = isset($Format["YMargin"]) ? $Format["YMargin"] : 0; + $ScaleSpacing = isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15; + $InnerTickWidth = isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2; + $OuterTickWidth = isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2; + $DrawXLines = isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : TRUE; + $DrawYLines = isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL; + $GridTicks = isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4; + $GridR = isset($Format["GridR"]) ? $Format["GridR"] : 255; + $GridG = isset($Format["GridG"]) ? $Format["GridG"] : 255; + $GridB = isset($Format["GridB"]) ? $Format["GridB"] : 255; + $GridAlpha = isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40; + $AxisRo = isset($Format["AxisR"]) ? $Format["AxisR"] : 0; + $AxisGo = isset($Format["AxisG"]) ? $Format["AxisG"] : 0; + $AxisBo = isset($Format["AxisB"]) ? $Format["AxisB"] : 0; + $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100; + $TickRo = isset($Format["TickR"]) ? $Format["TickR"] : 0; + $TickGo = isset($Format["TickG"]) ? $Format["TickG"] : 0; + $TickBo = isset($Format["TickB"]) ? $Format["TickB"] : 0; + $TickAlpha = isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100; + $DrawSubTicks = isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : FALSE; + $InnerSubTickWidth = isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0; + $OuterSubTickWidth = isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2; + $SubTickR = isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255; + $SubTickG = isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0; + $SubTickB = isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0; + $SubTickAlpha = isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100; + $AutoAxisLabels = isset($Format["AutoAxisLabels"]) ? $Format["AutoAxisLabels"] : TRUE; + $XReleasePercent = isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1; + $DrawArrows = isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : FALSE; + $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8; + $CycleBackground = isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : FALSE; + $BackgroundR1 = isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255; + $BackgroundG1 = isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255; + $BackgroundB1 = isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255; + $BackgroundAlpha1 = isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 20; + $BackgroundR2 = isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230; + $BackgroundG2 = isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230; + $BackgroundB2 = isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230; + $BackgroundAlpha2 = isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 20; + $LabelingMethod = isset($Format["LabelingMethod"]) ? $Format["LabelingMethod"] : LABELING_ALL; + $LabelSkip = isset($Format["LabelSkip"]) ? $Format["LabelSkip"] : 0; + $LabelRotation = isset($Format["LabelRotation"]) ? $Format["LabelRotation"] : 0; + $RemoveSkippedAxis = isset($Format["RemoveSkippedAxis"]) ? $Format["RemoveSkippedAxis"] : FALSE; + $SkippedAxisTicks = isset($Format["SkippedAxisTicks"]) ? $Format["SkippedAxisTicks"] : $GridTicks+2; + $SkippedAxisR = isset($Format["SkippedAxisR"]) ? $Format["SkippedAxisR"] : $GridR; + $SkippedAxisG = isset($Format["SkippedAxisG"]) ? $Format["SkippedAxisG"] : $GridG; + $SkippedAxisB = isset($Format["SkippedAxisB"]) ? $Format["SkippedAxisB"] : $GridB; + $SkippedAxisAlpha = isset($Format["SkippedAxisAlpha"]) ? $Format["SkippedAxisAlpha"] : $GridAlpha-30; + $SkippedTickR = isset($Format["SkippedTickR"]) ? $Format["SkippedTickR"] : $TickRo; + $SkippedTickG = isset($Format["SkippedTickG"]) ? $Format["SkippedTickG"] : $TickGo; + $SkippedTickB = isset($Format["SkippedTicksB"]) ? $Format["SkippedTickB"] : $TickBo; + $SkippedTickAlpha = isset($Format["SkippedTickAlpha"]) ? $Format["SkippedTickAlpha"] : $TickAlpha-80; + $SkippedInnerTickWidth = isset($Format["SkippedInnerTickWidth"]) ? $Format["SkippedInnerTickWidth"] : 0; + $SkippedOuterTickWidth = isset($Format["SkippedOuterTickWidth"]) ? $Format["SkippedOuterTickWidth"] : 2; + + /* Floating scale require X & Y margins to be set manually */ + if ( $Floating && ( $XMargin == AUTO || $YMargin == 0 ) ) { $Floating = FALSE; } + + /* Skip a NOTICE event in case of an empty array */ + if ( $DrawYLines == NONE || $DrawYLines == FALSE ) { $DrawYLines = array("zarma"=>"31"); } + + /* Define the color for the skipped elements */ + $SkippedAxisColor = array("R"=>$SkippedAxisR,"G"=>$SkippedAxisG,"B"=>$SkippedAxisB,"Alpha"=>$SkippedAxisAlpha,"Ticks"=>$SkippedAxisTicks); + $SkippedTickColor = array("R"=>$SkippedTickR,"G"=>$SkippedTickG,"B"=>$SkippedTickB,"Alpha"=>$SkippedTickAlpha); + + $Data = $this->DataSet->getData(); + if ( isset($Data["Abscissa"]) ) { $Abscissa = $Data["Abscissa"]; } else { $Abscissa = NULL; } + + /* Unset the abscissa axis, needed if we display multiple charts on the same picture */ + if ( $Abscissa != NULL ) + { + foreach($Data["Axis"] as $AxisID => $Parameters) + { if ($Parameters["Identity"] == AXIS_X) { unset($Data["Axis"][$AxisID]); } } + } + + /* Build the scale settings */ + $GotXAxis = FALSE; + foreach($Data["Axis"] as $AxisID => $AxisParameter) + { + if ( $AxisParameter["Identity"] == AXIS_X ) { $GotXAxis = TRUE; } + + if ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_Y) + { $Height = $this->GraphAreaY2-$this->GraphAreaY1 - $YMargin*2; } + elseif ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_X) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1; } + elseif ( $Pos == SCALE_POS_TOPBOTTOM && $AxisParameter["Identity"] == AXIS_Y) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1 - $YMargin*2;; } + else + { $Height = $this->GraphAreaY2-$this->GraphAreaY1; } + + $AxisMin = ABSOLUTE_MAX; $AxisMax = OUT_OF_SIGHT; + if ( $Mode == SCALE_MODE_FLOATING || $Mode == SCALE_MODE_START0 ) + { + foreach($Data["Series"] as $SerieID => $SerieParameter) + { + if ( $SerieParameter["Axis"] == $AxisID && $Data["Series"][$SerieID]["isDrawable"] && $Data["Abscissa"] != $SerieID) + { + $AxisMax = max($AxisMax,$Data["Series"][$SerieID]["Max"]); + $AxisMin = min($AxisMin,$Data["Series"][$SerieID]["Min"]); + } + } + $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent; + + $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin; + if ( $Mode == SCALE_MODE_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; } + } + elseif ( $Mode == SCALE_MODE_MANUAL ) + { + if ( isset($ManualScale[$AxisID]["Min"]) && isset($ManualScale[$AxisID]["Max"]) ) + { + $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"]; + $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"]; + #$Data["Axis"][0]["Max"] = 22; + } + else + { echo "Manual scale boundaries not set."; exit(); } + } + elseif ( $Mode == SCALE_MODE_ADDALL || $Mode == SCALE_MODE_ADDALL_START0 ) + { + $Series = ""; + foreach($Data["Series"] as $SerieID => $SerieParameter) + { if ( $SerieParameter["Axis"] == $AxisID && $SerieParameter["isDrawable"] && $Data["Abscissa"] != $SerieID ) { $Series[$SerieID] = count($Data["Series"][$SerieID]["Data"]); } } + + for ($ID=0;$ID<=max($Series)-1;$ID++) + { + $PointMin = 0; $PointMax = 0; + foreach($Series as $SerieID => $ValuesCount ) + { + if (isset($Data["Series"][$SerieID]["Data"][$ID]) && $Data["Series"][$SerieID]["Data"][$ID] != NULL ) + { + $Value = $Data["Series"][$SerieID]["Data"][$ID]; + if ( $Value > 0 ) { $PointMax = $PointMax + $Value; } else { $PointMin = $PointMin + $Value; } + } + } + $AxisMax = max($AxisMax,$PointMax); + $AxisMin = min($AxisMin,$PointMin); + } + $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent; + $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin; + } + $MaxDivs = floor($Height/$MinDivHeight); + + if ( $Mode == SCALE_MODE_ADDALL_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; } + + $Scale = $this->computeScale($Data["Axis"][$AxisID]["Min"],$Data["Axis"][$AxisID]["Max"],$MaxDivs,$Factors,$AxisID); + + $Data["Axis"][$AxisID]["Margin"] = $AxisParameter["Identity"] == AXIS_X ? $XMargin : $YMargin; + $Data["Axis"][$AxisID]["ScaleMin"] = $Scale["XMin"]; + $Data["Axis"][$AxisID]["ScaleMax"] = $Scale["XMax"]; + $Data["Axis"][$AxisID]["Rows"] = $Scale["Rows"]; + $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"]; + + if ( isset($Scale["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = $Scale["Format"]; } + + if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Unit"]) ) { $Data["Axis"][$AxisID]["Unit"] = NULL; } + } + + /* Still no X axis */ + if ( $GotXAxis == FALSE ) + { + if ( $Abscissa != NULL ) + { + $Points = count($Data["Series"][$Abscissa]["Data"]); + if ( $AutoAxisLabels ) + $AxisName = isset($Data["Series"][$Abscissa]["Description"]) ? $Data["Series"][$Abscissa]["Description"] : NULL; + else + $AxisName = NULL; + } + else + { + $Points = 0; + $AxisName = isset($Data["XAxisName"]) ? $Data["XAxisName"] : NULL; + foreach($Data["Series"] as $SerieID => $SerieParameter) + { if ( $SerieParameter["isDrawable"] ) { $Points = max($Points,count($SerieParameter["Data"])); } } + } + + $AxisID = count($Data["Axis"]); + $Data["Axis"][$AxisID]["Identity"] = AXIS_X; + if ( $Pos == SCALE_POS_LEFTRIGHT ) { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_BOTTOM; } else { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT; } + if ( isset($Data["AbscissaName"]) ) { $Data["Axis"][$AxisID]["Name"] = $Data["AbscissaName"]; } + if ( $XMargin == AUTO ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1; } + else + { $Height = $this->GraphAreaY2-$this->GraphAreaY1; } + + if ( $Points == 1 ) + $Data["Axis"][$AxisID]["Margin"] = $Height / 2; + else + $Data["Axis"][$AxisID]["Margin"] = ($Height/$Points) / 2; + } + else + { $Data["Axis"][$AxisID]["Margin"] = $XMargin; } + $Data["Axis"][$AxisID]["Rows"] = $Points-1; + if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Unit"]) ) { $Data["Axis"][$AxisID]["Unit"] = NULL; } + } + + /* Do we need to reverse the abscissa position? */ + if ( $Pos != SCALE_POS_LEFTRIGHT ) + { + if ( $Data["AbsicssaPosition"] == AXIS_POSITION_BOTTOM ) + { $Data["AbsicssaPosition"] = AXIS_POSITION_LEFT; } + else + { $Data["AbsicssaPosition"] = AXIS_POSITION_RIGHT; } + } + $Data["Axis"][$AxisID]["Position"] = $Data["AbsicssaPosition"]; + + $this->DataSet->saveOrientation($Pos); + $this->DataSet->saveAxisConfig($Data["Axis"]); + $this->DataSet->saveYMargin($YMargin); + + $FontColorRo = $this->FontColorR; $FontColorGo = $this->FontColorG; $FontColorBo = $this->FontColorB; + + $AxisPos["L"] = $this->GraphAreaX1; $AxisPos["R"] = $this->GraphAreaX2; $AxisPos["T"] = $this->GraphAreaY1; $AxisPos["B"] = $this->GraphAreaY2; + foreach($Data["Axis"] as $AxisID => $Parameters) + { + if ( isset($Parameters["Color"]) ) + { + $AxisR = $Parameters["Color"]["R"]; $AxisG = $Parameters["Color"]["G"]; $AxisB = $Parameters["Color"]["B"]; + $TickR = $Parameters["Color"]["R"]; $TickG = $Parameters["Color"]["G"]; $TickB = $Parameters["Color"]["B"]; + $this->setFontProperties(array("R"=>$Parameters["Color"]["R"],"G"=>$Parameters["Color"]["G"],"B"=>$Parameters["Color"]["B"])); + } + else + { + $AxisR = $AxisRo; $AxisG = $AxisGo; $AxisB = $AxisBo; + $TickR = $TickRo; $TickG = $TickGo; $TickB = $TickBo; + $this->setFontProperties(array("R"=>$FontColorRo,"G"=>$FontColorGo,"B"=>$FontColorBo)); + } + + $LastValue = "w00t"; $ID = 1; + if ( $Parameters["Identity"] == AXIS_X ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { + if ( $Parameters["Position"] == AXIS_POSITION_BOTTOM ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Width; } else { $Step = $Width / ($Parameters["Rows"]); } + + $MaxBottom = $AxisPos["B"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["B"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos,$YPos+$OuterTickWidth+$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBottom = $YPos+$OuterTickWidth+2+($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MaxBottom = max($MaxBottom,$TxtBottom); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis) { $this->drawLine($XPos,$YPos-$SkippedInnerTickWidth,$XPos,$YPos+$SkippedOuterTickWidth,$SkippedTickColor); } + } + else + { + if ( $DrawXLines && ($XPos != $this->GraphAreaX1 && $XPos != $this->GraphAreaX2) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos-$InnerTickWidth,$XPos,$YPos+$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis) + { + $YPos = $MaxBottom+2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $MaxBottom = $Bounds[0]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize; + } + + $AxisPos["B"] = $MaxBottom + $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_TOP ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Width; } else { $Step = $Width / $Parameters["Rows"]; } + + $MinTop = $AxisPos["T"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["T"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos,$YPos-$OuterTickWidth-$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $YPos-$OuterTickWidth-2-($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MinTop = min($MinTop,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$YPos+$SkippedInnerTickWidth,$XPos,$YPos-$SkippedOuterTickWidth,$SkippedTickColor); } + } + else + { + if ( $DrawXLines ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos+$InnerTickWidth,$XPos,$YPos-$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis ) + { + $YPos = $MinTop-2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $MinTop = $Bounds[2]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop; + } + + $AxisPos["T"] = $MinTop - $ScaleSpacing; + } + } + elseif ( $Pos == SCALE_POS_TOPBOTTOM ) + { + if ( $Parameters["Position"] == AXIS_POSITION_LEFT ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -6; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -2; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -5; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Height; } else { $Step = $Height / $Parameters["Rows"]; } + + $MinLeft = $AxisPos["L"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i; + $XPos = $AxisPos["L"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos-$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]); + $MinLeft = min($MinLeft,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos-$SkippedOuterTickWidth,$YPos,$XPos+$SkippedInnerTickWidth,$YPos,$SkippedTickColor); } + } + else + { + if ( $DrawXLines && ($YPos != $this->GraphAreaY1 && $YPos != $this->GraphAreaY2) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + if ( isset($Parameters["Name"]) && !$RemoveXAxis ) + { + $XPos = $MinLeft-2; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90)); + $MinLeft = $Bounds[0]["X"]; + + $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft; + } + + $AxisPos["L"] = $MinLeft - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 6; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 7; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Height; } else { $Step = $Height / $Parameters["Rows"]; } + + $MaxRight = $AxisPos["R"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i; + $XPos = $AxisPos["R"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos+$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]); + $MaxRight = max($MaxRight,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth != 0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos+$SkippedOuterTickWidth,$YPos,$XPos-$SkippedInnerTickWidth,$YPos,$SkippedTickColor); } + } + else + { + if ( $DrawXLines ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth != 0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos+$OuterTickWidth,$YPos,$XPos-$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis) + { + $XPos = $MaxRight+4; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270)); + $MaxRight = $Bounds[1]["X"]; + + $this->DataSet->Data["GraphArea"]["X2"] = $MaxRight + $this->FontSize; + } + + $AxisPos["R"] = $MaxRight + $ScaleSpacing; + } + } + } + + + + if ( $Parameters["Identity"] == AXIS_Y ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { + if ( $Parameters["Position"] == AXIS_POSITION_LEFT ) + { + + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + $Step = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinLeft = $AxisPos["L"]; + $LastY = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i; + $XPos = $AxisPos["L"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos-$OuterTickWidth-2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); + $TxtLeft = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]); + $MinLeft = min($MinLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($Parameters["Name"]) ) + { + $XPos = $MinLeft-2; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90)); + $MinLeft = $Bounds[2]["X"]; + + $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft; + } + + $AxisPos["L"] = $MinLeft - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + $Step = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxLeft = $AxisPos["R"]; + $LastY = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i; + $XPos = $AxisPos["R"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos-$InnerTickWidth,$YPos,$XPos+$OuterTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos+$OuterTickWidth+2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); + $TxtLeft = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]); + $MaxLeft = max($MaxLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($Parameters["Name"]) ) + { + $XPos = $MaxLeft+6; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270)); + $MaxLeft = $Bounds[2]["X"]; + + $this->DataSet->Data["GraphArea"]["X2"] = $MaxLeft + $this->FontSize; + } + $AxisPos["R"] = $MaxLeft + $ScaleSpacing; + } + } + elseif ( $Pos == SCALE_POS_TOPBOTTOM ) + { + if ( $Parameters["Position"] == AXIS_POSITION_TOP ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + $Step = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinTop = $AxisPos["T"]; + $LastX = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["T"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos,$YPos-$OuterTickWidth-2,$Value,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $TxtHeight = $YPos-$OuterTickWidth-2-($Bounds[1]["Y"]-$Bounds[2]["Y"]); + $MinTop = min($MinTop,$TxtHeight); + + $LastX = $XPos; + } + + if ( isset($Parameters["Name"]) ) + { + $YPos = $MinTop-2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $MinTop = $Bounds[2]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop; + } + + $AxisPos["T"] = $MinTop - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_BOTTOM ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + $Step = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxBottom = $AxisPos["B"]; + $LastX = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["B"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos,$YPos+$OuterTickWidth+2,$Value,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $TxtHeight = $YPos+$OuterTickWidth+2+($Bounds[1]["Y"]-$Bounds[2]["Y"]); + $MaxBottom = max($MaxBottom,$TxtHeight); + + $LastX = $XPos; + } + + if ( isset($Parameters["Name"]) ) + { + $YPos = $MaxBottom+2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $MaxBottom = $Bounds[0]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize; + } + + $AxisPos["B"] = $MaxBottom + $ScaleSpacing; + } + } + } + } + } + + function isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) + { + if ( $LabelingMethod == LABELING_DIFFERENT && $Value != $LastValue ) { return(TRUE); } + if ( $LabelingMethod == LABELING_DIFFERENT && $Value == $LastValue ) { return(FALSE); } + if ( $LabelingMethod == LABELING_ALL && $LabelSkip == 0 ) { return(TRUE); } + if ( $LabelingMethod == LABELING_ALL && ($ID+$LabelSkip) % ($LabelSkip+1) != 1 ) { return(FALSE); } + + return(TRUE); + } + + /* Compute the scale, check for the best visual factors */ + function computeScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID=0) + { + /* Compute each factors */ + $Results = ""; + foreach ($Factors[$AxisID] as $Key => $Factor) + $Results[$Factor] = $this->processScale($XMin,$XMax,$MaxDivs,array($Factor),$AxisID); + + /* Remove scales that are creating to much decimals */ + $GoodScaleFactors = ""; + foreach ($Results as $Key => $Result) + { + $Decimals = preg_split("/\./",$Result["RowHeight"]); + if ( (!isset($Decimals[1])) || (strlen($Decimals[1]) < 6) ) { $GoodScaleFactors[] = $Key; } + } + + /* Found no correct scale, shame,... returns the 1st one as default */ + if ( $GoodScaleFactors == "" ) { return($Results[$Factors[0]]); } + + /* Find the factor that cause the maximum number of Rows */ + $MaxRows = 0; $BestFactor = 0; + foreach($GoodScaleFactors as $Key => $Factor) + { if ( $Results[$Factor]["Rows"] > $MaxRows ) { $MaxRows = $Results[$Factor]["Rows"]; $BestFactor = $Factor; } } + + /* Return the best visual scale */ + return($Results[$BestFactor]); + } + + /* Compute the best matching scale based on size & factors */ + function processScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID) + { + $ScaleHeight = abs(ceil($XMax)-floor($XMin)); + + if ( isset($this->DataSet->Data["Axis"][$AxisID]["Format"]) ) + $Format = $this->DataSet->Data["Axis"][$AxisID]["Format"]; + else + $Format = NULL; + + if ( isset($this->DataSet->Data["Axis"][$AxisID]["Display"]) ) + $Mode = $this->DataSet->Data["Axis"][$AxisID]["Display"]; + else + $Mode = AXIS_FORMAT_DEFAULT; + + $Scale = ""; + if ( $XMin != $XMax ) + { + $Found = FALSE; $Rescaled = FALSE; $Scaled10Factor = .0001; $Result = 0; + while(!$Found) + { + foreach($Factors as $Key => $Factor) + { + if ( !$Found ) + { + if ( !($this->modulo($XMin,$Factor*$Scaled10Factor) == 0) || ($XMin != floor($XMin))) { $XMinRescaled = floor($XMin/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor; } else { $XMinRescaled = $XMin; } + if ( !($this->modulo($XMax,$Factor*$Scaled10Factor) == 0) || ($XMax != floor($XMax))) { $XMaxRescaled = floor($XMax/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor+($Factor*$Scaled10Factor); } else { $XMaxRescaled = $XMax; } + $ScaleHeightRescaled = abs($XMaxRescaled-$XMinRescaled); + + if ( !$Found && floor($ScaleHeightRescaled/($Factor*$Scaled10Factor)) <= $MaxDivs ) { $Found = TRUE; $Rescaled = TRUE; $Result = $Factor * $Scaled10Factor; } + } + } + $Scaled10Factor = $Scaled10Factor * 10; + } + + /* ReCall Min / Max / Height */ + if ( $Rescaled ) { $XMin = $XMinRescaled; $XMax = $XMaxRescaled; $ScaleHeight = $ScaleHeightRescaled; } + + /* Compute rows size */ + $Rows = floor($ScaleHeight / $Result); if ( $Rows == 0 ) { $Rows = 1; } + $RowHeight = $ScaleHeight / $Rows; + + /* Return the results */ + $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin; $Scale["XMax"] = $XMax; + + /* Compute the needed decimals for the metric view to avoid repetition of the same X Axis labels */ + if ( $Mode == AXIS_FORMAT_METRIC && $Format == NULL ) + { + $Done = FALSE; $GoodDecimals = 0; + for($Decimals=0;$Decimals<=10;$Decimals++) + { + if ( !$Done ) + { + $LastLabel = "zob"; $ScaleOK = TRUE; + for($i=0;$i<=$Rows;$i++) + { + $Value = $XMin + $i*$RowHeight; + $Label = $this->scaleFormat($Value,AXIS_FORMAT_METRIC,$Decimals); + + if ( $LastLabel == $Label ) { $ScaleOK = FALSE; } + $LastLabel = $Label; + } + if ( $ScaleOK ) { $Done = TRUE; $GoodDecimals = $Decimals; } + } + } + + $Scale["Format"] = $GoodDecimals; + } + } + else + { + /* If all values are the same we keep a +1/-1 scale */ + $Rows = 2; $XMin = $XMax-1; $XMax = $XMax+1; $RowHeight = 1; + + /* Return the results */ + $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin; $Scale["XMax"] = $XMax; + } + + return($Scale); + } + + /* + function modulo($Value1,$Value2) + { + if ($Value1 > $Value2) { return 0; } + if (floor($Value2) == 0) { return(0); } + if (floor($Value2) != 0) { return($Value1 % $Value2); } + + $MinValue = min($Value1,$Value2); $Factor = 10; + while ( floor($MinValue*$Factor) == 0 ) + { $Factor = $Factor * 10; } + + return(($Value1*$Factor) % ($Value2*$Factor)); + } + */ + function modulo( $Value1, $Value2 ) { + if ($Value1 > $Value2) { return 0; } + + if ($Value2 == 0) { + return 0; + } else { + $quotient = floor( $Value1 / $Value2 ); + + return $Value1 - ( $quotient * $Value2 ); + } + } + + /* Draw an X threshold */ + function drawXThreshold($Value,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 6; + $Wide = isset($Format["Wide"]) ? $Format["Wide"] : FALSE; + $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5; + $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : NULL; + $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP; + $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 5; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 3; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 30; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + $ValueIsLabel = isset($Format["ValueIsLabel"]) ? $Format["ValueIsLabel"] : FALSE; + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + $XScale = $this->scaleGetXSettings(); + + if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawXThreshold($ID,$Format); } return(0); } + + if ( $ValueIsLabel ) + { + $Format["ValueIsLabel"] = FALSE; + foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $SerieValue) + { if ( $SerieValue == $Value ) { $this->drawXThreshold($Key,$Format); } } + + return(0); + } + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha, + "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); + + if ( $Caption == NULL ) + { + if ( isset($Data["Abscissa"]) ) + { + if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$Value]) ) + $Caption = $Data["Series"][$Data["Abscissa"]]["Data"][$Value]; + else + $Caption = $Value; + } + else + $Caption = $Value; + } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1]; + $XPos = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value; + $YPos1 = $this->GraphAreaY1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaY2 - $Data["YMargin"]; + + if ( $XPos >= $this->GraphAreaX1 + $AbscissaMargin && $XPos <= $this->GraphAreaX2 - $AbscissaMargin ) + { + $this->drawLine($XPos,$YPos1,$XPos,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($XPos-1,$YPos1,$XPos-1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($XPos+1,$YPos1,$XPos+1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + else + { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + + $this->drawText($XPos,$Y,$Caption,$CaptionSettings); + } + + return(array("X"=>$XPos)); + } + } + elseif( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1]; + $XPos = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value; + $YPos1 = $this->GraphAreaX1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaX2 - $Data["YMargin"]; + + if ( $XPos >= $this->GraphAreaY1 + $AbscissaMargin && $XPos <= $this->GraphAreaY2 - $AbscissaMargin ) + { + $this->drawLine($YPos1,$XPos,$YPos2,$XPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($YPos1,$XPos-1,$YPos2,$XPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($YPos1,$XPos+1,$YPos2,$XPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + + $this->drawText($Y,$XPos,$Caption,$CaptionSettings); + } + + return(array("X"=>$XPos)); + } + } + } + + /* Draw an X threshold area */ + function drawXThresholdArea($Value1,$Value2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20; + $Border = isset($Format["Border"]) ? $Format["Border"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20; + $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2; + $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : NULL; + $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO; + $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255; + $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255; + $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255; + $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100; + $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE; + + $RestoreShadow = $this->Shadow; + if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; } + + if ($BorderAlpha >100) { $BorderAlpha = 100;} + + $Data = $this->DataSet->getData(); + $XScale = $this->scaleGetXSettings(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1]; + $XPos1 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value1; + $XPos2 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value2; + $YPos1 = $this->GraphAreaY1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaY2 - $Data["YMargin"]; + + if ( $XPos1 < $this->GraphAreaX1 + $XScale[0] ) { $XPos1 = $this->GraphAreaX1 + $XScale[0]; } + if ( $XPos1 > $this->GraphAreaX2 - $XScale[0] ) { $XPos1 = $this->GraphAreaX2 - $XScale[0]; } + if ( $XPos2 < $this->GraphAreaX1 + $XScale[0] ) { $XPos2 = $this->GraphAreaX1 + $XScale[0]; } + if ( $XPos2 > $this->GraphAreaX2 - $XScale[0] ) { $XPos2 = $this->GraphAreaX2 - $XScale[0]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + + if ( $NameAngle == ZONE_NAME_ANGLE_AUTO ) + { + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"]; + if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; } + } + $this->Shadow = $RestoreShadow; + $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("X1"=>$XPos1,"X2"=>$XPos2)); + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1]; + $XPos1 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value1; + $XPos2 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value2; + $YPos1 = $this->GraphAreaX1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaX2 - $Data["YMargin"]; + + if ( $XPos1 < $this->GraphAreaY1 + $XScale[0] ) { $XPos1 = $this->GraphAreaY1 + $XScale[0]; } + if ( $XPos1 > $this->GraphAreaY2 - $XScale[0] ) { $XPos1 = $this->GraphAreaY2 - $XScale[0]; } + if ( $XPos2 < $this->GraphAreaY1 + $XScale[0] ) { $XPos2 = $this->GraphAreaY1 + $XScale[0]; } + if ( $XPos2 > $this->GraphAreaY2 - $XScale[0] ) { $XPos2 = $this->GraphAreaY2 - $XScale[0]; } + + $this->drawFilledRectangle($YPos1,$XPos1,$YPos2,$XPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->drawLine($YPos1,$XPos1,$YPos2,$XPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($YPos1,$XPos2,$YPos2,$XPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + + $this->Shadow = $RestoreShadow; + $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("X1"=>$XPos1,"X2"=>$XPos2)); + } + } + + /* Draw an Y threshold with the computed scale */ + function drawThreshold($Value,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 6; + $Wide = isset($Format["Wide"]) ? $Format["Wide"] : FALSE; + $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5; + $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : NULL; + $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP; + $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + $NoMargin = isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE; + + if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawThreshold($ID,$Format); } return(0); } + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha, + "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $NoMargin ) { $AbscissaMargin = 0; } + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + if ( $Caption == NULL ) { $Caption = $Value; } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $YPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID)); + if ( $YPos >= $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] && $YPos <= $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) + { + $X1 = $this->GraphAreaX1 + $AbscissaMargin; + $X2 = $this->GraphAreaX2 - $AbscissaMargin; + + $this->drawLine($X1,$YPos,$X2,$YPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($X1,$YPos-1,$X2,$YPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($X1,$YPos+1,$X2,$YPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $X = $X1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + { $X = $X2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + + $this->drawText($X,$YPos,$Caption,$CaptionSettings); + } + } + + return(array("Y"=>$YPos)); + } + + if ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID)); + if ( $XPos >= $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] && $XPos <= $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) + { + $Y1 = $this->GraphAreaY1 + $AbscissaMargin; + $Y2 = $this->GraphAreaY2 - $AbscissaMargin; + + $this->drawLine($XPos,$Y1,$XPos,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($XPos-1,$Y1,$XPos-1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($XPos+1,$Y1,$XPos+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $Y1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + else + { $Y = $Y2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + + $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; + $this->drawText($XPos,$Y,$Caption,$CaptionSettings); + } + } + + return(array("Y"=>$XPos)); + } + } + + /* Draw a threshold with the computed scale */ + function drawThresholdArea($Value1,$Value2,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20; + $Border = isset($Format["Border"]) ? $Format["Border"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20; + $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2; + $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : NULL; + $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO; + $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255; + $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255; + $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255; + $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100; + $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE; + $NoMargin = isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE; + + if ($Value1 > $Value2) { list($Value1, $Value2) = array($Value2, $Value1); } + + $RestoreShadow = $this->Shadow; + if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; } + + if ($BorderAlpha >100) { $BorderAlpha = 100;} + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $NoMargin ) { $AbscissaMargin = 0; } + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XPos1 = $this->GraphAreaX1 + $AbscissaMargin; + $XPos2 = $this->GraphAreaX2 - $AbscissaMargin; + $YPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID)); + $YPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID)); + + if ( $YPos1 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos1 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos2 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos2 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos2,$YPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos1,$YPos2,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + $this->Shadow = $RestoreShadow; + $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("Y1"=>$YPos1,"Y2"=>$YPos2)); + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $YPos1 = $this->GraphAreaY1 + $AbscissaMargin; + $YPos2 = $this->GraphAreaY2 - $AbscissaMargin; + $XPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID)); + $XPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID)); + + if ( $XPos1 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos1 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos2 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos2 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($YPos2-$YPos1)/2 + $YPos1; + $YPos = ($XPos2-$XPos1)/2 + $XPos1; + + if ( $NameAngle == ZONE_NAME_ANGLE_AUTO ) + { + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"]; + if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; } + } + $this->Shadow = $RestoreShadow; + $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("Y1"=>$XPos1,"Y2"=>$XPos2)); + } + } + + function scaleGetXSettings() + { + $Data = $this->DataSet->getData(); + foreach($Data["Axis"] as $AxisID => $Settings) + { + if ( $Settings["Identity"] == AXIS_X ) + { + $Rows = $Settings["Rows"]; + + return(array($Settings["Margin"],$Rows)); + } + } + } + + function scaleComputeY($Values,$Option="",$ReturnOnly0Height=FALSE) + { + $AxisID = isset($Option["AxisID"]) ? $Option["AxisID"] : 0; + $SerieName = isset($Option["SerieName"]) ? $Option["SerieName"] : NULL; + + $Data = $this->DataSet->getData(); + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $SerieName != NULL ) { $AxisID = $Data["Series"][$SerieName]["Axis"]; } + if ( !is_array($Values) ) { $tmp = $Values; $Values = ""; $Values[0] = $tmp; } + + $Result = ""; + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + $Step = $Height / $ScaleHeight; + + if ( $ReturnOnly0Height ) + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } } + else + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } } + } + else + { + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleWidth = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + + if ($ScaleWidth > 0) { + $Step = $Width / $ScaleWidth; + } else { + $Step = 1; // or change this to 0 if it doesn't work, I am not sure what this line does. + } + + if ( $ReturnOnly0Height ) + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } } + else + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } } + } + + if ( count($Result) == 1 ) + return($Result[0]); + else + return($Result); + } + + /* Format the axis values */ + function scaleFormat($Value,$Mode=NULL,$Format=NULL,$Unit=NULL) + { + if ( $Value == VOID ) { return(""); } + + if ( $Mode == AXIS_FORMAT_TRAFFIC ) + { + if ( $Value == 0 ) { return("0B"); } + $Units = array("B","KB","MB","GB","TB","PB"); + $Sign = ""; if ( $Value < 0 ) { $Value = abs($Value); $Sign = "-"; } + + $Value = number_format($Value/pow(1024,($Scale=floor(log($Value,1024)))),2,",","."); + return($Sign.$Value." ".$Units[$Scale]); + } + + if ( $Mode == AXIS_FORMAT_CUSTOM ) + { if ( function_exists($Format) ) { return(call_user_func($Format,$Value)); } } + + if ( $Mode == AXIS_FORMAT_DATE ) + { if ( $Format == NULL ) { $Pattern = "d/m/Y"; } else { $Pattern = $Format; } return(gmdate($Pattern,$Value)); } + + if ( $Mode == AXIS_FORMAT_TIME ) + { if ( $Format == NULL ) { $Pattern = "H:i:s"; } else { $Pattern = $Format; } return(gmdate($Pattern,$Value)); } + + if ( $Mode == AXIS_FORMAT_CURRENCY ) + { return($Format.number_format($Value,2)); } + + if ( $Mode == AXIS_FORMAT_METRIC ) + { + if (abs($Value) > 1000000000) + return(round($Value/1000000000,$Format)."g".$Unit); + if (abs($Value) > 1000000) + return(round($Value/1000000,$Format)."m".$Unit); + elseif (abs($Value) >= 1000) + return(round($Value/1000,$Format)."k".$Unit); + + } + return($Value.$Unit); + } + + /* Write Max value on a chart */ + function writeBounds($Type=BOUND_BOTH,$Format=NULL) + { + $MaxLabelTxt = isset($Format["MaxLabelTxt"]) ? $Format["MaxLabelTxt"] : "max="; + $MinLabelTxt = isset($Format["MinLabelTxt"]) ? $Format["MinLabelTxt"] : "min="; + $Decimals = isset($Format["Decimals"]) ? $Format["Decimals"] : 1; + $ExcludedSeries = isset($Format["ExcludedSeries"]) ? $Format["ExcludedSeries"] : ""; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $MaxDisplayR = isset($Format["MaxDisplayR"]) ? $Format["MaxDisplayR"] : 0; + $MaxDisplayG = isset($Format["MaxDisplayG"]) ? $Format["MaxDisplayG"] : 0; + $MaxDisplayB = isset($Format["MaxDisplayB"]) ? $Format["MaxDisplayB"] : 0; + $MinDisplayR = isset($Format["MinDisplayR"]) ? $Format["MinDisplayR"] : 255; + $MinDisplayG = isset($Format["MinDisplayG"]) ? $Format["MinDisplayG"] : 255; + $MinDisplayB = isset($Format["MinDisplayB"]) ? $Format["MinDisplayB"] : 255; + $MinLabelPos = isset($Format["MinLabelPos"]) ? $Format["MinLabelPos"] : BOUND_LABEL_POS_AUTO; + $MaxLabelPos = isset($Format["MaxLabelPos"]) ? $Format["MaxLabelPos"] : BOUND_LABEL_POS_AUTO; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha); + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $Data = $this->DataSet->getData(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && !isset($ExcludedSeries[$SerieName])) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $MinValue = $this->DataSet->getMin($SerieName); + $MaxValue = $this->DataSet->getMax($SerieName); + + $MinPos = VOID; $MaxPos = VOID; + foreach($Serie["Data"] as $Key => $Value) + { + if ( $Value == $MinValue && $MinPos == VOID ) { $MinPos = $Key; } + if ( $Value == $MaxValue ) { $MaxPos = $Key; } + } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; + $X = $this->GraphAreaX1 + $XMargin; + $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0; + + if ( $Type == BOUND_MAX || $Type == BOUND_BOTH ) + { + if ( $MaxLabelPos == BOUND_LABEL_POS_TOP || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; } + if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; } + + $XPos = $X + $MaxPos*$XStep + $SerieOffset; + $Label = $MaxLabelTxt.$this->scaleFormat(round($MaxValue,$Decimals),$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); } + + $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG; + $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($XPos+$XOffset,$YPos+$YOffset,$Label,$CaptionSettings); + } + + if ( $Type == BOUND_MIN || $Type == BOUND_BOTH ) + { + if ( $MinLabelPos == BOUND_LABEL_POS_TOP || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; } + if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; } + + $XPos = $X + $MinPos*$XStep + $SerieOffset; + $Label = $MinLabelTxt.$this->scaleFormat(round($MinValue,$Decimals),$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); } + + $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG; + $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($XPos+$XOffset,$YPos-$DisplayOffset+$YOffset,$Label,$CaptionSettings); + } + } + else + { + $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; + $X = $this->GraphAreaY1 + $XMargin; + $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0; + + if ( $Type == BOUND_MAX || $Type == BOUND_BOTH ) + { + if ( $MaxLabelPos == BOUND_LABEL_POS_TOP || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; } + if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; } + + $XPos = $X + $MaxPos*$XStep + $SerieOffset; + $Label = $MaxLabelTxt.$this->scaleFormat($MaxValue,$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);} + + $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG; + $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings); + } + + if ( $Type == BOUND_MIN || $Type == BOUND_BOTH ) + { + if ( $MinLabelPos == BOUND_LABEL_POS_TOP || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; } + if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; } + + $XPos = $X + $MinPos*$XStep + $SerieOffset; + $Label = $MinLabelTxt.$this->scaleFormat($MinValue,$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);} + + $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG; + $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings); + } + } + } + } + } + + /* Draw a plot chart */ + function drawPlotChart($Format=NULL) + { + $PlotSize = isset($Format["PlotSize"]) ? $Format["PlotSize"] : NULL; + $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 50; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 50; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 50; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30; + $BorderSize = isset($Format["BorderSize"]) ? $Format["BorderSize"] : 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( isset($Serie["Weight"]) ) { $SerieWeight = $Serie["Weight"] + 2; } else { $SerieWeight = 2; } + if ( $PlotSize != NULL ) { $SerieWeight = $PlotSize; } + + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + if ( isset($Serie["Picture"]) ) + { $Picture = $Serie["Picture"]; list($PicWidth,$PicHeight,$PicType) = $this->getPicInfo($Picture); } + else { $Picture = NULL; $PicOffset = 0; } + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Shape = $Serie["Shape"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + if ( $Picture != NULL ) { $PicOffset = $PicHeight / 2; $SerieWeight = 0; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset-$SerieWeight-$BorderSize-$PicOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $Y != VOID ) + { + if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Picture != NULL ) + { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); } + else + { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); } + } + $X = $X + $XStep; + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + if ( $Picture != NULL ) { $PicOffset = $PicWidth / 2; $SerieWeight = 0; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset+$SerieWeight+$BorderSize+$PicOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $X != VOID ) + { + if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Picture != NULL ) + { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); } + else + { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); } + } + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a spline chart */ + function drawSplineChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; // 234 + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; // 55 + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; // 26 + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $WayPoints = ""; + $Force = $XStep / 5; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Y == VOID && $LastY != NULL ) + { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; } + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); } + + if ( $Y != VOID ) + $WayPoints[] = array($X,$Y); + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + $LastX = $X; $LastY = $Y; + $X = $X + $XStep; + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $WayPoints = ""; + $Force = $YStep / 5; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $X == VOID && $LastX != NULL ) + { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; } + + if ( $X != VOID && $LastX == NULL && $LastGoodX != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); } + + if ( $X != VOID ) + $WayPoints[] = array($X,$Y); + + if ( $X != VOID ) { $LastGoodX = $X; $LastGoodY = $Y; } + if ( $X == VOID ) { $X = NULL; } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + } + } + } + + /* Draw a filled spline chart */ + function drawFilledSplineChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + if ( $AroundZero ) { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); } + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Params) + { + $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"])); + $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"])); + } + } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $WayPoints = ""; + $Force = $XStep / 5; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + $LastX = ""; $LastY = ""; + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $Y == VOID ) + { + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]+1; + } + $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + $WayPoints = ""; + } + else + $WayPoints[] = array($X,$Y-.5); /* -.5 for AA visual fix */ + + $X = $X + $XStep; + } + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]+1; + } + $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $WayPoints = ""; + $Force = $YStep / 5; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $X == VOID ) + { + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"]; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]; + } + $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + $WayPoints = ""; + } + else + $WayPoints[] = array($X,$Y); + + $Y = $Y + $YStep; + } + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"]; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]; + } + $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + } + } + } + } + + /* Draw a line chart */ + function drawLineChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + $ForceColor = isset($Format["ForceColor"]) ? $Format["ForceColor"] : FALSE; + $ForceR = isset($Format["ForceR"]) ? $Format["ForceR"] : 0; + $ForceG = isset($Format["ForceG"]) ? $Format["ForceG"] : 0; + $ForceB = isset($Format["ForceB"]) ? $Format["ForceB"] : 0; + $ForceAlpha = isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : 100; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $ForceColor ) + { $R = $ForceR; $G = $ForceG; $B = $ForceB; $Alpha = $ForceAlpha; } + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + $LastX = $X; $LastY = $Y; + $X = $X + $XStep; + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { $this->drawText($X+$DisplayOffset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + + if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a line chart */ + function drawZoneChart($SerieA,$SerieB,$Format=NULL) + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $LineR = isset($Format["LineR"]) ? $Format["LineR"] : 150; + $LineG = isset($Format["LineG"]) ? $Format["LineG"] : 150; + $LineB = isset($Format["LineB"]) ? $Format["LineB"] : 150; + $LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 50; + $LineTicks = isset($Format["LineTicks"]) ? $Format["LineTicks"] : 1; + $AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 150; + $AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 150; + $AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 150; + $AreaAlpha = isset($Format["AreaAlpha"]) ? $Format["AreaAlpha"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + if ( !isset($Data["Series"][$SerieA]["Data"]) || !isset($Data["Series"][$SerieB]["Data"]) ) { return(0); } + $SerieAData = $Data["Series"][$SerieA]["Data"]; + $SerieBData = $Data["Series"][$SerieB]["Data"]; + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArrayA = $this->scaleComputeY($SerieAData,array("AxisID"=>$AxisID)); + $PosArrayB = $this->scaleComputeY($SerieBData,array("AxisID"=>$AxisID)); + if ( count($PosArrayA) != count($PosArrayB) ) { return(0); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + $LastX = NULL; $LastY1 = NULL; $LastY2 = NULL; + $BoundsA = ""; $BoundsB = ""; + foreach($PosArrayA as $Key => $Y1) + { + $Y2 = $PosArrayB[$Key]; + + $BoundsA[] = $X; $BoundsA[] = $Y1; + $BoundsB[] = $X; $BoundsB[] = $Y2; + + $LastX = $X; + $LastY1 = $Y1; $LastY2 = $Y2; + + $X = $X + $XStep; + } + $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB)); + $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha)); + + for($i=0;$i<=count($BoundsA)-4;$i=$i+2) + { + $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + $LastY = NULL; $LastX1 = NULL; $LastX2 = NULL; + $BoundsA = ""; $BoundsB = ""; + foreach($PosArrayA as $Key => $X1) + { + $X2 = $PosArrayB[$Key]; + + $BoundsA[] = $X1; $BoundsA[] = $Y; + $BoundsB[] = $X2; $BoundsB[] = $Y; + + $LastY = $Y; + $LastX1 = $X1; $LastX2 = $X2; + + $Y = $Y + $YStep; + } + $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB)); + $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha)); + + for($i=0;$i<=count($BoundsA)-4;$i=$i+2) + { + $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + } + } + } + + /* Draw a step chart */ + function drawStepChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : FALSE; + $ReCenter = isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Y <= $LastY ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + { + $this->drawLine($LastX,$LastY,$X,$LastY,$Color); + $this->drawLine($X,$LastY,$X,$Y,$Color); + if ( $ReCenter && $X+$XStep < $this->GraphAreaX2 - $XMargin ) + { + $this->drawLine($X,$Y,$X+$XStep,$Y,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } } + } + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { + if ( $ReCenter ) + { + $this->drawLine($LastGoodX+$XStep,$LastGoodY,$X,$LastGoodY,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX+$XStep-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + $this->drawLine($LastGoodX,$LastGoodY,$X,$LastGoodY,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + $this->drawLine($X,$LastGoodY,$X,$Y,$BreakSettings); + $LastGoodY = NULL; + } + elseif( !$BreakVoid && $LastGoodY == NULL && $Y != VOID ) + { + $this->drawLine($this->GraphAreaX1 + $XMargin,$Y,$X,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($this->GraphAreaX1+$XMargin-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; } + $X = $X + $XStep; + } + if ( $ReCenter ) + { + $this->drawLine($LastX,$LastY,$this->GraphAreaX2 - $XMargin,$LastY,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($this->GraphAreaX2-$XMargin+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $X >= $LastX ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; } + $this->drawText($X+$Offset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + { + $this->drawLine($LastX,$LastY,$LastX,$Y,$Color); + $this->drawLine($LastX,$Y,$X,$Y,$Color); + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid ) + { + $this->drawLine($LastGoodX,$LastGoodY,$LastGoodX,$LastGoodY+$YStep,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($LastGoodY+$YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + $this->drawLine($LastGoodX,$LastGoodY+$YStep,$LastGoodX,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY+$YStep-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + $this->drawLine($LastGoodX,$Y,$X,$Y,$BreakSettings); + $LastGoodY = NULL; + } + elseif ( $X != VOID && $LastGoodY == NULL && !$BreakVoid ) + { + $this->drawLine($X,$this->GraphAreaY1 + $XMargin,$X,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($this->GraphAreaY1+$XMargin-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + if ( !$Init && $ReCenter ) { $Y = $Y - $YStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; } + $Y = $Y + $YStep; + } + if ( $ReCenter ) + { + $this->drawLine($LastX,$LastY,$LastX,$this->GraphAreaY2 - $XMargin,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$ImageMapPlotSize).",".floor($this->GraphAreaY2-$XMargin+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + } + } + } + } + + /* Draw a step chart */ + function drawFilledStepChart($Format=NULL) + { + $ReCenter = isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + if ( $ForceTransparency != NULL ) { $Color["Alpha"] = $ForceTransparency; } else { $Color["Alpha"] = $Alpha; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Points = ""; $Init = FALSE; + foreach($PosArray as $Key => $Y) + { + if ( $Y == VOID && $LastX != NULL && $LastY != NULL && $Points !="" ) + { + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $X; $Points[] = $LastY; + $Points[] = $X; $Points[] = $YZero; + $this->drawPolygon($Points,$Color); + $Points = ""; + } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + { + if ( $Points == "") { $Points[] = $LastX; $Points[] = $YZero; } + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $X; $Points[] = $LastY; + $Points[] = $X; $Points[] = $Y; + } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; } + $X = $X + $XStep; + } + + if ( $ReCenter ) + { + $Points[] = $LastX+$XStep/2; $Points[] = $LastY; + $Points[] = $LastX+$XStep/2; $Points[] = $YZero; + } + else + { $Points[] = $LastX; $Points[] = $YZero; } + + $this->drawPolygon($Points,$Color); + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Points = ""; + foreach($PosArray as $Key => $X) + { + if ( $X == VOID && $LastX != NULL && $LastY != NULL && $Points !="" ) + { + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $LastX; $Points[] = $Y; + $Points[] = $YZero; $Points[] = $Y; + $this->drawPolygon($Points,$Color); + $Points = ""; + } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + { + if ( $Points == "") { $Points[] = $YZero; $Points[] = $LastY; } + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $LastX; $Points[] = $Y; + $Points[] = $X; $Points[] = $Y; + } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + if ( $LastX == NULL && $ReCenter ) { $Y = $Y - $YStep/2; } + $LastX = $X; $LastY = $Y; + if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; } + $Y = $Y + $YStep; + } + + if ( $ReCenter ) + { + $Points[] = $LastX; $Points[] = $LastY+$YStep/2; + $Points[] = $YZero; $Points[] = $LastY+$YStep/2; + } + else + { $Points[] = $YZero; $Points[] = $LastY; } + + $this->drawPolygon($Points,$Color); + } + } + } + } + + /* Draw an area chart */ + function drawAreaChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : 25; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Params) + { + $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"])); + $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"])); + } + } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + $Areas = ""; $AreaID = 0; + $Areas[$AreaID][] = $this->GraphAreaX1 + $XMargin; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $Y == VOID && isset($Areas[$AreaID]) ) + { + if($LastX == NULL) + { $Areas[$AreaID][] = $X; } + else + { $Areas[$AreaID][] = $LastX; } + + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + $AreaID++; + } + elseif ($Y != VOID) + { + if ( !isset($Areas[$AreaID]) ) + { + $Areas[$AreaID][] = $X; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + } + + $Areas[$AreaID][] = $X; + $Areas[$AreaID][] = $Y; + } + + $LastX = $X; + $X = $X + $XStep; + } + $Areas[$AreaID][] = $LastX; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + + /* Handle shadows in the areas */ + if ( $this->Shadow ) + { + $ShadowArea = ""; + foreach($Areas as $Key => $Points) + { + $ShadowArea[$Key] = ""; + foreach($Points as $Key2 => $Value) + { + if ( $Key2 % 2 == 0 ) + { $ShadowArea[$Key][] = $Value + $this->ShadowX; } + else + { $ShadowArea[$Key][] = $Value + $this->ShadowY; } + } + } + + foreach($ShadowArea as $Key => $Points) + $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold); + + foreach($Areas as $Key => $Points) + $this->drawPolygonChart($Points,$Color); + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + $Areas = ""; $AreaID = 0; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $this->GraphAreaY1 + $XMargin; + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X+$Offset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $X == VOID && isset($Areas[$AreaID]) ) + { + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + + if($LastY == NULL) + { $Areas[$AreaID][] = $Y; } + else + { $Areas[$AreaID][] = $LastY; } + + $AreaID++; + } + elseif ($X != VOID) + { + if ( !isset($Areas[$AreaID]) ) + { + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $Y; + } + + $Areas[$AreaID][] = $X; + $Areas[$AreaID][] = $Y; + } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $LastY; + + /* Handle shadows in the areas */ + if ( $this->Shadow ) + { + $ShadowArea = ""; + foreach($Areas as $Key => $Points) + { + $ShadowArea[$Key] = ""; + foreach($Points as $Key2 => $Value) + { + if ( $Key2 % 2 == 0 ) + { $ShadowArea[$Key][] = $Value + $this->ShadowX; } + else + { $ShadowArea[$Key][] = $Value + $this->ShadowY; } + } + } + + foreach($ShadowArea as $Key => $Points) + $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold); + + foreach($Areas as $Key => $Points) + $this->drawPolygonChart($Points,$Color); + } + } + } + } + + + /* Draw a bar chart */ + function drawBarChart($Format=NULL) + { + $Floating0Serie = isset($Format["Floating0Serie"]) ? $Format["Floating0Serie"] : NULL; + $Floating0Value = isset($Format["Floating0Value"]) ? $Format["Floating0Value"] : NULL; + $Draw0Line = isset($Format["Draw0Line"]) ? $Format["Draw0Line"] : FALSE; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_HORIZONTAL; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayFont = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontName; + $DisplaySize = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize; + $DisplayPos = isset($Format["DisplayPos"]) ? $Format["DisplayPos"] : LABEL_POS_OUTSIDE; + $DisplayShadow = isset($Format["DisplayShadow"]) ? $Format["DisplayShadow"] : TRUE; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Interleave = isset($Format["Interleave"]) ? $Format["Interleave"] : .5; + $Rounded = isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE; + $RoundRadius = isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Gradient = isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE; + $GradientMode = isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE; + $GradientAlpha = isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0; + $TxtMargin = isset($Format["TxtMargin"]) ? $Format["TxtMargin"] : 6; + $OverrideColors = isset($Format["OverrideColors"]) ? $Format["OverrideColors"] : NULL; + $OverrideSurrounding = isset($Format["OverrideSurrounding"]) ? $Format["OverrideSurrounding"] : 30; + $InnerSurrounding = isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL; + $InnerBorderR = isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1; + $InnerBorderG = isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1; + $InnerBorderB = isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( $OverrideColors != NULL ) + { + $OverrideColors = $this->validatePalette($OverrideColors,$OverrideSurrounding); + $this->DataSet->saveExtendedData("Palette",$OverrideColors); + } + + $RestoreShadow = $this->Shadow; + + $SeriesCount = $this->countDrawableSeries(); + $CurrentSerie = 0; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; } + if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); } + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB); + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Floating0Value != NULL ) + { $YZero = $this->scaleComputeY($Floating0Value,array("AxisID"=>$Serie["Axis"])); } + else + { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; } + if ( $XDivs == 0 ) { $XSize = ($this->GraphAreaX2-$this->GraphAreaX1)/($SeriesCount+$Interleave); } else { $XSize = ($XStep / ($SeriesCount+$Interleave) ); } + + $XOffset = -($XSize*$SeriesCount)/2 + $CurrentSerie * $XSize; + if ( $X + $XOffset <= $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $X + 1 ; } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $XOffset + $XSize / 2; + + if ( $Rounded || $BorderR != -1) { $XSpace = 1; } else { $XSpace = 0; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $ID = 0; + foreach($PosArray as $Key => $Y2) + { + if ( $Floating0Serie != NULL ) + { + if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) ) + { $Value = $Data["Series"][$Floating0Serie]["Data"][$Key]; } + else + { $Value = 0; } + + $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"])); + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; } + } + + if ( $OverrideColors != NULL ) + { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } } + + if ( $Y2 != VOID ) + { + $BarHeight = $Y1 - $Y2; + + if ( $Serie["Data"][$Key] == 0 ) + { + $this->drawLine($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y1,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1-1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y1+1),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$Color); + + if ( $InnerColor != NULL ) { $this->drawRectangle($X+$XOffset+$XSpace+1,min($Y1,$Y2)+1,$X+$XOffset+$XSize-$XSpace-1,max($Y1,$Y2)-1,$InnerColor); } + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + if ( $Serie["Data"][$Key] >= 0 ) + $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + else + $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + + $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_VERTICAL,$GradienColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $XSpan = floor($XSize / 3); + + $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSpan-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor1); + $this->drawGradientArea($X+$XOffset+$XSpan+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $Draw0Line ) + { + $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20); + + if ( abs($Y1 - $Y2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; } + if ( $Y1 - $Y2 < 0 ) { $Line0Width = -$Line0Width; } + + $this->drawFilledRectangle($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1)-$Line0Width,$Line0Color); + $this->drawLine($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1),$Line0Color); + } + } + + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $DisplayShadow ) { $this->Shadow = TRUE; } + + $Caption = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,90,$Caption); + $TxtHeight = $TxtPos[0]["Y"] - $TxtPos[1]["Y"] + $TxtMargin; + + if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtHeight) < abs($BarHeight) ) + { + $CenterX = (($X+$XOffset+$XSize-$XSpace)-($X+$XOffset+$XSpace))/2 + $X+$XOffset+$XSpace; + $CenterY = ($Y2-$Y1)/2 + $Y1; + + $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"Angle"=>90)); + } + else + { + if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X+$XOffset+$XSize/2,$Y2-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize)); + } + + $this->Shadow = $RestoreShadow; + } + } + + $X = $X + $XStep; + $ID++; + } + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = 0; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + + $Y = $this->GraphAreaY1 + $XMargin; + + if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; } + if ( $XDivs == 0 ) { $YSize = ($this->GraphAreaY2-$this->GraphAreaY1)/($SeriesCount+$Interleave); } else { $YSize = ($YStep / ($SeriesCount+$Interleave) ); } + + $YOffset = -($YSize*$SeriesCount)/2 + $CurrentSerie * $YSize; + if ( $Y + $YOffset <= $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $Y + 1 ; } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $YOffset + $YSize / 2; + + if ( $Rounded || $BorderR != -1 ) { $YSpace = 1; } else { $YSpace = 0; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $ID = 0 ; + foreach($PosArray as $Key => $X2) + { + if ( $Floating0Serie != NULL ) + { + if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) ) + $Value = $Data["Series"][$Floating0Serie]["Data"][$Key]; + else { $Value = 0; } + + $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"])); + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; } + } + + if ( $OverrideColors != NULL ) + { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } } + + if ( $X2 != VOID ) + { + $BarWidth = $X2 - $X1; + + if ( $Serie["Data"][$Key] == 0 ) + { + $this->drawLine($X1,$Y+$YOffset+$YSpace,$X1,$Y+$YOffset+$YSize-$YSpace,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1-1).",".floor($Y+$YOffset+$YSpace).",".floor($X1+1).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1).",".floor($Y+$YOffset+$YSpace).",".floor($X2).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X1+1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$Color); + + if ( $InnerColor != NULL ) { $this->drawRectangle(min($X1,$X2)+1,$Y+$YOffset+$YSpace+1,max($X1,$X2)-1,$Y+$YOffset+$YSize-$YSpace-1,$InnerColor); } + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + if ( $Serie["Data"][$Key] >= 0 ) + $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + else + $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + + $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_HORIZONTAL,$GradienColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $YSpan = floor($YSize / 3); + + $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSpan-$YSpace,DIRECTION_VERTICAL,$GradienColor1); + $this->drawGradientArea($X1,$Y+$YOffset+$YSpan,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_VERTICAL,$GradienColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $Draw0Line ) + { + $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20); + + if ( abs($X1 - $X2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; } + if ( $X2 - $X1 < 0 ) { $Line0Width = -$Line0Width; } + + $this->drawFilledRectangle(floor($X1),$Y+$YOffset+$YSpace,floor($X1)+$Line0Width,$Y+$YOffset+$YSize-$YSpace,$Line0Color); + $this->drawLine(floor($X1),$Y+$YOffset+$YSpace,floor($X1),$Y+$YOffset+$YSize-$YSpace,$Line0Color); + } + } + + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $DisplayShadow ) { $this->Shadow = TRUE; } + + $Caption = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"] + $TxtMargin; + + if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtWidth) < abs($BarWidth) ) + { + $CenterX = ($X2-$X1)/2 + $X1; + $CenterY = (($Y+$YOffset+$YSize-$YSpace)-($Y+$YOffset+$YSpace))/2 + ($Y+$YOffset+$YSpace); + + $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize)); + } + else + { + if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; } + $this->drawText($X2+$Offset,$Y+$YOffset+$YSize/2,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize)); + } + + $this->Shadow = $RestoreShadow; + } + } + $Y = $Y + $YStep; + $ID++; + } + } + $CurrentSerie++; + } + } + } + + /* Draw a bar chart */ + function drawStackedBarChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_AUTO; + $DisplayRound = isset($Format["DisplayRound"]) ? $Format["DisplayRound"] : 0; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayFont = isset($Format["DisplayFont"]) ? $Format["DisplayFont"] : $this->FontName; + $DisplaySize = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $Interleave = isset($Format["Interleave"]) ? $Format["Interleave"] : .5; + $Rounded = isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE; + $RoundRadius = isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Gradient = isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE; + $GradientMode = isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE; + $GradientAlpha = isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0; + $InnerSurrounding = isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL; + $InnerBorderR = isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1; + $InnerBorderG = isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1; + $InnerBorderB = isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $FontFactor = isset($Format["FontFactor"]) ? $Format["FontFactor"] : 8; + + $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $RestoreShadow = $this->Shadow; + + $LastX = ""; $LastY = ""; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = 255; $DisplayG = 255; $DisplayB = 255; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; } + if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + $Color = array("TransCorner"=>TRUE,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + $XSize = ($XStep / (1+$Interleave) ); + $XOffset = -($XSize/2); + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID && $Serie["Data"][$Key] != 0 ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; } + + if ( !isset($LastY[$Key] ) ) { $LastY[$Key] = ""; } + if ( !isset($LastY[$Key][$Pos] ) ) { $LastY[$Key][$Pos] = $YZero; } + + $Y1 = $LastY[$Key][$Pos]; + $Y2 = $Y1 - $Height; + + if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $Y1 != $YZero) ) { $YSpaceUp = 1; } else { $YSpaceUp = 0; } + if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $Y1 != $YZero) ) { $YSpaceDown = 1; } else { $YSpaceDown = 0; } + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset).",".floor($Y1-$YSpaceUp+$YSpaceDown).",".floor($X+$XOffset+$XSize).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$Color); + + if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X+$XOffset+1,$X+$XOffset+$XSize),min($Y1-$YSpaceUp+$YSpaceDown,$Y2)+1,max($X+$XOffset+1,$X+$XOffset+$XSize)-1,max($Y1-$YSpaceUp+$YSpaceDown,$Y2)-1,$InnerColor); $this->Shadow = $RestoreShadow;} + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $this->drawGradientArea($X+$XOffset,$Y1-1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+1,DIRECTION_VERTICAL,$GradientColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $XSpan = floor($XSize / 3); + + $this->drawGradientArea($X+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSpan,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor1); + $this->drawGradientArea($X+$XSpan+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $DisplayValues ) + { + $BarHeight = abs($Y2-$Y1)-2; + $BarWidth = $XSize+($XOffset/2)-$FontFactor; + + $Caption = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]); + $TxtWidth = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]); + + $XCenter = ( ($X+$XOffset+$XSize) - ($X+$XOffset) ) / 2 + $X+$XOffset; + $YCenter = ( ($Y2) - ($Y1-$YSpaceUp+$YSpaceDown) ) / 2 + $Y1-$YSpaceUp+$YSpaceDown; + + $Done = FALSE; + if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO ) + { + if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth ) + { + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + $Done = TRUE; + } + } + + if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) ) + { + if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight ) + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + } + } + + $LastY[$Key][$Pos] = $Y2; + } + + $X = $X + $XStep; + } + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + $YSize = $YStep / (1+$Interleave); + $YOffset = -($YSize/2); + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Width) + { + if ( $Width != VOID && $Serie["Data"][$Key] != 0 ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; } + + if ( !isset($LastX[$Key] ) ) { $LastX[$Key] = ""; } + if ( !isset($LastX[$Key][$Pos] ) ) { $LastX[$Key][$Pos] = $YZero; } + + $X1 = $LastX[$Key][$Pos]; + $X2 = $X1 + $Width; + + if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $X1 != $YZero) ) { $XSpaceLeft = 2; } else { $XSpaceLeft = 0; } + if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $X1 != $YZero) ) { $XSpaceRight = 2; } else { $XSpaceRight = 0; } + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1+$XSpaceLeft).",".floor($Y+$YOffset).",".floor($X2-$XSpaceRight).",".floor($Y+$YOffset+$YSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$Color); + + if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X1+$XSpaceLeft,$X2-$XSpaceRight)+1,min($Y+$YOffset,$Y+$YOffset+$YSize)+1,max($X1+$XSpaceLeft,$X2-$XSpaceRight)-1,max($Y+$YOffset,$Y+$YOffset+$YSize)-1,$InnerColor); $this->Shadow = $RestoreShadow;} + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_HORIZONTAL,$GradientColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $YSpan = floor($YSize / 3); + + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSpan,DIRECTION_VERTICAL,$GradientColor1); + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset+$YSpan,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_VERTICAL,$GradientColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $DisplayValues ) + { + $BarWidth = abs($X2-$X1)-$FontFactor; + $BarHeight = $YSize+($YOffset/2)-$FontFactor/2; + $Caption = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]); + $TxtWidth = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]); + + $XCenter = ( $X2 - $X1 ) / 2 + $X1; + $YCenter = ( ($Y+$YOffset+$YSize) - ($Y+$YOffset) ) / 2 + $Y+$YOffset; + + $Done = FALSE; + if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO ) + { + if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth ) + { + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + $Done = TRUE; + } + } + + if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) ) + { + if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight ) + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + } + } + + $LastX[$Key][$Pos] = $X2; + } + + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a stacked area chart */ + function drawStackedAreaChart($Format=NULL) + { + $DrawLine = isset($Format["DrawLine"]) ? $Format["DrawLine"] : FALSE; + $LineSurrounding = isset($Format["LineSurrounding"]) ? $Format["LineSurrounding"] : NULL; + $LineR = isset($Format["LineR"]) ? $Format["LineR"] : VOID; + $LineG = isset($Format["LineG"]) ? $Format["LineG"] : VOID; + $LineB = isset($Format["LineB"]) ? $Format["LineB"] : VOID; + $LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 100; + $DrawPlot = isset($Format["DrawPlot"]) ? $Format["DrawPlot"] : FALSE; + $PlotRadius = isset($Format["PlotRadius"]) ? $Format["PlotRadius"] : 2; + $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : 1; + $PlotBorderSurrounding = isset($Format["PlotBorderSurrounding"]) ? $Format["PlotBorderSurrounding"] : NULL; + $PlotBorderR = isset($Format["PlotBorderR"]) ? $Format["PlotBorderR"] : 0; + $PlotBorderG = isset($Format["PlotBorderG"]) ? $Format["PlotBorderG"] : 0; + $PlotBorderB = isset($Format["PlotBorderB"]) ? $Format["PlotBorderB"] : 0; + $PlotBorderAlpha = isset($Format["PlotBorderAlpha"]) ? $Format["PlotBorderAlpha"] : 50; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Build the offset data series */ + $OffsetData = ""; + $OverallOffset = ""; + $SerieOrder = ""; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $SerieOrder[] = $SerieName; + + foreach($Serie["Data"] as $Key => $Value) + { + if ( $Value == VOID ) { $Value = 0; } + if ($Value >= 0) { $Sign = "+"; } else { $Sign = "-"; } + if ( !isset($OverallOffset[$Key]) || !isset($OverallOffset[$Key][$Sign]) ) { $OverallOffset[$Key][$Sign] = 0; } + + if ( $Sign == "+" ) + { $Data["Series"][$SerieName]["Data"][$Key] = $Value + $OverallOffset[$Key][$Sign]; } + else + { $Data["Series"][$SerieName]["Data"][$Key] = $Value - $OverallOffset[$Key][$Sign]; } + + $OverallOffset[$Key][$Sign] = $OverallOffset[$Key][$Sign] + abs($Value); + } + } + } + $SerieOrder = array_reverse($SerieOrder); + + $LastX = ""; $LastY = ""; + foreach($SerieOrder as $Key => $SerieName) + { + $Serie = $Data["Series"][$SerieName]; + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $ForceTransparency != NULL ) { $Alpha = $ForceTransparency; } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + + if ( $LineSurrounding != NULL ) + $LineColor = array("R"=>$R+$LineSurrounding,"G"=>$G+$LineSurrounding,"B"=>$B+$LineSurrounding,"Alpha"=>$Alpha); + elseif ( $LineR != VOID ) + $LineColor = array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha); + else + $LineColor = $Color; + + if ( $PlotBorderSurrounding != NULL ) + $PlotBorderColor = array("R"=>$R+$PlotBorderSurrounding,"G"=>$G+$PlotBorderSurrounding,"B"=>$B+$PlotBorderSurrounding,"Alpha"=>$PlotBorderAlpha); + else + $PlotBorderColor = array("R"=>$PlotBorderR,"G"=>$PlotBorderG,"B"=>$PlotBorderB,"Alpha"=>$PlotBorderAlpha); + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $Plots = ""; $Plots[] = $X; $Plots[] = $YZero; + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID ) { $Plots[] = $X; $Plots[] = $YZero-$Height; } + $X = $X + $XStep; + } + $Plots[] = $X-$XStep; $Plots[] = $YZero; + + $this->drawPolygon($Plots,$Color); + + $this->Shadow = $RestoreShadow; + if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } } + if ( $DrawPlot ) + { + for($i=2; $i<=count($Plots)-4; $i=$i+2) + { + if ( $PlotBorder != 0 ) + { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); } + + $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color); + } + } + $this->Shadow = FALSE; + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $Plots = ""; $Plots[] = $YZero; $Plots[] = $Y; + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID ) { $Plots[] = $YZero+$Height; $Plots[] = $Y; } + $Y = $Y + $YStep; + } + $Plots[] = $YZero; $Plots[] = $Y-$YStep; + + $this->drawPolygon($Plots,$Color); + + $this->Shadow = $RestoreShadow; + if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } } + if ( $DrawPlot ) + { + for($i=2; $i<=count($Plots)-4; $i=$i+2) + { + if ( $PlotBorder != 0 ) + { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); } + + $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color); + } + } + $this->Shadow = FALSE; + } + } + } + $this->Shadow = $RestoreShadow; + } + + /* Returns a random color */ + function getRandomColor($Alpha=100) + { return(array("R"=>rand(0,255),"G"=>rand(0,255),"B"=>rand(0,255),"Alpha"=>$Alpha)); } + + /* Validate a palette */ + function validatePalette($Colors,$Surrounding=NULL) + { + $Result = ""; + + if ( !is_array($Colors) ) { return($this->getRandomColor()); } + + foreach($Colors as $Key => $Values) + { + if ( isset($Values["R"]) ) { $Result[$Key]["R"] = $Values["R"]; } else { $Result[$Key]["R"] = rand(0,255); } + if ( isset($Values["G"]) ) { $Result[$Key]["G"] = $Values["G"]; } else { $Result[$Key]["G"] = rand(0,255); } + if ( isset($Values["B"]) ) { $Result[$Key]["B"] = $Values["B"]; } else { $Result[$Key]["B"] = rand(0,255); } + if ( isset($Values["Alpha"]) ) { $Result[$Key]["Alpha"] = $Values["Alpha"]; } else { $Result[$Key]["Alpha"] = 100; } + + if ( $Surrounding != NULL ) + { + $Result[$Key]["BorderR"] = $Result[$Key]["R"] + $Surrounding; + $Result[$Key]["BorderG"] = $Result[$Key]["G"] + $Surrounding; + $Result[$Key]["BorderB"] = $Result[$Key]["B"] + $Surrounding; + } + else + { + if ( isset($Values["BorderR"]) ) { $Result[$Key]["BorderR"] = $Values["BorderR"]; } else { $Result[$Key]["BorderR"] = $Result[$Key]["R"]; } + if ( isset($Values["BorderG"]) ) { $Result[$Key]["BorderG"] = $Values["BorderG"]; } else { $Result[$Key]["BorderG"] = $Result[$Key]["G"]; } + if ( isset($Values["BorderB"]) ) { $Result[$Key]["BorderB"] = $Values["BorderB"]; } else { $Result[$Key]["BorderB"] = $Result[$Key]["B"]; } + if ( isset($Values["BorderAlpha"]) ) { $Result[$Key]["BorderAlpha"] = $Values["BorderAlpha"]; } else { $Result[$Key]["BorderAlpha"] = $Result[$Key]["Alpha"]; } + } + } + + return($Result); + } + + /* Draw the derivative chart associated to the data series */ + function drawDerivative($Format=NULL) + { + $Offset = isset($Format["Offset"]) ? $Format["Offset"] : 10; + $SerieSpacing = isset($Format["SerieSpacing"]) ? $Format["SerieSpacing"] : 3; + $DerivativeHeight = isset($Format["DerivativeHeight"]) ? $Format["DerivativeHeight"] : 4; + $ShadedSlopeBox = isset($Format["ShadedSlopeBox"]) ? $Format["ShadedSlopeBox"] : FALSE; + $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE; + $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255; + $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255; + $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255; + $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 20; + $DrawBorder = isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 100; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : TRUE; + $CaptionHeight = isset($Format["CaptionHeight"]) ? $Format["CaptionHeight"] : 10; + $CaptionWidth = isset($Format["CaptionWidth"]) ? $Format["CaptionWidth"] : 20; + $CaptionMargin = isset($Format["CaptionMargin"]) ? $Format["CaptionMargin"] : 4; + $CaptionLine = isset($Format["CaptionLine"]) ? $Format["CaptionLine"] : FALSE; + $CaptionBox = isset($Format["CaptionBox"]) ? $Format["CaptionBox"] : FALSE; + $CaptionBorderR = isset($Format["CaptionBorderR"]) ? $Format["CaptionBorderR"] : 0; + $CaptionBorderG = isset($Format["CaptionBorderG"]) ? $Format["CaptionBorderG"] : 0; + $CaptionBorderB = isset($Format["CaptionBorderB"]) ? $Format["CaptionBorderB"] : 0; + $CaptionFillR = isset($Format["CaptionFillR"]) ? $Format["CaptionFillR"] : 255; + $CaptionFillG = isset($Format["CaptionFillG"]) ? $Format["CaptionFillG"] : 255; + $CaptionFillB = isset($Format["CaptionFillB"]) ? $Format["CaptionFillB"] : 255; + $CaptionFillAlpha = isset($Format["CaptionFillAlpha"]) ? $Format["CaptionFillAlpha"] : 80; + $PositiveSlopeStartR = isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 184; + $PositiveSlopeStartG = isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 234; + $PositiveSlopeStartB = isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 88; + $PositiveSlopeEndR = isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 239; + $PositiveSlopeEndG = isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 31; + $PositiveSlopeEndB = isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 36; + $NegativeSlopeStartR = isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 184; + $NegativeSlopeStartG = isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 234; + $NegativeSlopeStartB = isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 88; + $NegativeSlopeEndR = isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 67; + $NegativeSlopeEndG = isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 124; + $NegativeSlopeEndB = isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 227; + + $Data = $this->DataSet->getData(); + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + $YPos = $this->DataSet->Data["GraphArea"]["Y2"] + $Offset; + else + $XPos = $this->DataSet->Data["GraphArea"]["X2"] + $Offset; + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + $AxisID = $Serie["Axis"]; + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $Caption ) + { + if ( $CaptionLine ) + { + $StartX = floor($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin); + $EndX = floor($this->GraphAreaX1-$CaptionMargin+$XMargin); + + $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + if ( $CaptionBox ) { $this->drawFilledRectangle($StartX,$YPos,$EndX,$YPos+$CaptionHeight,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); } + $this->drawLine($StartX+2,$YPos+($CaptionHeight/2),$EndX-2,$YPos+($CaptionHeight/2),$CaptionSettings); + } + else + $this->drawFilledRectangle($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin,$YPos,$this->GraphAreaX1-$CaptionMargin+$XMargin,$YPos+$CaptionHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB)); + } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + $TopY = $YPos + ($CaptionHeight/2) - ($DerivativeHeight/2); + $BottomY = $YPos + ($CaptionHeight/2) + ($DerivativeHeight/2); + + $StartX = floor($this->GraphAreaX1+$XMargin); + $EndX = floor($this->GraphAreaX2-$XMargin); + + if ( $DrawBackground ) { $this->drawFilledRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); } + if ( $DrawBorder ) { $this->drawRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Determine the Max slope index */ + $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID && $LastX != NULL ) + { $Slope = ($LastY - $Y); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } } + + if ( $Y == VOID ) + { $LastX = NULL; $LastY = NULL; } + else + { $LastX = $X; $LastY = $Y; } + } + + $LastX = NULL; $LastY = NULL; $LastColor = NULL; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID && $LastY != NULL ) + { + $Slope = ($LastY - $Y); + + if ( $Slope >= 0 ) + { + $SlopeIndex = (100 / $MaxSlope) * $Slope; + $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR; + $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG; + $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB; + } + elseif ( $Slope < 0 ) + { + $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope); + $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR; + $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG; + $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB; + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + + if ( $ShadedSlopeBox && $LastColor != NULL ) // && $Slope != 0 + { + $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + $this->drawGradientArea($LastX,$TopY,$X,$BottomY,DIRECTION_HORIZONTAL,$GradientSettings); + } + elseif ( !$ShadedSlopeBox || $LastColor == NULL ) // || $Slope == 0 + $this->drawFilledRectangle(floor($LastX),$TopY,floor($X),$BottomY,$Color); + + $LastColor = $Color; + } + + if ( $Y == VOID ) + { $LastY = NULL; } + else + { $LastX = $X; $LastY = $Y; } + + $X = $X + $XStep; + } + + $YPos = $YPos + $CaptionHeight + $SerieSpacing; + } + else + { + if ( $Caption ) + { + $StartY = floor($this->GraphAreaY1-$CaptionWidth+$XMargin-$CaptionMargin); + $EndY = floor($this->GraphAreaY1-$CaptionMargin+$XMargin); + if ( $CaptionLine ) + { + $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + if ( $CaptionBox ) { $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); } + $this->drawLine($XPos+($CaptionHeight/2),$StartY+2,$XPos+($CaptionHeight/2),$EndY-2,$CaptionSettings); + } + else + $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB)); + } + + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + $TopX = $XPos + ($CaptionHeight/2) - ($DerivativeHeight/2); + $BottomX = $XPos + ($CaptionHeight/2) + ($DerivativeHeight/2); + + $StartY = floor($this->GraphAreaY1+$XMargin); + $EndY = floor($this->GraphAreaY2-$XMargin); + + if ( $DrawBackground ) { $this->drawFilledRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); } + if ( $DrawBorder ) { $this->drawRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Determine the Max slope index */ + $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID && $LastX != NULL ) + { $Slope = ($X - $LastX); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } } + + if ( $X == VOID ) + { $LastX = NULL; } + else + { $LastX = $X; } + } + + $LastX = NULL; $LastY = NULL; $LastColor = NULL; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID && $LastX != NULL ) + { + $Slope = ($X - $LastX); + + if ( $Slope >= 0 ) + { + $SlopeIndex = (100 / $MaxSlope) * $Slope; + $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR; + $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG; + $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB; + } + elseif ( $Slope < 0 ) + { + $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope); + $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR; + $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG; + $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB; + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + + if ( $ShadedSlopeBox && $LastColor != NULL ) + { + $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + + $this->drawGradientArea($TopX,$LastY,$BottomX,$Y,DIRECTION_VERTICAL,$GradientSettings); + } + elseif ( !$ShadedSlopeBox || $LastColor == NULL ) + $this->drawFilledRectangle($TopX,floor($LastY),$BottomX,floor($Y),$Color); + + $LastColor = $Color; + } + + if ( $X == VOID ) + { $LastX = NULL; } + else + { $LastX = $X; $LastY = $Y; } + + $Y = $Y + $XStep; + } + + $XPos = $XPos + $CaptionHeight + $SerieSpacing; + } + + $this->Shadow = $RestoreShadow; + } + } + } + + /* Draw the line of best fit */ + function drawBestFit($Format="") + { + $OverrideTicks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $OverrideR = isset($Format["R"]) ? $Format["R"] : VOID; + $OverrideG = isset($Format["G"]) ? $Format["G"] : VOID; + $OverrideB = isset($Format["B"]) ? $Format["B"] : VOID; + $OverrideAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : VOID; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $OverrideR != VOID && $OverrideG != VOID && $OverrideB != VOID ) { $R = $OverrideR; $G = $OverrideG; $B = $OverrideB; } else { $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; } + if ( $OverrideTicks == NULL ) { $Ticks = $Serie["Ticks"]; } else { $Ticks = $OverrideTicks; } + if ( $OverrideAlpha == VOID ) { $Alpha = $Serie["Color"]["Alpha"]; } else { $Alpha = $OverrideAlpha; } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks); + + $AxisID = $Serie["Axis"]; + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID ) + { + $Sxy = $Sxy + $X*$Y; + $Sx = $Sx + $X; + $Sy = $Sy + $Y; + $Sxx = $Sxx + $X*$X; + } + + $X = $X + $XStep; + } + $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray); + $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx)); + $B = (($Sy)-($M*$Sx))/($n); + + $X1 = $this->GraphAreaX1 + $XMargin; + $Y1 = $M * $X1 + $B; + $X2 = $this->GraphAreaX2 - $XMargin; + $Y2 = $M * $X2 + $B; + + if ( $Y1 < $this->GraphAreaY1 ) { $X1 = $X1 + ($this->GraphAreaY1-$Y1); $Y1 = $this->GraphAreaY1; } + if ( $Y1 > $this->GraphAreaY2 ) { $X1 = $X1 + ($Y1-$this->GraphAreaY2); $Y1 = $this->GraphAreaY2; } + if ( $Y2 < $this->GraphAreaY1 ) { $X2 = $X2 - ($this->GraphAreaY1-$Y2); $Y2 = $this->GraphAreaY1; } + if ( $Y2 > $this->GraphAreaY2 ) { $X2 = $X2 - ($Y2-$this->GraphAreaY2); $Y2 = $this->GraphAreaY2; } + + $this->drawLine($X1,$Y1,$X2,$Y2,$Color); + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID ) + { + $Sxy = $Sxy + $X*$Y; + $Sx = $Sx + $Y; + $Sy = $Sy + $X; + $Sxx = $Sxx + $Y*$Y; + } + + $Y = $Y + $YStep; + } + $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray); + $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx)); + $B = (($Sy)-($M*$Sx))/($n); + + $Y1 = $this->GraphAreaY1 + $XMargin; + $X1 = $M * $Y1 + $B; + $Y2 = $this->GraphAreaY2 - $XMargin; + $X2 = $M * $Y2 + $B; + + if ( $X1 < $this->GraphAreaX1 ) { $Y1 = $Y1 + ($this->GraphAreaX1-$X1); $X1 = $this->GraphAreaX1; } + if ( $X1 > $this->GraphAreaX2 ) { $Y1 = $Y1 + ($X1-$this->GraphAreaX2); $X1 = $this->GraphAreaX2; } + if ( $X2 < $this->GraphAreaX1 ) { $Y2 = $Y2 - ($this->GraphAreaY1-$X2); $X2 = $this->GraphAreaX1; } + if ( $X2 > $this->GraphAreaX2 ) { $Y2 = $Y2 - ($X2-$this->GraphAreaX2); $X2 = $this->GraphAreaX2; } + + $this->drawLine($X1,$Y1,$X2,$Y2,$Color); + } + } + } + } + + /* Write labels */ + function writeLabel($SeriesName,$Indexes,$Format="") + { + $OverrideTitle = isset($Format["OverrideTitle"]) ? $Format["OverrideTitle"] : NULL; + $ForceLabels = isset($Format["ForceLabels"]) ? $Format["ForceLabels"] : NULL; + $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX; + $DrawVerticalLine = isset($Format["DrawVerticalLine"]) ? $Format["DrawVerticalLine"] : FALSE; + $VerticalLineR = isset($Format["VerticalLineR"]) ? $Format["VerticalLineR"] : 0; + $VerticalLineG = isset($Format["VerticalLineG"]) ? $Format["VerticalLineG"] : 0; + $VerticalLineB = isset($Format["VerticalLineB"]) ? $Format["VerticalLineB"] : 0; + $VerticalLineAlpha = isset($Format["VerticalLineAlpha"]) ? $Format["VerticalLineAlpha"] : 40; + $VerticalLineTicks = isset($Format["VerticalLineTicks"]) ? $Format["VerticalLineTicks"] : 2; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( !is_array($Indexes) ) { $Index = $Indexes; $Indexes = ""; $Indexes[] = $Index; } + if ( !is_array($SeriesName) ) { $SerieName = $SeriesName; $SeriesName = ""; $SeriesName[] = $SerieName; } + if ( $ForceLabels != NULL && !is_array($ForceLabels) ) { $ForceLabel = $ForceLabels; $ForceLabels = ""; $ForceLabels[] = $ForceLabel; } + + foreach ($Indexes as $Key => $Index) + { + $Series = ""; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin + $Index * $XStep; + + if ( $DrawVerticalLine ) { $this->drawLine($X,$this->GraphAreaY1+$Data["YMargin"],$X,$this->GraphAreaY2-$Data["YMargin"],array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); } + + $MinY = $this->GraphAreaY2; + foreach ($SeriesName as $iKey => $SerieName) + { + if ( isset($Data["Series"][$SerieName]["Data"][$Index]) ) + { + $AxisID = $Data["Series"][$SerieName]["Axis"]; + $XAxisMode = $Data["XAxisDisplay"]; + $XAxisFormat = $Data["XAxisFormat"]; + $XAxisUnit = $Data["XAxisUnit"]; + $AxisMode = $Data["Axis"][$AxisID]["Display"]; + $AxisFormat = $Data["Axis"][$AxisID]["Format"]; + $AxisUnit = $Data["Axis"][$AxisID]["Unit"]; + + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $XLabel = $this->scaleFormat($Data["Series"][$Data["Abscissa"]]["Data"][$Index],$XAxisMode,$XAxisFormat,$XAxisUnit); + else + $XLabel = ""; + + if ( $OverrideTitle != NULL) + $Description = $OverrideTitle; + elseif ( count($SeriesName) == 1 ) + { + $Description = $Data["Series"][$SerieName]["Description"]." - ".$XLabel; + } + elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $XLabel; + + $Serie = ""; + $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"]; + $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"]; + $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"]; + $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"]; + + if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) ) + $SerieOffset = $Data["Series"][$SerieName]["XOffset"]; + else + $SerieOffset = 0; + + $Value = $Data["Series"][$SerieName]["Data"][$Index]; + if ( $Value == VOID ) { $Value = "NaN"; } + + if ( $ForceLabels != NULL ) + $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set"; + else + $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit); + + if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED ) + { + if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; } + + $Value = 0; $Done = FALSE; + foreach($Data["Series"] as $Name => $SerieLookup) + { + if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done ) + { + if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID ) + { + if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; } + if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" ) { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; } + if ($Name == $SerieName ) { $Done = TRUE; } + } + } + } + } + + $X = floor($this->GraphAreaX1 + $XMargin + $Index * $XStep + $SerieOffset); + $Y = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID))); + + if ($Y < $MinY) { $MinY = $Y; } + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $Series[] = array("Format"=>$Serie,"Caption"=>$Caption); + } + } + $this->drawLabelBox($X,$MinY-3,$Description,$Series,$Format); + + } + else + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin + $Index * $XStep; + + if ( $DrawVerticalLine ) { $this->drawLine($this->GraphAreaX1+$Data["YMargin"],$Y,$this->GraphAreaX2-$Data["YMargin"],$Y,array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); } + + $MinX = $this->GraphAreaX2; + foreach ($SeriesName as $Key => $SerieName) + { + if ( isset($Data["Series"][$SerieName]["Data"][$Index]) ) + { + $AxisID = $Data["Series"][$SerieName]["Axis"]; + $XAxisMode = $Data["XAxisDisplay"]; + $XAxisFormat = $Data["XAxisFormat"]; + $XAxisUnit = $Data["XAxisUnit"]; + $AxisMode = $Data["Axis"][$AxisID]["Display"]; + $AxisFormat = $Data["Axis"][$AxisID]["Format"]; + $AxisUnit = $Data["Axis"][$AxisID]["Unit"]; + + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $XLabel = $this->scaleFormat($Data["Series"][$Data["Abscissa"]]["Data"][$Index],$XAxisMode,$XAxisFormat,$XAxisUnit); + else + $XLabel = ""; + + if ( $OverrideTitle != NULL) + $Description = $OverrideTitle; + elseif ( count($SeriesName) == 1 ) + { + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $Data["Series"][$SerieName]["Description"]." - ".$XLabel; + } + elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $XLabel; + + $Serie = ""; + if ( isset($Data["Extended"]["Palette"][$Index] ) ) + { + $Serie["R"] = $Data["Extended"]["Palette"][$Index]["R"]; + $Serie["G"] = $Data["Extended"]["Palette"][$Index]["G"]; + $Serie["B"] = $Data["Extended"]["Palette"][$Index]["B"]; + $Serie["Alpha"] = $Data["Extended"]["Palette"][$Index]["Alpha"]; + } + else + { + $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"]; + $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"]; + $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"]; + $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"]; + } + + if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) ) + $SerieOffset = $Data["Series"][$SerieName]["XOffset"]; + else + $SerieOffset = 0; + + $Value = $Data["Series"][$SerieName]["Data"][$Index]; + if ( $ForceLabels != NULL ) + $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set"; + else + $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit); + if ( $Value == VOID ) { $Value = "NaN"; } + + if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED ) + { + if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; } + + $Value = 0; $Done = FALSE; + foreach($Data["Series"] as $Name => $SerieLookup) + { + if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done ) + { + if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID ) + { + if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; } + if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" ) { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; } + if ($Name == $SerieName ) { $Done = TRUE; } + } + } + } + } + + $X = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID))); + $Y = floor($this->GraphAreaY1 + $XMargin + $Index * $XStep + $SerieOffset); + + if ($X < $MinX) { $MinX = $X; } + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $Series[] = array("Format"=>$Serie,"Caption"=>$Caption); + } + } + $this->drawLabelBox($MinX,$Y-3,$Description,$Series,$Format); + + } + } + } + + /* Draw a label box */ + function drawLabelBox($X,$Y,$Title,$Captions,$Format="") + { + $NoTitle = isset($Format["NoTitle"]) ? $Format["NoTitle"] : NULL; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 50; + $DrawSerieColor = isset($Format["DrawSerieColor"]) ? $Format["DrawSerieColor"] : TRUE; + $SerieR = isset($Format["SerieR"]) ? $Format["SerieR"] : NULL; + $SerieG = isset($Format["SerieG"]) ? $Format["SerieG"] : NULL; + $SerieB = isset($Format["SerieB"]) ? $Format["SerieB"] : NULL; + $SerieAlpha = isset($Format["SerieAlpha"]) ? $Format["SerieAlpha"] : NULL; + $SerieBoxSize = isset($Format["SerieBoxSize"]) ? $Format["SerieBoxSize"] : 6; + $SerieBoxSpacing = isset($Format["SerieBoxSpacing"]) ? $Format["SerieBoxSpacing"] : 4; + $VerticalMargin = isset($Format["VerticalMargin"]) ? $Format["VerticalMargin"] : 10; + $HorizontalMargin = isset($Format["HorizontalMargin"]) ? $Format["HorizontalMargin"] : 8; + $R = isset($Format["R"]) ? $Format["R"] : $this->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->FontColorB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $TitleMode = isset($Format["TitleMode"]) ? $Format["TitleMode"] : LABEL_TITLE_NOBACKGROUND; + $TitleR = isset($Format["TitleR"]) ? $Format["TitleR"] : $R; + $TitleG = isset($Format["TitleG"]) ? $Format["TitleG"] : $G; + $TitleB = isset($Format["TitleB"]) ? $Format["TitleB"] : $B; + $TitleAlpha = isset($Format["TitleAlpha"]) ? $Format["TitleAlpha"] : 100; + $TitleBackgroundR = isset($Format["TitleBackgroundR"]) ? $Format["TitleBackgroundR"] : 0; + $TitleBackgroundG = isset($Format["TitleBackgroundG"]) ? $Format["TitleBackgroundG"] : 0; + $TitleBackgroundB = isset($Format["TitleBackgroundB"]) ? $Format["TitleBackgroundB"] : 0; + $TitleBackgroundAlpha = isset($Format["TitleBackgroundAlpha"]) ? $Format["TitleBackgroundAlpha"] : 100; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 220; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 220; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 220; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 100; + + if ( !$DrawSerieColor ) { $SerieBoxSize = 0; $SerieBoxSpacing = 0; } + + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Title); + $TitleWidth = ($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2; + $TitleHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]); + + if ( $NoTitle ) { $TitleWidth = 0; $TitleHeight = 0; } + + $CaptionWidth = 0; $CaptionHeight = -$HorizontalMargin; + foreach($Captions as $Key =>$Caption) + { + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Caption["Caption"]); + $CaptionWidth = max($CaptionWidth,($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2); + $CaptionHeight = $CaptionHeight + max(($TxtPos[0]["Y"] - $TxtPos[2]["Y"]),($SerieBoxSize+2)) + $HorizontalMargin; + } + + if ( $CaptionHeight <= 5 ) { $CaptionHeight = $CaptionHeight + $HorizontalMargin/2; } + + if ( $DrawSerieColor ) { $CaptionWidth = $CaptionWidth + $SerieBoxSize + $SerieBoxSpacing; } + + $BoxWidth = max($BoxWidth,$TitleWidth,$CaptionWidth); + + $XMin = $X - 5 - floor(($BoxWidth-10) / 2); + $XMax = $X + 5 + floor(($BoxWidth-10) / 2); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow == TRUE ) + { + $this->Shadow = FALSE; + + $Poly = ""; + $Poly[] = $X+$this->ShadowX; $Poly[] = $Y+$this->ShadowX; + $Poly[] = $X+5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + + if ( $NoTitle ) + { + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX; + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX; + } + else + { + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX; + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX; + } + + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $Poly[] = $X-5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $this->drawPolygon($Poly,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + /* Draw the background */ + $GradientSettings = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$BoxAlpha); + if ( $NoTitle ) + $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings); + else + $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings); + $Poly = ""; $Poly[] = $X; $Poly[] = $Y; $Poly[] = $X-5; $Poly[] = $Y-5; $Poly[] = $X+5; $Poly[] = $Y-5; + $this->drawPolygon($Poly,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB,"Alpha"=>$BoxAlpha,"NoBorder"=>TRUE)); + + /* Outer border */ + $OuterBorderColor = $this->allocateColor($this->Picture,100,100,100,$BoxAlpha); + imageline($this->Picture,$XMin,$Y-5,$X-5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X,$Y,$X-5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X,$Y,$X+5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X+5,$Y-5,$XMax,$Y-5,$OuterBorderColor); + if ( $NoTitle ) + { + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$OuterBorderColor); + } + else + { + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$OuterBorderColor); + } + + /* Inner border */ + $InnerBorderColor = $this->allocateColor($this->Picture,255,255,255,$BoxAlpha); + imageline($this->Picture,$XMin+1,$Y-6,$X-5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X,$Y-1,$X-5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X,$Y-1,$X+5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X+5,$Y-6,$XMax-1,$Y-6,$InnerBorderColor); + if ( $NoTitle ) + { + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin+1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$InnerBorderColor); + } + else + { + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin+1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$InnerBorderColor); + } + + /* Draw the separator line */ + if ( $TitleMode == LABEL_TITLE_NOBACKGROUND && !$NoTitle ) + { + $YPos = $Y-7-$CaptionHeight-$HorizontalMargin-$HorizontalMargin/2; + $XMargin = $VerticalMargin / 2; + $this->drawLine($XMin+$XMargin,$YPos+1,$XMax-$XMargin,$YPos+1,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB,"Alpha"=>$BoxAlpha)); + $this->drawLine($XMin+$XMargin,$YPos,$XMax-$XMargin,$YPos,array("R"=>$GradientStartR,"G"=>$GradientStartG,"B"=>$GradientStartB,"Alpha"=>$BoxAlpha)); + } + elseif ( $TitleMode == LABEL_TITLE_BACKGROUND ) + { + $this->drawFilledRectangle($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2,array("R"=>$TitleBackgroundR,"G"=>$TitleBackgroundG,"B"=>$TitleBackgroundB,"Alpha"=>$BoxAlpha)); + imageline($this->Picture,$XMin+1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$XMax-1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$InnerBorderColor); + } + + /* Write the description */ + if ( !$NoTitle ) + $this->drawText($XMin+$VerticalMargin,$Y-7-$CaptionHeight-$HorizontalMargin*2,$Title,array("Align"=>TEXT_ALIGN_BOTTOMLEFT,"R"=>$TitleR,"G"=>$TitleG,"B"=>$TitleB)); + + /* Write the value */ + $YPos = $Y-5-$HorizontalMargin; $XPos = $XMin+$VerticalMargin+$SerieBoxSize+$SerieBoxSpacing; + foreach($Captions as $Key => $Caption) + { + $CaptionTxt = $Caption["Caption"]; + $TxtPos = $this->getTextBox($XPos,$YPos,$FontName,$FontSize,0,$CaptionTxt); + $CaptionHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]); + + /* Write the serie color if needed */ + if ( $DrawSerieColor ) + { + $BoxSettings = array("R"=>$Caption["Format"]["R"],"G"=>$Caption["Format"]["G"],"B"=>$Caption["Format"]["B"],"Alpha"=>$Caption["Format"]["Alpha"],"BorderR"=>0,"BorderG"=>0,"BorderB"=>0); + $this->drawFilledRectangle($XMin+$VerticalMargin,$YPos-$SerieBoxSize,$XMin+$VerticalMargin+$SerieBoxSize,$YPos,$BoxSettings); + } + + $this->drawText($XPos,$YPos,$CaptionTxt,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); + + $YPos = $YPos - $CaptionHeight - $HorizontalMargin; + } + + $this->Shadow = $RestoreShadow; + } + + /* Draw a basic shape */ + function drawShape($X,$Y,$Shape,$PlotSize,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha) + { + if ( $Shape == SERIE_SHAPE_FILLEDCIRCLE ) + { + if ( $PlotBorder ) { $this->drawFilledCircle($X,$Y,$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + $this->drawFilledCircle($X,$Y,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDSQUARE ) + { + if ( $PlotBorder ) { $this->drawFilledRectangle($X-$PlotSize-$BorderSize,$Y-$PlotSize-$BorderSize,$X+$PlotSize+$BorderSize,$Y+$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + $this->drawFilledRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDTRIANGLE ) + { + if ( $PlotBorder ) + { + $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize; + $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); + } + + $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X-$PlotSize; $Pos[]=$Y+$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_TRIANGLE ) + { + $this->drawLine($X,$Y-$PlotSize,$X-$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + $this->drawLine($X-$PlotSize,$Y+$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + $this->drawLine($X+$PlotSize,$Y+$PlotSize,$X,$Y-$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_SQUARE ) + $this->drawRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + elseif ( $Shape == SERIE_SHAPE_CIRCLE ) + $this->drawCircle($X,$Y,$PlotSize,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + elseif ( $Shape == SERIE_SHAPE_DIAMOND ) + { + $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("NoFill"=>TRUE,"BorderR"=>$R,"BorderG"=>$G,"BorderB"=>$B,"BorderAlpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDDIAMOND ) + { + if ( $PlotBorder ) + { + $Pos = ""; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize+$BorderSize; + $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); + } + + $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + } + + function drawPolygonChart($Points,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $NoFill = isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha / 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + $AllIntegers = TRUE; + for($i=0;$i<=count($Points)-2;$i=$i+2) + { if ( $this->getFirstDecimal($Points[$i+1]) != 0 ) { $AllIntegers = FALSE; } } + + /* Convert polygon to segments */ + $Segments = ""; + for($i=2;$i<=count($Points)-2;$i=$i+2) + { $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[$i],"Y2"=>$Points[$i+1]); } + $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[0],"Y2"=>$Points[1]); + + /* Simplify straight lines */ + $Result = ""; $inHorizon = FALSE; $LastX = VOID; + foreach($Segments as $Key => $Pos) + { + if ( $Pos["Y1"] != $Pos["Y2"] ) + { + if ( $inHorizon ) { $inHorizon = FALSE; $Result[] = array("X1"=>$LastX,"Y1"=>$Pos["Y1"],"X2"=>$Pos["X1"],"Y2"=>$Pos["Y1"]); } + + $Result[] = array("X1"=>$Pos["X1"],"Y1"=>$Pos["Y1"],"X2"=>$Pos["X2"],"Y2"=>$Pos["Y2"]); + } + else { if ( !$inHorizon ) { $inHorizon = TRUE; $LastX = $Pos["X1"];} } + } + $Segments = $Result; + + /* Do we have something to draw */ + if ( $Segments == "" ) { return(0); } + + /* For segments debugging purpose */ + //foreach($Segments as $Key => $Pos) + // echo $Pos["X1"].",".$Pos["Y1"].",".$Pos["X2"].",".$Pos["Y2"]."\r\n"; + + /* Find out the min & max Y boundaries */ + $MinY = OUT_OF_SIGHT; $MaxY = OUT_OF_SIGHT; + foreach($Segments as $Key => $Coords) + { + if ( $MinY == OUT_OF_SIGHT || $MinY > min($Coords["Y1"],$Coords["Y2"]) ) { $MinY = min($Coords["Y1"],$Coords["Y2"]); } + if ( $MaxY == OUT_OF_SIGHT || $MaxY < max($Coords["Y1"],$Coords["Y2"]) ) { $MaxY = max($Coords["Y1"],$Coords["Y2"]); } + } + + if ( $AllIntegers ) { $YStep = 1; } else { $YStep = .5; } + + $MinY = floor($MinY); $MaxY = floor($MaxY); + + /* Scan each Y lines */ + $DefaultColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + $DebugLine = 0; $DebugColor = $this->allocateColor($this->Picture,255,0,0,100); + + $MinY = floor($MinY); $MaxY = floor($MaxY); $YStep = 1; + + if ( !$NoFill ) + { + //if ( $DebugLine ) { $MinY = $DebugLine; $MaxY = $DebugLine; } + for($Y=$MinY;$Y<=$MaxY;$Y=$Y+$YStep) + { + $Intersections = ""; $LastSlope = NULL; $RestoreLast = "-"; + foreach($Segments as $Key => $Coords) + { + $X1 = $Coords["X1"]; $X2 = $Coords["X2"]; $Y1 = $Coords["Y1"]; $Y2 = $Coords["Y2"]; + + if ( min($Y1,$Y2) <= $Y && max($Y1,$Y2) >= $Y ) + { + if ( $Y1 == $Y2 ) + { $X = $X1; } + else + { $X = $X1 + ( ($Y-$Y1)*$X2 - ($Y-$Y1)*$X1 ) / ($Y2-$Y1); } + + $X = floor($X); + + if ( $X2 == $X1 ) + { $Slope = "!"; } + else + { + $SlopeC = ($Y2 - $Y1) / ($X2 - $X1); + if( $SlopeC == 0 ) + { $Slope = "="; } + elseif( $SlopeC > 0 ) + { $Slope = "+"; } + elseif ( $SlopeC < 0 ) + { $Slope = "-"; } + } + + if ( !is_array($Intersections) ) + { $Intersections[] = $X; } + elseif( !in_array($X,$Intersections) ) + { $Intersections[] = $X; } + elseif( in_array($X,$Intersections) ) + { + if ($Y == $DebugLine) { echo $Slope."/".$LastSlope."(".$X.") "; } + + if ( $Slope == "=" && $LastSlope == "-" ) { $Intersections[] = $X; } + if ( $Slope != $LastSlope && $LastSlope != "!" && $LastSlope != "=" ) { $Intersections[] = $X; } + if ( $Slope != $LastSlope && $LastSlope == "!" && $Slope == "+" ) { $Intersections[] = $X; } + } + + if ( is_array($Intersections) && in_array($X,$Intersections) && $LastSlope == "=" && ($Slope == "-" )) { $Intersections[] = $X; } + + $LastSlope = $Slope; + } + } + if ( $RestoreLast != "-" ) { $Intersections[] = $RestoreLast; echo "@".$Y."\r\n"; } + + if ( is_array($Intersections) ) + { + sort($Intersections); + + if ($Y == $DebugLine) { print_r($Intersections); } + + /* Remove NULL plots */ + $Result = ""; + for($i=0;$i<=count($Intersections)-1;$i=$i+2) + { + if ( isset($Intersections[$i+1]) ) + { if ( $Intersections[$i] != $Intersections[$i+1] ) { $Result[] = $Intersections[$i]; $Result[] = $Intersections[$i+1]; } } + } + + if ( is_array($Result) ) + { + $Intersections = $Result; + + $LastX = OUT_OF_SIGHT; + foreach($Intersections as $Key => $X) + { + if ( $LastX == OUT_OF_SIGHT ) + $LastX = $X; + elseif ( $LastX != OUT_OF_SIGHT ) + { + if ( $this->getFirstDecimal($LastX) > 1 ) { $LastX++; } + + $Color = $DefaultColor; + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Parameters) + { + if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"]) + { + if ( isset($Parameters["R"]) ) { $R = $Parameters["R"]; } else { $R = 0; } + if ( isset($Parameters["G"]) ) { $G = $Parameters["G"]; } else { $G = 0; } + if ( isset($Parameters["B"]) ) { $B = $Parameters["B"]; } else { $B = 0; } + if ( isset($Parameters["Alpha"]) ) { $Alpha = $Parameters["Alpha"]; } else { $Alpha = 100; } + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + } + } + } + + imageline($this->Picture,$LastX,$Y,$X,$Y,$Color); + + if ( $Y == $DebugLine) { imageline($this->Picture,$LastX,$Y,$X,$Y,$DebugColor); } + + $LastX = OUT_OF_SIGHT; + } + } + } + } + } + } + + /* Draw the polygon border, if required */ + if ( !$NoBorder) + { + foreach($Segments as $Key => $Coords) + $this->drawLine($Coords["X1"],$Coords["Y1"],$Coords["X2"],$Coords["Y2"],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Threshold"=>$Threshold)); + } + + $this->Shadow = $RestoreShadow; + } + + /* Return the abscissa margin */ + function getAbscissaMargin($Data) + { + foreach($Data["Axis"] as $AxisID => $Values) { if ( $Values["Identity"] == AXIS_X ) { return($Values["Margin"]); } } + return(0); + } + + } +?> \ No newline at end of file diff --git a/system/library/games/graph/pImage.php b/system/library/games/graph/pImage.php new file mode 100644 index 0000000..99b6cae --- /dev/null +++ b/system/library/games/graph/pImage.php @@ -0,0 +1,461 @@ +TransparentBackground = $TransparentBackground; + + if ( $DataSet != NULL ) { $this->DataSet = $DataSet; } + + $this->XSize = $XSize; + $this->YSize = $YSize; + $this->Picture = imagecreatetruecolor($XSize,$YSize); + + if ( $this->TransparentBackground ) + { + imagealphablending($this->Picture,FALSE); + imagefilledrectangle($this->Picture, 0,0,$XSize, $YSize, imagecolorallocatealpha($this->Picture, 255, 255, 255, 127)); + imagealphablending($this->Picture,TRUE); + imagesavealpha($this->Picture,true); + } + else + { + $C_White = $this->AllocateColor($this->Picture,255,255,255); + imagefilledrectangle($this->Picture,0,0,$XSize,$YSize,$C_White); + } + } + + /* Enable / Disable and set shadow properties */ + function setShadow($Enabled=TRUE,$Format="") + { + $X = isset($Format["X"]) ? $Format["X"] : 2; + $Y = isset($Format["Y"]) ? $Format["Y"] : 2; + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 10; + + $this->Shadow = $Enabled; + $this->ShadowX = $X; + $this->ShadowY = $Y; + $this->ShadowR = $R; + $this->ShadowG = $G; + $this->ShadowB = $B; + $this->Shadowa = $Alpha; + } + + /* Set the graph area position */ + function setGraphArea($X1,$Y1,$X2,$Y2) + { + if ( $X2 < $X1 || $X1 == $X2 || $Y2 < $Y1 || $Y1 == $Y2 ) { return(-1); } + + $this->GraphAreaX1 = $X1; $this->DataSet->Data["GraphArea"]["X1"] = $X1; + $this->GraphAreaY1 = $Y1; $this->DataSet->Data["GraphArea"]["Y1"] = $Y1; + $this->GraphAreaX2 = $X2; $this->DataSet->Data["GraphArea"]["X2"] = $X2; + $this->GraphAreaY2 = $Y2; $this->DataSet->Data["GraphArea"]["Y2"] = $Y2; + } + + /* Return the width of the picture */ + function getWidth() + { return($this->XSize); } + + /* Return the heigth of the picture */ + function getHeight() + { return($this->YSize); } + + /* Render the picture to a file */ + function render($FileName) + { + if ( $this->TransparentBackground ) { imagealphablending($this->Picture,false); imagesavealpha($this->Picture,true); } + imagepng($this->Picture,$FileName); + } + + /* Render the picture to a web browser stream */ + function stroke($BrowserExpire=FALSE) + { + if ( $this->TransparentBackground ) { imagealphablending($this->Picture,false); imagesavealpha($this->Picture,true); } + + if ( $BrowserExpire ) + { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Cache-Control: no-cache"); + header("Pragma: no-cache"); + } + + header('Content-type: image/png'); + imagepng($this->Picture); + } + + /* Automatic output method based on the calling interface */ + function autoOutput($FileName="output.png") + { + if (php_sapi_name() == "cli") + $this->Render($FileName); + else + $this->Stroke(); + } + + /* Return the length between two points */ + function getLength($X1,$Y1,$X2,$Y2) + { return(sqrt(pow(max($X1,$X2)-min($X1,$X2),2)+pow(max($Y1,$Y2)-min($Y1,$Y2),2))); } + + /* Return the orientation of a line */ + function getAngle($X1,$Y1,$X2,$Y2) + { + $Opposite = $Y2 - $Y1; $Adjacent = $X2 - $X1;$Angle = rad2deg(atan2($Opposite,$Adjacent)); + if ($Angle > 0) { return($Angle); } else { return(360-abs($Angle)); } + } + + /* Return the surrounding box of text area */ + function getTextBox_deprecated($X,$Y,$FontName,$FontSize,$Angle,$Text) + { + $Size = imagettfbbox($FontSize,$Angle,$FontName,$Text); + $Width = $this->getLength($Size[0],$Size[1],$Size[2],$Size[3])+1; + $Height = $this->getLength($Size[2],$Size[3],$Size[4],$Size[5])+1; + + $RealPos[0]["X"] = $X; $RealPos[0]["Y"] = $Y; + $RealPos[1]["X"] = cos((360-$Angle)*PI/180)*$Width + $RealPos[0]["X"]; $RealPos[1]["Y"] = sin((360-$Angle)*PI/180)*$Width + $RealPos[0]["Y"]; + $RealPos[2]["X"] = cos((270-$Angle)*PI/180)*$Height + $RealPos[1]["X"]; $RealPos[2]["Y"] = sin((270-$Angle)*PI/180)*$Height + $RealPos[1]["Y"]; + $RealPos[3]["X"] = cos((180-$Angle)*PI/180)*$Width + $RealPos[2]["X"]; $RealPos[3]["Y"] = sin((180-$Angle)*PI/180)*$Width + $RealPos[2]["Y"]; + + $RealPos[TEXT_ALIGN_BOTTOMLEFT]["X"] = $RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMLEFT]["Y"] = $RealPos[0]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["X"] = $RealPos[1]["X"]; $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["Y"] = $RealPos[1]["Y"]; + + return($RealPos); + } + + /* Return the surrounding box of text area */ + function getTextBox($X,$Y,$FontName,$FontSize,$Angle,$Text) + { + $coords = imagettfbbox($FontSize, 0, $FontName, $Text); + + $a = deg2rad($Angle); $ca = cos($a); $sa = sin($a); $RealPos = array(); + for($i = 0; $i < 7; $i += 2) + { + $RealPos[$i/2]["X"] = $X + round($coords[$i] * $ca + $coords[$i+1] * $sa); + $RealPos[$i/2]["Y"] = $Y + round($coords[$i+1] * $ca - $coords[$i] * $sa); + } + + $RealPos[TEXT_ALIGN_BOTTOMLEFT]["X"] = $RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMLEFT]["Y"] = $RealPos[0]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["X"] = $RealPos[1]["X"]; $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["Y"] = $RealPos[1]["Y"]; + $RealPos[TEXT_ALIGN_TOPLEFT]["X"] = $RealPos[3]["X"]; $RealPos[TEXT_ALIGN_TOPLEFT]["Y"] = $RealPos[3]["Y"]; + $RealPos[TEXT_ALIGN_TOPRIGHT]["X"] = $RealPos[2]["X"]; $RealPos[TEXT_ALIGN_TOPRIGHT]["Y"] = $RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["X"] = ($RealPos[1]["X"]-$RealPos[0]["X"])/2+$RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["Y"] = ($RealPos[0]["Y"]-$RealPos[1]["Y"])/2+$RealPos[1]["Y"]; + $RealPos[TEXT_ALIGN_TOPMIDDLE]["X"] = ($RealPos[2]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_TOPMIDDLE]["Y"] = ($RealPos[3]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLELEFT]["X"] = ($RealPos[0]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_MIDDLELEFT]["Y"] = ($RealPos[0]["Y"]-$RealPos[3]["Y"])/2+$RealPos[3]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLERIGHT]["X"] = ($RealPos[1]["X"]-$RealPos[2]["X"])/2+$RealPos[2]["X"]; $RealPos[TEXT_ALIGN_MIDDLERIGHT]["Y"] = ($RealPos[1]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["X"] = ($RealPos[1]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["Y"] = ($RealPos[0]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + + return($RealPos); + } + + /* Set current font properties */ + function setFontProperties($Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : -1; + $G = isset($Format["G"]) ? $Format["G"] : -1; + $B = isset($Format["B"]) ? $Format["B"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : NULL; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : NULL; + + if ( $R != -1) { $this->FontColorR = $R; } + if ( $G != -1) { $this->FontColorG = $G; } + if ( $B != -1) { $this->FontColorB = $B; } + if ( $Alpha != NULL) { $this->FontColorA = $Alpha; } + + if ( $FontName != NULL ) + $this->FontName = $FontName; + + if ( $FontSize != NULL ) + $this->FontSize = $FontSize; + } + + /* Returns the 1st decimal values (used to correct AA bugs) */ + function getFirstDecimal($Value) + { + $Values = preg_split("/\./",$Value); + if ( isset($Values[1]) ) { return(substr($Values[1],0,1)); } else { return(0); } + } + + /* Attach a dataset to your pChart Object */ + function setDataSet(&$DataSet) + { $this->DataSet = $DataSet; } + + /* Print attached dataset contents to STDOUT */ + function printDataSet() + { print_r($this->DataSet); } + + /* Initialise the image map methods */ + function initialiseImageMap($Name="pChart",$StorageMode=IMAGE_MAP_STORAGE_SESSION,$UniqueID="imageMap",$StorageFolder="tmp") + { + $this->ImageMapIndex = $Name; + $this->ImageMapStorageMode = $StorageMode; + + if ($StorageMode == IMAGE_MAP_STORAGE_SESSION) + { + if(!isset($_SESSION)) { session_start(); } + $_SESSION[$this->ImageMapIndex] = NULL; + } + elseif($StorageMode == IMAGE_MAP_STORAGE_FILE) + { + $this->ImageMapFileName = $UniqueID; + $this->ImageMapStorageFolder = $StorageFolder; + + if (file_exists($StorageFolder."/".$UniqueID.".map")) { unlink($StorageFolder."/".$UniqueID.".map"); } + } + } + + /* Add a zone to the image map */ + function addToImageMap($Type,$Plots,$Color=NULL,$Title=NULL,$Message=NULL,$HTMLEncode=FALSE) + { + if ( $this->ImageMapStorageMode == NULL ) { $this->initialiseImageMap(); } + + /* Encode the characters in the imagemap in HTML standards */ + $Title = str_replace("€","\u20AC",$Title); + $Title = htmlentities($Title,ENT_QUOTES,"ISO-8859-15"); + if ( $HTMLEncode ) + { + $Message = htmlentities($Message,ENT_QUOTES,"ISO-8859-15"); + $Message = str_replace("<","<",$Message); + $Message = str_replace(">",">",$Message); + } + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { $this->initialiseImageMap(); } + $_SESSION[$this->ImageMapIndex][] = array($Type,$Plots,$Color,$Title,$Message); + } + elseif($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) + { + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'a'); + fwrite($Handle, $Type.IMAGE_MAP_DELIMITER.$Plots.IMAGE_MAP_DELIMITER.$Color.IMAGE_MAP_DELIMITER.$Title.IMAGE_MAP_DELIMITER.$Message."\r\n"); + fclose($Handle); + } + } + + /* Remove VOID values from an imagemap custom values array */ + function removeVOIDFromArray($SerieName, $Values) + { + if ( !isset($this->DataSet->Data["Series"][$SerieName]) ) { return(-1); } + + $Result = ""; + foreach($this->DataSet->Data["Series"][$SerieName]["Data"] as $Key => $Value) + { if ( $Value != VOID && isset($Values[$Key]) ) { $Result[] = $Values[$Key]; } } + return($Result); + } + + /* Replace the title of one image map serie */ + function replaceImageMapTitle($OldTitle, $NewTitle) + { + if ( $this->ImageMapStorageMode == NULL ) { return(-1); } + + if ( is_array($NewTitle) ) { $NewTitle = $this->removeVOIDFromArray($OldTitle, $NewTitle); } + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { return(-1); } + if ( is_array($NewTitle) ) + { $ID = 0; foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $OldTitle && isset($NewTitle[$ID])) { $_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle[$ID]; $ID++; } } } + else + { foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $OldTitle ) { $_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle; } } } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + $TempArray = ""; + $Handle = @fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", "r"); + if ($Handle) + { + while (($Buffer = fgets($Handle, 4096)) !== false) + { + $Fields = preg_split("/".IMAGE_MAP_DELIMITER."/",str_replace(array(chr(10),chr(13)),"",$Buffer)); + $TempArray[] = array($Fields[0],$Fields[1],$Fields[2],$Fields[3],$Fields[4]); + } + fclose($Handle); + + if ( is_array($NewTitle) ) + { $ID = 0; foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $OldTitle && isset($NewTitle[$ID]) ) { $TempArray[$Key][3] = $NewTitle[$ID]; $ID++; } } } + else + { foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $OldTitle ) { $TempArray[$Key][3] = $NewTitle; } } } + + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'w'); + foreach($TempArray as $Key => $Settings) + { fwrite($Handle, $Settings[0].IMAGE_MAP_DELIMITER.$Settings[1].IMAGE_MAP_DELIMITER.$Settings[2].IMAGE_MAP_DELIMITER.$Settings[3].IMAGE_MAP_DELIMITER.$Settings[4]."\r\n"); } + fclose($Handle); + } + } + } + + /* Replace the values of the image map contents */ + function replaceImageMapValues($Title, $Values) + { + if ( $this->ImageMapStorageMode == NULL ) { return(-1); } + + $Values = $this->removeVOIDFromArray($Title, $Values); + $ID = 0; + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { return(-1); } + foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $Title ) { if ( isset($Values[$ID]) ) { $_SESSION[$this->ImageMapIndex][$Key][4] = $Values[$ID]; } $ID++; } } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + $TempArray = ""; + $Handle = @fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", "r"); + if ($Handle) + { + while (($Buffer = fgets($Handle, 4096)) !== false) + { + $Fields = preg_split("/".IMAGE_MAP_DELIMITER."/",str_replace(array(chr(10),chr(13)),"",$Buffer)); + $TempArray[] = array($Fields[0],$Fields[1],$Fields[2],$Fields[3],$Fields[4]); + } + fclose($Handle); + + foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $Title ) { if ( isset($Values[$ID]) ) { $TempArray[$Key][4] = $Values[$ID]; } $ID++; } } + + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'w'); + foreach($TempArray as $Key => $Settings) + { fwrite($Handle, $Settings[0].IMAGE_MAP_DELIMITER.$Settings[1].IMAGE_MAP_DELIMITER.$Settings[2].IMAGE_MAP_DELIMITER.$Settings[3].IMAGE_MAP_DELIMITER.$Settings[4]."\r\n"); } + fclose($Handle); + } + } + } + + /* Dump the image map */ + function dumpImageMap($Name="pChart",$StorageMode=IMAGE_MAP_STORAGE_SESSION,$UniqueID="imageMap",$StorageFolder="tmp") + { + $this->ImageMapIndex = $Name; + $this->ImageMapStorageMode = $StorageMode; + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { session_start(); } + if ( $_SESSION[$Name] != NULL ) + { + foreach($_SESSION[$Name] as $Key => $Params) + { echo $Params[0].IMAGE_MAP_DELIMITER.$Params[1].IMAGE_MAP_DELIMITER.$Params[2].IMAGE_MAP_DELIMITER.$Params[3].IMAGE_MAP_DELIMITER.$Params[4]."\r\n"; } + } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + if (file_exists($StorageFolder."/".$UniqueID.".map")) + { + $Handle = @fopen($StorageFolder."/".$UniqueID.".map", "r"); + if ($Handle) { while (($Buffer = fgets($Handle, 4096)) !== false) { echo $Buffer; } } + fclose($Handle); + + if ( $this->ImageMapAutoDelete ) { unlink($StorageFolder."/".$UniqueID.".map"); } + } + } + + /* When the image map is returned to the client, the script ends */ + exit(); + } + + /* Return the HTML converted color from the RGB composite values */ + function toHTMLColor($R,$G,$B) + { + $R=intval($R); $G=intval($G); $B=intval($B); + $R=dechex($R<0?0:($R>255?255:$R)); $G=dechex($G<0?0:($G>255?255:$G));$B=dechex($B<0?0:($B>255?255:$B)); + $Color="#".(strlen($R) < 2?'0':'').$R; $Color.=(strlen($G) < 2?'0':'').$G; $Color.= (strlen($B) < 2?'0':'').$B; + return($Color); + } + + /* Reverse an array of points */ + function reversePlots($Plots) + { + $Result = ""; + for($i=count($Plots)-2;$i>=0;$i=$i-2) { $Result[] = $Plots[$i]; $Result[] = $Plots[$i+1]; } + return($Result); + } + + /* Mirror Effect */ + function drawAreaMirror($X,$Y,$Width,$Height,$Format="") + { + $StartAlpha = isset($Format["StartAlpha"]) ? $Format["StartAlpha"] : 80; + $EndAlpha = isset($Format["EndAlpha"]) ? $Format["EndAlpha"] : 0; + + $AlphaStep = ($StartAlpha-$EndAlpha)/$Height; + + $Picture = imagecreatetruecolor($this->XSize,$this->YSize); + imagecopy($Picture,$this->Picture,0,0,0,0,$this->XSize,$this->YSize); + + for($i=1;$i<=$Height;$i++) + { + if ( $Y+($i-1) < $this->YSize && $Y-$i > 0 ) { imagecopymerge($Picture,$this->Picture,$X,$Y+($i-1),$X,$Y-$i,$Width,1,$StartAlpha-$AlphaStep*$i); } + } + + imagecopy($this->Picture,$Picture,0,0,0,0,$this->XSize,$this->YSize); + } + } +?> \ No newline at end of file diff --git a/system/library/games/mc/action.php b/system/library/games/mc/action.php new file mode 100644 index 0000000..003c3ac --- /dev/null +++ b/system/library/games/mc/action.php @@ -0,0 +1,110 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `ram`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe;'); + + // Временный файл + $temp = sys::temp(action::config($ip, $port, $server['slots_start'], $ssh->get('cat '.$tarif['install'].'/'.$server['uid'].'/server.properties'))); + + // Обновление файла server.cfg + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.properties', 0644); + + unlink($temp); + + // Параметры запуска + $bash = 'java -Xmx'.$server['ram'].'M -Xms'.$server['ram'].'M -jar start.jar nogui'; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'sudo -u server'.$server['uid'].' mkdir -p oldstart;' // Создание папки логов + .'cat console.log >> oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm console.log; rm oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 server.properties start.sh;' // Обновление владельца файлов + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh > console.log"'); // Запуск игровго сервера + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function config($ip, $port, $slots, $config) + { + $aLine = explode("\n", $config); + + $search = array( + "#^server-ip=(.*?)$#is", + "#^server-port=(.*?)$#is", + "#^rcon\.port=(.*?)$#is", + "#^query\.port=(.*?)$#is", + "#^max-players=(.*?)$#is", + "#^enable-query=(.*?)$#is", + "#^debug=(.*?)$#is" + ); + + $config = ''; + + foreach($aLine as $line) + { + if(str_replace(array(' ', "\t"), '', $line) != '') + $edit = trim(preg_replace($search, array('','','','','','',''), $line)); + + if($edit != '') + $config .= $edit.PHP_EOL; + + $edit = ''; + } + + $config .= 'server-ip='.$ip.PHP_EOL + .'server-port='.$port.PHP_EOL + .'rcon.port='.($port+10000).PHP_EOL + .'query.port='.($port).PHP_EOL + .'max-players='.$slots.PHP_EOL + .'enable-query=true'.PHP_EOL + .'debug=false'; + + return $config; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mc/scan.php b/system/library/games/mc/scan.php new file mode 100644 index 0000000..ed18502 --- /dev/null +++ b/system/library/games/mc/scan.php @@ -0,0 +1,113 @@ +query('SELECT `address`, `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + include(LIB.'games/query/McQuery.php'); + + $sq = new McQuery($ip, $port); + + if($players_get) + $nmch = 'server_scan_mon_pl_'.$id; + else + $nmch = 'server_scan_mon_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + $info = $sq->getInfo($players_get); + + if(!is_array($info)) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + $players = scan::players($info['players_list']); + + $info['map'] = htmlspecialchars(mb_convert_encoding($info['map'], 'UTF-8', 'WINDOWS-1251')); + $out['name'] = htmlspecialchars(mb_convert_encoding($info['hostname'], 'UTF-8', 'WINDOWS-1251')); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = sys::int($info['online']); + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('ping', $player['ping']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function players($aPlayrs) + { + $i = 1; + $aData = array(); + + foreach($aPlayrs as $n => $player) + { + $aData[$i]['i'] = $i; + $aData[$i]['name'] = $player['nickname'] == '' ? 'Подключается' : htmlspecialchars($player['nickname']); + + $i+=1; + } + + return $aData; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mc/service.php b/system/library/games/mc/service.php new file mode 100644 index 0000000..38745a8 --- /dev/null +++ b/system/library/games/mc/service.php @@ -0,0 +1,369 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `mc`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`ram`,' + .'`param_fix`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`map`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + // Проверка RAM + if(!in_array($aData['ram'], explode(':', $tarif['ram']))) + sys::outjs(array('e' => 'Переданные данные ram неверны.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'mc') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение цены + $aPrice = explode(':', $tarif['price']); + $price = $aPrice[array_search($aData['ram'], explode(':', $tarif['ram']))]; + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $price, $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'ram' => $aData['ram'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['mc']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $aData['ram']*$aData['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'map' => $tarif['map'], // Фиксированное значение слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame['mc'].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="mc", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `ram`="'.$aSDATA['ram'].'", + `ram_fix`="'.$aSDATA['param_fix'].'", + `map_start`="'.$aSDATA['map'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="mc", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mc/tarif.php b/system/library/games/mc/tarif.php new file mode 100644 index 0000000..923aa1f --- /dev/null +++ b/system/library/games/mc/tarif.php @@ -0,0 +1,231 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['ram'].' RAM'); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + $sum = $tarif['slots'] ? $aPrice[array_search($ram, $aRAM)] : $aPrice[array_search($ram, $aRAM)]*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', $server['ram'].' RAM'); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan($server, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `ram`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $tarif = $sql->get(); + + $options = ''; + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + // Если есть выбор + if(count($aRAM) > 1) + { + // Удалить при наличии ram сервера из выбора + if(in_array($ram, $aRAM)) + unset($aRAM[array_search($ram, $aRAM)]); + + foreach($aRAM as $index => $ram) + $options .= ''; + }else + return NULL; + + $html->get('plan', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('info', $server['ram'].' RAM'); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit`, `ram` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + while($tarif = $sql->get($tarifs)) + { + if(!in_array($ram, explode(':', $tarif['ram']))) + continue; + + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', $server['ram'].' RAM'); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `vac`="1", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mta/action.php b/system/library/games/mta/action.php new file mode 100644 index 0000000..6e2cc55 --- /dev/null +++ b/system/library/games/mta/action.php @@ -0,0 +1,157 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe;'); + + // Временный файл + $temp = sys::temp(action::config($ip, $port, $server['slots_start'], $ssh->get('cat '.$tarif['install'].'/'.$server['uid'].'/mods/deathmatch/mtaserver.conf'))); + + // Обновление файла server.cfg + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/mods/deathmatch/mtaserver.conf', 0644); + + unlink($temp); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Параметры запуска + $bash = './mta-server'; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p mods/deathmatch/oldstart;' // Создание папки логов + .'cat mods/deathmatch/logs/server.log >> mods/deathmatch/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm mods/deathmatch/logs/server.log; rm mods/deathmatch/logs/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 mods/deathmatch/mtaserver.conf start.sh;' // Обновление владельца файлов + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function config($ip, $port, $slots, $config) + { + $aRepl = array( + '', '', + '', '', + '', '', + '', '', + '', '', + '', '', + '', '' + ); + + $config = str_ireplace($aRepl, $aRepl, $config); + $config = str_ireplace(array('', '', "\r", "\t"),'', $config); + $config = preg_replace("#\<\!--(.+?)--\>#is", '', $config); + + $aLine = explode("\n", $config); + + $search = array( + "#\(.+?)\<\/serverip\>#is", + "#\(.+?)\<\/maxplayers\>#is", + "#\(.+?)\<\/httpserver\>#is", + "#\(.+?)\<\/serverport\>#is", + "#\(.+?)\<\/httpport\>#is", + "#\(.+?)\<\/logfile\>#is", + "#\(.+?)\<\/ase\>#is" + ); + + $config = ''.PHP_EOL; + + foreach($aLine as $line) + { + if(str_replace(array(' ', "\t"), '', $line) != '') + $edit = trim(preg_replace($search, array('','','','','',''), $line)); + + if($edit != '') + $config .= ' '.$edit.PHP_EOL; + + $edit = ''; + } + + $config .= ' '.$ip.''.PHP_EOL + .' '.$slots.''.PHP_EOL + .' 1'.PHP_EOL + .' '.$port.''.PHP_EOL + .' '.($port+10000).''.PHP_EOL + .' 1'.PHP_EOL + .' logs/server.log'; + + return $config."\n".''; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mta/scan.php b/system/library/games/mta/scan.php new file mode 100644 index 0000000..7fe2d08 --- /dev/null +++ b/system/library/games/mta/scan.php @@ -0,0 +1,114 @@ +query('SELECT `address`, `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + include(LIB.'games/query/MtaQuery.php'); + + $sq = new MtaQuery($ip, $port); + + if($players_get) + $nmch = 'server_scan_mon_pl_'.$id; + else + $nmch = 'server_scan_mon_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + $info = $sq->getInfo($players_get); + + if(!is_array($info)) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + $players = scan::players($info['players_list']); + + $info['map'] = htmlspecialchars(mb_convert_encoding($info['map'], 'UTF-8', 'WINDOWS-1251')); + $out['name'] = htmlspecialchars(mb_convert_encoding($info['hostname'], 'UTF-8', 'WINDOWS-1251')); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = sys::int($info['players']); + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', $player['name']); + $html->set('ping', $player['ping']); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function players($aPlayrs) + { + $i = 1; + $aData = array(); + + foreach($aPlayrs as $n => $player) + { + $aData[$i]['i'] = $i; + $aData[$i]['name'] = $player['nickname'] == '' ? 'Подключается' : htmlspecialchars($player['nickname']); + $aData[$i]['ping'] = sys::int($player['ping']); + + $i+=1; + } + + return $aData; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mta/service.php b/system/library/games/mta/service.php new file mode 100644 index 0000000..74aa423 --- /dev/null +++ b/system/library/games/mta/service.php @@ -0,0 +1,354 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `mta`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'mta') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['mta']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['mta']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 777 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['mta']].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="mta", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="mta", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/mta/tarif.php b/system/library/games/mta/tarif.php new file mode 100644 index 0000000..a65da45 --- /dev/null +++ b/system/library/games/mta/tarif.php @@ -0,0 +1,179 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $sum = $tarif['slots'] ? $tarif['price'] : $tarif['price']*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan() + { + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/plugins.php b/system/library/games/plugins.php new file mode 100644 index 0000000..cbfe1e5 --- /dev/null +++ b/system/library/games/plugins.php @@ -0,0 +1,181 @@ +arr['images'])) + unset($html->arr['images']); + + $aImg = explode("\n", $images); + + foreach($aImg as $img) + { + $html->get('plugin_images', 'sections/servers/games/plugins'); + + $html->set('id', $plugin); + $html->set('img', $img); + + $html->pack('images'); + } + + return isset($html->arr['images']) ? $html->arr['images'] : ''; + } + + public static function status($status) + { + global $html; + + if(!$status) + { + $html->unit('unstable'); + $html->unit('stable', 1); + $html->unit('testing'); + }elseif($status == 2){ + $html->unit('unstable'); + $html->unit('stable'); + $html->unit('testing', 1); + }else{ + $html->unit('unstable', 1); + $html->unit('stable'); + $html->unit('testing'); + } + + return NULL; + } + + public static function required($id, $required, $choice, $mcache) + { + global $sql; + + if($required == '') + return NULL; + + $aRequi = explode(':', $required); + + foreach($aRequi as $pl) + { + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pl.'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$pl.'" LIMIT 1'); + $plRequi = $sql->get(); + + if($choice != '') + { + $aChoice = explode(' ', $choice); + + foreach($aChoice as $plugins) + { + $aPlugins = explode(':', $plugins); + + if(in_array($pl, $aPlugins)) + { + $options = ''; + foreach($aPlugins as $plugin) + { + $sql->query('SELECT `name`, `upd` FROM `plugins` WHERE `id`="'.$plugin.'" LIMIT 1'); + $data = $sql->get(); + + if($data['upd']) + { + $sql->query('SELECT `name` FROM `plugins_update` WHERE `plugin`="'.$plugin.'" ORDER BY `id` DESC LIMIT 1'); + $data = $sql->get(); + } + + $options .= ''; + } + + if($options != '') + sys::outjs(array('e' => 'Для данного плагина требуется установка одного из родителя', 'required' => true, 'pid' => $pl, 'select' => $options), $mcache); + } + } + } + + sys::outjs(array('e' => 'Для данного плагина требуется установка родителя', 'required' => true, 'pid' => $pl, 'pname' => htmlspecialchars_decode($plRequi['name'])), $mcache); + } + } + + return NULL; + } + + public static function incompatible($id, $incompatible, $mcache) + { + global $sql; + + if($incompatible == '') + return NULL; + + $aIncomp = explode(':', $incompatible); + + foreach($aIncomp as $pl) + { + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pl.'" LIMIT 1'); + if($sql->num()) + { + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$pl.'" LIMIT 1'); + $plIncomp = $sql->get(); + + sys::outjs(array('e' => 'Данный плагин несовместим с уже установленным плагином', 'pid' => $pl, 'pname' => htmlspecialchars_decode($plIncomp['name'])), $mcache); + } + } + + return NULL; + } + + public static function clear($clear, $uid, $dir) + { + global $ssh; + + // Если регулярное выражение + if(isset($clear['regex']) AND $clear['regex']) + { + $file = preg_replace($clear['text'], '', $ssh->get('sudo -u server'.$uid.' cat '.$dir.$clear['file'])); + + // Временный файл + $temp = sys::temp($file); + + $ssh->setfile($temp, $dir.$clear['file'], 0644); + + unlink($temp); + + $query = 'chown server'.$uid.':servers '.$dir.$clear['file'].';'; + + }else + // Удаление текста из файла + $query = 'sudo -u server'.$uid.' sed -i '."'s/".str_replace('/', '\/', htmlspecialchars_decode($clear['text']))."//g'".' '.$dir.$clear['file'].';'; + + $ssh->set($query.'sudo -u server'.$uid.' sed -i '."'/./!d'".' '.$dir.$clear['file']); + + return NULL; + } + + public static function write($write, $uid, $dir) + { + global $ssh; + + // Костыль (добавить пустую строку на всякий случай) + $query = 'sudo -u server'.$uid.' echo "" >> '.$dir.$write['file'].';'; + + // Исключить дублирование, путем удаления добавляемого текста + $query .= 'sudo -u server'.$uid.' sed -i '."'s/".str_replace('/', '\/', htmlspecialchars_decode($write['text']))."//g'".' '.$dir.$write['file'].';'; + + // Добавление текста в начало файла + if($write['top']) + $query .= 'sudo -u server'.$uid.' touch '.$dir.$write['file'].'; sudo -u server'.$uid.' sed -i '."'1i ".str_replace(array('/', "'", '\"'), array('\/', "\'", '"'), htmlspecialchars_decode($write['text']))."'".' '.$dir.$write['file'].';'; + else + // Добавление текста в конец файла + $query .= 'sudo -u server'.$uid.' touch '.$dir.$write['file'].'; sudo -u server'.$uid.' echo "'.str_replace('"', '\"', htmlspecialchars_decode($write['text'])).'" >> '.$dir.$write['file'].';'; + + $ssh->set($query.'sudo -u server'.$uid.' sed -i '."'/./!d'".' '.$dir.$clear['file']); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/query/BaseSocket.php b/system/library/games/query/BaseSocket.php new file mode 100644 index 0000000..0e7cb0e --- /dev/null +++ b/system/library/games/query/BaseSocket.php @@ -0,0 +1,98 @@ +Close(); + } + + abstract public function Close(); + abstract public function Open($Address, $Port, $Timeout, $Engine); + abstract public function Write($Header, $String = ''); + abstract public function Read($Length = 1400); + + protected function ReadInternal($Buffer, $Length, $SherlockFunction) + { + if($Buffer->Remaining() === 0) + return false; + + if($Buffer->Remaining() === 0) + return false; + + $Header = $Buffer->GetLong(); + + if($Header === -2) + { + $Packets = []; + $IsCompressed = false; + $ReadMore = false; + + do + { + $RequestID = $Buffer->GetLong(); + + switch($this->Engine) + { + case SourceQuery::GOLDSOURCE: + { + $PacketCountAndNumber = $Buffer->GetByte(); + $PacketCount = $PacketCountAndNumber & 0xF; + $PacketNumber = $PacketCountAndNumber >> 4; + + break; + } + + case SourceQuery::SOURCE: + { + $IsCompressed = ($RequestID & 0x80000000) !== 0; + $PacketCount = $Buffer->GetByte(); + $PacketNumber = $Buffer->GetByte() + 1; + + if($IsCompressed) + { + $Buffer->GetLong(); + + $PacketChecksum = $Buffer->GetUnsignedLong(); + }else + $Buffer->GetShort(); + + break; + } + } + + $Packets[$PacketNumber] = $Buffer->Get(); + + $ReadMore = $PacketCount > sizeof($Packets); + } + + while($ReadMore && $SherlockFunction($Buffer, $Length)); + + $Data = Implode($Packets); + + if($IsCompressed) + { + if(!Function_Exists('bzdecompress')) + return false; + + $Data = bzdecompress($Data); + + if(CRC32($Data) !== $PacketChecksum) + return false; + } + + $Buffer->Set(SubStr($Data, 4)); + }else + return false; + + return $Buffer; + } + } \ No newline at end of file diff --git a/system/library/games/query/Buffer.php b/system/library/games/query/Buffer.php new file mode 100644 index 0000000..ae2e9d5 --- /dev/null +++ b/system/library/games/query/Buffer.php @@ -0,0 +1,102 @@ +Buffer = $Buffer; + $this->Length = StrLen($Buffer); + $this->Position = 0; + } + + public function Remaining() + { + return $this->Length - $this->Position; + } + + public function Get($Length = -1) + { + if($Length === 0) + return ''; + + $Remaining = $this->Remaining(); + + if($Length === -1) + $Length = $Remaining; + + else if($Length > $Remaining) + return ''; + + $Data = SubStr($this->Buffer, $this->Position, $Length); + + $this->Position += $Length; + + return $Data; + } + + public function GetByte() + { + return Ord($this->Get(1)); + } + + public function GetShort() + { + if($this->Remaining() < 2) + return false; + + $Data = UnPack('v', $this->Get(2)); + + return $Data[ 1 ]; + } + + public function GetLong() + { + if($this->Remaining() < 4) + return false; + + $Data = UnPack('l', $this->Get(4)); + + return $Data[ 1 ]; + } + + public function GetFloat() + { + if($this->Remaining() < 4) + return false; + + $Data = UnPack('f', $this->Get(4)); + + return $Data[ 1 ]; + } + + public function GetUnsignedLong() + { + if($this->Remaining() < 4) + return false; + + $Data = UnPack('V', $this->Get(4)); + + return $Data[ 1 ]; + } + + public function GetString() + { + $ZeroBytePosition = StrPos($this->Buffer, "\0", $this->Position); + + if($ZeroBytePosition === false) + return ''; + + $String = $this->Get($ZeroBytePosition - $this->Position); + + $this->Position++; + + return $String; + } + } \ No newline at end of file diff --git a/system/library/games/query/GoldSourceRcon.php b/system/library/games/query/GoldSourceRcon.php new file mode 100644 index 0000000..3e2f466 --- /dev/null +++ b/system/library/games/query/GoldSourceRcon.php @@ -0,0 +1,105 @@ +Socket = $Socket; + } + + public function Close() + { + $this->RconChallenge = 0; + $this->RconRequestId = 0; + $this->RconPassword = 0; + } + + public function Open() + { + // + } + + public function Write($Header, $String = '') + { + $Command = Pack('cccca*', 0xFF, 0xFF, 0xFF, 0xFF, $String); + $Length = StrLen($Command); + + return $Length === FWrite($this->Socket->Socket, $Command, $Length); + } + + public function Read($Length = 1400) + { + $Buffer = $this->Socket->Read(); + + $StringBuffer = ''; + $ReadMore = false; + + do + { + $ReadMore = $Buffer->Remaining() > 0; + + if($ReadMore) + { + if($Buffer->GetByte() !== SourceQuery::S2A_RCON) + sys::outjs(array('e' => 'неправильный rcon запрос.')); + + $Packet = $Buffer->Get(); + $StringBuffer .= $Packet; + + $ReadMore = StrLen($Packet) > 1000; + + if($ReadMore) + $Buffer = $this->Socket->Read(); + } + } + + while($ReadMore); + + $Trimmed = trim($StringBuffer); + + if($Trimmed === 'Bad rcon_password.') + sys::outjs(array('e' => 'rcon_password из server.cfg не подходит.')); + + else if($Trimmed === 'You have been banned from this server.') + sys::outjs(array('e' => 'Игровой сервер заблокировал доступ.')); + + $Buffer->Set($Trimmed); + + return $Buffer; + } + + public function Command($Command) + { + if(!$this->RconChallenge) + return false; + + $this->Write(0, 'rcon ' . $this->RconChallenge . ' "' . $this->RconPassword . '" ' . $Command . "\0"); + $Buffer = $this->Read(); + + if($Buffer) + return $Buffer->Get(); + + return $Buffer; + } + + public function Authorize($Password) + { + $this->RconPassword = $Password; + + $this->Write(0, 'challenge rcon'); + $Buffer = $this->Socket->Read(); + + if($Buffer->Get(14) !== 'challenge rcon') + sys::outjs(array('e' => 'Не удалось выполнить rcon запрос.')); + + $this->RconChallenge = Trim($Buffer->Get()); + } + } \ No newline at end of file diff --git a/system/library/games/query/McQuery.php b/system/library/games/query/McQuery.php new file mode 100644 index 0000000..2615d2c --- /dev/null +++ b/system/library/games/query/McQuery.php @@ -0,0 +1,96 @@ +stack = fsockopen('udp://'.$ip, $port, $errorNum, $errorString, 2); + + socket_set_timeout($this->stack, 2); + } + + public function getInfo($pl = false) + { + $Data = $this->WriteData(0x00, $this->GetChallenge().Pack('c*', 0x00, 0x00, 0x00, 0x00)); + + $server_info = array(); + + $Data = substr($Data, 11); + $Data = explode("\x00\x00\x01player_\x00\x00", $Data); + $aData = explode("\x00", $Data[0]); + + $last = ''; + + $keys = Array( + 'hostname' => 'hostname', + 'version' => 'version', + 'plugins' => 'plugins', + 'map' => 'map', + 'numplayers' => 'online' + ); + + foreach($aData as $index => $val) + { + if(~$index & 1) + { + if(!array_key_exists($val, $keys)) + { + $last = false; + continue; + } + + $last = $keys[$val]; + $server_info[$last] = ''; + + }elseif($last != false) + $server_info[$last] = $val; + } + + if(!count($server_info)) + return NULL; + + if(!$pl) + return $server_info; + + $server_info['players_list'] = explode("\x00", substr($Data[1], 0, -2)); + + if(!isset($server_info['players_list'][1])) + $server_info['players_list'] = array(); + + return $server_info; + } + + private function GetChallenge() + { + $Data = $this->WriteData(0x09); + + if($Data === false) + return NULL; + + return Pack('N', $Data); + } + + private function WriteData($Command, $Append = '') + { + $Command = Pack('c*', 0xFE, 0xFD, $Command, 0x01, 0x02, 0x03, 0x04).$Append; + $Length = StrLen($Command); + + if($Length !== fwrite($this->stack, $Command, $Length)) + return NULL; + + $Data = fread($this->stack, 2048); + + if($Data === false) + return NULL; + + if(StrLen($Data) < 5 || $Data[0] != $Command[2]) + return false; + + return SubStr($Data, 5); + } + } +?> \ No newline at end of file diff --git a/system/library/games/query/MtaQuery.php b/system/library/games/query/MtaQuery.php new file mode 100644 index 0000000..e86cdb0 --- /dev/null +++ b/system/library/games/query/MtaQuery.php @@ -0,0 +1,93 @@ +stack = fsockopen('udp://'.$ip, $port+123, $errorNum, $errorString, 2); + + socket_set_timeout($this->stack, 2); + } + + public function getInfo($pl = false) + { + fwrite($this->stack, 's'); + + $buffer = fread($this->stack, 4096); + + if(!$buffer) + return NULL; + + $buffer = substr($buffer, 4); + + $server_info = array(); + + $server_info['gamename'] = $this->cut_pascal($buffer, 1, -1); + $server_info['hostport'] = $this->cut_pascal($buffer, 1, -1); + $server_info['hostname'] = $this->cut_pascal($buffer, 1, -1); + $server_info['gamemode'] = $this->cut_pascal($buffer, 1, -1); + $server_info['map'] = $this->cut_pascal($buffer, 1, -1); + $server_info['version'] = $this->cut_pascal($buffer, 1, -1); + $server_info['password'] = $this->cut_pascal($buffer, 1, -1); + $server_info['players'] = $this->cut_pascal($buffer, 1, -1); + $server_info['playersmax'] = $this->cut_pascal($buffer, 1, -1); + + while($buffer && $buffer[0] != "\x01") + { + $item_key = strtolower($this->cut_pascal($buffer, 1, -1)); + $item_value = $this->cut_pascal($buffer, 1, -1); + + $server_info[$item_key] = $item_value; + } + + if(!$pl) + return $server_info; + + $buffer = substr($buffer, 1); + + $i = 1; + + while($buffer) + { + $bit_flags = $this->cut_byte($buffer, 1); + + $field_list = array('name', '', '', '', 'ping', ''); + + foreach($field_list as $item_key) + { + $item_value = $this->cut_pascal($buffer, 1, -1); + + if(!$item_key) + continue; + + $server_info['players_list'][$i][$item_key] = $item_value; + } + + $i+=1; + } + + return $server_info; + } + + private function cut_pascal(&$buffer, $start_byte = 1, $length_adjust = 0, $end_byte = 0) + { + $length = ord(substr($buffer, 0, $start_byte)) + $length_adjust; + $string = substr($buffer, $start_byte, $length); + $buffer = substr($buffer, $start_byte + $length + $end_byte); + + return $string; + } + + private function cut_byte(&$buffer, $length) + { + $string = substr($buffer, 0, $length); + $buffer = substr($buffer, $length); + + return $string; + } + } +?> \ No newline at end of file diff --git a/system/library/games/query/SampQuery.php b/system/library/games/query/SampQuery.php new file mode 100644 index 0000000..5b6a2ba --- /dev/null +++ b/system/library/games/query/SampQuery.php @@ -0,0 +1,122 @@ +stack = fsockopen('udp://'.$ip, $port, $errorNum, $errorString, 2); + + socket_set_timeout($this->stack, 2); + } + + public function getInfo() + { + @fwrite($this->stack, $this->assemblePacket('i')); + + fread($this->stack, 11); + + $serverInfo = array(); + + $serverInfo['password'] = sys::int(ord(fread($this->stack, 1))); + + $serverInfo['players'] = sys::int($this->toInt(fread($this->stack, 2))); + + $serverInfo['maxplayers'] = sys::int($this->toInt(fread($this->stack, 2))); + + $strLen = ord(fread($this->stack, 4)); + + if(!$strLen) + return -1; + + $serverInfo['hostname'] = fread($this->stack, $strLen); + + $strLen = ord(fread($this->stack, 4)); + $serverInfo['gamemode'] = fread($this->stack, $strLen); + + $strLen = ord(fread($this->stack, 4)); + $serverInfo['map'] = fread($this->stack, $strLen); + + return $serverInfo; + } + + public function getDetailedPlayers() + { + @fwrite($this->stack, $this->assemblePacket('d')); + fread($this->stack, 11); + + $playerCount = ord(fread($this->stack, 2)); + $players = array(); + + for($i = 0; $i < $playerCount; ++$i) + { + $player['playerid'] = ord(fread($this->stack, 1)); + + $strLen = ord(fread($this->stack, 1)); + $player['nickname'] = fread($this->stack, $strLen); + + $player['ping'] = $this->toInt(fread($this->stack, 4)); + + $players[$i] = $player; + + unset($player); + } + + return $players; + } + + private function toInt($string) + { + if($string === '') + return null; + + $int = 0; + $int += (ord($string[0])); + + if(isset($string[1])) + $int += (ord($string[1]) << 8); + + if(isset($string[2])) + $int += (ord($string[2]) << 16); + + if(isset($string[3])) + $int += (ord($string[3]) << 24); + + if($int >= 4294967294) + $int -= 4294967296; + + return $int; + } + + private function assemblePacket($type) + { + $packet = 'SAMP'; + $packet .= chr(strtok($this->server, '.')); + $packet .= chr(strtok('.')); + $packet .= chr(strtok('.')); + $packet .= chr(strtok('.')); + $packet .= chr($this->port & 0xFF); + $packet .= chr($this->port >> 8 & 0xFF); + $packet .= $type; + + return $packet; + } + + public function connect() + { + $connected = false; + fwrite($this->stack, $this->assemblePacket('p0101')); + + if(fread($this->stack, 10)) + { + if(fread($this->stack, 5) == 'p0101') + $connected = true; + } + + return $connected; + } + } +?> \ No newline at end of file diff --git a/system/library/games/query/Socket.php b/system/library/games/query/Socket.php new file mode 100644 index 0000000..ffe1444 --- /dev/null +++ b/system/library/games/query/Socket.php @@ -0,0 +1,62 @@ +Socket) + { + FClose($this->Socket); + + $this->Socket = null; + } + } + + public function Open($Address, $Port, $Timeout, $Engine) + { + $this->Timeout = $Timeout; + $this->Engine = $Engine; + $this->Port = $Port; + $this->Address = $Address; + + $this->Socket = @FSockOpen('udp://' . $Address, $Port, $ErrNo, $ErrStr, $Timeout); + + if($ErrNo || $this->Socket === false) + return false; + + Stream_Set_Timeout($this->Socket, $Timeout); + Stream_Set_Blocking($this->Socket, true); + } + + public function Write($Header, $String = '') + { + $Command = Pack('ccccca*', 0xFF, 0xFF, 0xFF, 0xFF, $Header, $String); + $Length = StrLen($Command); + + return $Length === FWrite($this->Socket, $Command, $Length); + } + + public function Read($Length = 1400) + { + $Buffer = new Buffer(); + $Buffer->Set(FRead($this->Socket, $Length)); + + $this->ReadInternal($Buffer, $Length, [$this, 'Sherlock']); + + return $Buffer; + } + + public function Sherlock($Buffer, $Length) + { + $Data = FRead($this->Socket, $Length); + + if(StrLen($Data) < 4) + return false; + + $Buffer->Set($Data); + + return $Buffer->GetLong() === -2; + } + } \ No newline at end of file diff --git a/system/library/games/query/SourceQuery.php b/system/library/games/query/SourceQuery.php new file mode 100644 index 0000000..69f5685 --- /dev/null +++ b/system/library/games/query/SourceQuery.php @@ -0,0 +1,347 @@ +Socket = $Socket ?: new Socket(); + } + + public function __destruct() + { + $this->Disconnect(); + } + + public function Connect($Address, $Port, $Timeout = 3, $Engine = self::SOURCE) + { + $this->Disconnect(); + + if(!is_int($Timeout) || $Timeout < 0) + return false; + + $this->Socket->Open($Address, (int)$Port, $Timeout, (int)$Engine); + + $this->Connected = true; + } + + public function SetUseOldGetChallengeMethod($Value) + { + $Previous = $this->UseOldGetChallengeMethod; + + $this->UseOldGetChallengeMethod = $Value === true; + + return $Previous; + } + + public function Disconnect() + { + $this->Connected = false; + $this->Challenge = 0; + + $this->Socket->Close(); + + if($this->Rcon) + { + $this->Rcon->Close(); + + $this->Rcon = null; + } + } + + public function Ping() + { + if(!$this->Connected) + return false; + + $this->Socket->Write(self::A2S_PING); + $Buffer = $this->Socket->Read(); + + return $Buffer->GetByte() === self::S2A_PING; + } + + public function GetInfo() + { + if(!$this->Connected) + return false; + + $this->Socket->Write(self::A2S_INFO, "Source Engine Query\0"); + $Buffer = $this->Socket->Read(); + + $Type = $Buffer->GetByte(); + + if($Type === self::S2A_INFO_OLD && $this->Socket->Engine === self::GOLDSOURCE) + { + $Server['Address'] = $Buffer->GetString(); + $Server['HostName'] = $Buffer->GetString(); + $Server['Map'] = $Buffer->GetString(); + $Server['ModDir'] = $Buffer->GetString(); + $Server['ModDesc'] = $Buffer->GetString(); + $Server['Players'] = $Buffer->GetByte(); + $Server['MaxPlayers'] = $Buffer->GetByte(); + $Server['Protocol'] = $Buffer->GetByte(); + $Server['Dedicated'] = Chr($Buffer->GetByte()); + $Server['Os'] = Chr($Buffer->GetByte()); + $Server['Password'] = $Buffer->GetByte() === 1; + $Server['IsMod'] = $Buffer->GetByte() === 1; + + if($Server['IsMod']) + { + $Mod['Url'] = $Buffer->GetString(); + $Mod['Download'] = $Buffer->GetString(); + $Buffer->Get(1); + $Mod['Version'] = $Buffer->GetLong(); + $Mod['Size'] = $Buffer->GetLong(); + $Mod['ServerSide'] = $Buffer->GetByte() === 1; + $Mod['CustomDLL'] = $Buffer->GetByte() === 1; + } + + $Server['Secure'] = $Buffer->GetByte() === 1; + $Server['Bots'] = $Buffer->GetByte(); + + if(isset($Mod)) + $Server['Mod'] = $Mod; + + return $Server; + } + + if($Type !== self::S2A_INFO) + return false; + + if($Type !== self::S2A_INFO) + return false; + + $Server['Protocol'] = $Buffer->GetByte(); + $Server['HostName'] = $Buffer->GetString(); + $Server['Map'] = $Buffer->GetString(); + $Server['ModDir'] = $Buffer->GetString(); + $Server['ModDesc'] = $Buffer->GetString(); + $Server['AppID'] = $Buffer->GetShort(); + $Server['Players'] = $Buffer->GetByte(); + $Server['MaxPlayers'] = $Buffer->GetByte(); + $Server['Bots'] = $Buffer->GetByte(); + $Server['Dedicated'] = Chr($Buffer->GetByte()); + $Server['Os'] = Chr($Buffer->GetByte()); + $Server['Password'] = $Buffer->GetByte() === 1; + $Server['Secure'] = $Buffer->GetByte() === 1; + + if($Server['AppID'] === 2400) + { + $Server['GameMode'] = $Buffer->GetByte(); + $Server['WitnessCount'] = $Buffer->GetByte(); + $Server['WitnessTime'] = $Buffer->GetByte(); + } + + $Server['Version'] = $Buffer->GetString(); + + if($Buffer->Remaining() > 0) + { + $Server['ExtraDataFlags'] = $Flags = $Buffer->GetByte(); + + if($Flags & 0x80) + $Server['GamePort'] = $Buffer->GetShort(); + + if($Flags & 0x10) + { + $SteamIDLower = $Buffer->GetUnsignedLong(); + $SteamIDInstance = $Buffer->GetUnsignedLong(); + $SteamID = 0; + + if(PHP_INT_SIZE === 4) + { + if(extension_loaded('gmp')) + { + $SteamIDLower = gmp_abs($SteamIDLower); + $SteamIDInstance = gmp_abs($SteamIDInstance); + $SteamID = gmp_strval(gmp_or($SteamIDLower, gmp_mul($SteamIDInstance, gmp_pow(2, 32)))); + }else + return false; + }else + $SteamID = $SteamIDLower | ($SteamIDInstance << 32); + + $Server['SteamID'] = $SteamID; + + unset($SteamIDLower, $SteamIDInstance, $SteamID); + } + + if($Flags & 0x40) + { + $Server['SpecPort'] = $Buffer->GetShort(); + $Server['SpecName'] = $Buffer->GetString(); + } + + if($Flags & 0x20) + $Server['GameTags'] = $Buffer->GetString(); + + if($Flags & 0x01) + $Server['GameID'] = $Buffer->GetUnsignedLong() | ($Buffer->GetUnsignedLong() << 32); + + if($Buffer->Remaining() > 0) + return false; + } + + return $Server; + } + + public function GetPlayers() + { + if(!$this->Connected) + return false; + + $this->GetChallenge(self::A2S_PLAYER, self::S2A_PLAYER); + + $this->Socket->Write(self::A2S_PLAYER, $this->Challenge); + $Buffer = $this->Socket->Read(14000); + $Type = $Buffer->GetByte(); + + if($Type !== self::S2A_PLAYER) + return false; + + $Players = []; + $Count = $Buffer->GetByte(); + + while($Count-- > 0 && $Buffer->Remaining() > 0) + { + $Player['Id'] = $Buffer->GetByte(); + $Player['Name'] = $Buffer->GetString(); + $Player['Frags'] = $Buffer->GetLong(); + $Player['Time'] = (int)$Buffer->GetFloat(); + $Player['TimeF'] = GMDate(($Player['Time'] > 3600 ? "H:i:s" : "i:s"), $Player['Time']); + + $Players[] = $Player; + } + + return $Players; + } + + public function GetRules() + { + if(!$this->Connected) + return false; + + $this->GetChallenge(self::A2S_RULES, self::S2A_RULES); + $this->Socket->Write(self::A2S_RULES, $this->Challenge); + $Buffer = $this->Socket->Read(); + $Type = $Buffer->GetByte(); + + if($Type !== self::S2A_RULES) + return false; + + $Rules = []; + $Count = $Buffer->GetShort(); + + while($Count-- > 0 && $Buffer->Remaining() > 0) + { + $Rule = $Buffer->GetString(); + $Value = $Buffer->GetString(); + + if(!empty($Rule)) + $Rules[$Rule] = $Value; + } + + return $Rules; + } + + private function GetChallenge($Header, $ExpectedResult) + { + if($this->Challenge) + return; + + if($this->UseOldGetChallengeMethod) + $Header = self::A2S_SERVERQUERY_GETCHALLENGE; + + $this->Socket->Write($Header, "\xFF\xFF\xFF\xFF"); + $Buffer = $this->Socket->Read(); + $Type = $Buffer->GetByte(); + + switch($Type) + { + case self::S2A_CHALLENGE: + { + $this->Challenge = $Buffer->Get(4); + + return; + } + case $ExpectedResult: + { + return; + } + case 0: + { + return; + } + default: + { + return; + } + } + } + + public function SetRconPassword($Password) + { + if(!$this->Connected) + { + return false; + } + + switch($this->Socket->Engine) + { + case SourceQuery::GOLDSOURCE: + { + $this->Rcon = new GoldSourceRcon($this->Socket); + + break; + } + case SourceQuery::SOURCE: + { + $this->Rcon = new SourceRcon($this->Socket); + + break; + } + } + + $this->Rcon->Open(); + $this->Rcon->Authorize($Password); + } + + public function Rcon($Command) + { + if(!$this->Connected) + { + return false; + } + + if($this->Rcon === null) + { + return false; + } + + return $this->Rcon->Command($Command); + } + } \ No newline at end of file diff --git a/system/library/games/query/SourceRcon.php b/system/library/games/query/SourceRcon.php new file mode 100644 index 0000000..76ac507 --- /dev/null +++ b/system/library/games/query/SourceRcon.php @@ -0,0 +1,148 @@ +Socket = $Socket; + } + + public function Close() + { + if($this->RconSocket) + { + FClose($this->RconSocket); + + $this->RconSocket = null; + } + + $this->RconRequestId = 0; + } + + public function Open() + { + if(!$this->RconSocket) + { + $this->RconSocket = @FSockOpen($this->Socket->Address, $this->Socket->Port, $ErrNo, $ErrStr, $this->Socket->Timeout); + + if($ErrNo || !$this->RconSocket) + return false; + + Stream_Set_Timeout($this->RconSocket, $this->Socket->Timeout); + Stream_Set_Blocking($this->RconSocket, true); + } + } + + public function Write($Header, $String = '') + { + $Command = Pack('VV', ++$this->RconRequestId, $Header) . $String . "\x00\x00"; + $Command = Pack('V', StrLen($Command)) . $Command; + $Length = StrLen($Command); + + return $Length === FWrite($this->RconSocket, $Command, $Length); + } + + public function Read() + { + $Buffer = new Buffer(); + $Buffer->Set(FRead($this->RconSocket, 4)); + + if($Buffer->Remaining() < 4) + return false; + + $PacketSize = $Buffer->GetLong(); + + $Buffer->Set(FRead($this->RconSocket, $PacketSize)); + + $Data = $Buffer->Get(); + + $Remaining = $PacketSize - StrLen($Data); + + while($Remaining > 0) + { + $Data2 = FRead($this->RconSocket, $Remaining); + + $PacketSize = StrLen($Data2); + + if($PacketSize === 0) + return false; + + $Data .= $Data2; + $Remaining -= $PacketSize; + } + + $Buffer->Set($Data); + + return $Buffer; + } + + public function Command($Command) + { + $this->Write(SourceQuery::SERVERDATA_EXECCOMMAND, $Command); + $Buffer = $this->Read(); + + $Buffer->GetLong(); + + $Type = $Buffer->GetLong(); + + if($Type === SourceQuery::SERVERDATA_AUTH_RESPONSE) + return false; + + if($Type !== SourceQuery::SERVERDATA_RESPONSE_VALUE) + return false; + + $Data = $Buffer->Get(); + + if(StrLen($Data) >= 4000) + { + do + { + $this->Write(SourceQuery::SERVERDATA_RESPONSE_VALUE); + + $Buffer = $this->Read(); + + $Buffer->GetLong(); + + if($Buffer->GetLong() !== SourceQuery::SERVERDATA_RESPONSE_VALUE) + break; + + $Data2 = $Buffer->Get(); + + if($Data2 === "\x00\x01\x00\x00\x00\x00") + break; + + $Data .= $Data2; + } + + while(true); + } + + return rtrim($Data, "\0"); + } + + public function Authorize($Password) + { + $this->Write(SourceQuery::SERVERDATA_AUTH, $Password); + $Buffer = $this->Read(); + + $RequestID = $Buffer->GetLong(); + $Type = $Buffer->GetLong(); + + if($Type === SourceQuery::SERVERDATA_RESPONSE_VALUE) + { + $Buffer = $this->Read(); + + $RequestID = $Buffer->GetLong(); + $Type = $Buffer->GetLong(); + } + + if($RequestID === -1 || $Type !== SourceQuery::SERVERDATA_AUTH_RESPONSE) + return false; + } + } \ No newline at end of file diff --git a/system/library/games/samp/action.php b/system/library/games/samp/action.php new file mode 100644 index 0000000..6d96f64 --- /dev/null +++ b/system/library/games/samp/action.php @@ -0,0 +1,129 @@ +query('SELECT `uid`, `unit`, `tarif`, `game`, `address`, `slots_start`, `name`, `map_start`, `time_start`, `core_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соедниения пу с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return array('e' => sys::text('error', 'ssh')); + + list($ip, $port) = explode(':', $server['address']); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe;'); + + // Временный файл + $temp = sys::temp(action::config($ip, $port, $server['slots_start'], $ssh->get('cat '.$tarif['install'].'/'.$server['uid'].'/server.cfg'))); + + // Обновление файла server.cfg + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.cfg', 0644); + + unlink($temp); + + $taskset = ''; + + // Если включена система автораспределения и не установлен фиксированный поток + if($cfg['cpu_route'] AND !$server['core_fix']) + { + $proc_stat = array(); + + $proc_stat[0] = $ssh->get('cat /proc/stat'); + } + + // Если система автораспределения продолжить парсинг загрузки процессора + if(isset($proc_stat)) + { + $proc_stat[1] = $ssh->get('cat /proc/stat'); + + // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера) + $core = sys::cpu_idle($proc_stat, $server['unit'], false); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого) + + if(!is_numeric($core)) + return array('e' => sys::text('error', 'cpu')); + + $taskset = 'taskset -c '.$core; + } + + if($server['core_fix']) + { + $core = $server['core_fix']-1; + $taskset = 'taskset -c '.$core; + } + + // Параметры запуска + $bash = './samp03svr'; + + // Временный файл + $temp = sys::temp($bash); + + // Обновление файла start.sh + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/start.sh', 0500); + + // Строка запуска + $ssh->set('cd '.$tarif['install'].$server['uid'].';' // переход в директорию игрового сервера + .'rm *.pid;' // Удаление *.pid файлов + .'sudo -u server'.$server['uid'].' mkdir -p oldstart;' // Создание папки логов + .'cat server_log.txt >> oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm server_log.txt; rm oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска + .'chown server'.$server['uid'].':1000 server.cfg start.sh;' // Обновление владельца файлов + .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера + + $core = !isset($core) ? 0 : $core+1; + + // Обновление информации в базе + $sql->query('UPDATE `servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + unlink($temp); + + // Сброс кеша + actions::clmcache($id); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0)); + + return array('s' => 'ok'); + } + + public static function config($ip, $port, $slots, $config) + { + $aLine = explode("\n", $config); + + $eConfig = ''; + + foreach($aLine as $line) + { + $param = explode(' ', trim($line)); + + if(in_array(trim($param[0]), array('bind', 'port', 'maxplayers', 'query'))) + continue; + + $eConfig .= $line.PHP_EOL; + } + + $eConfig .= 'bind '.$ip.PHP_EOL + .'port '.$port.PHP_EOL + .'maxplayers '.$slots.PHP_EOL + .'query 1'; + + return $eConfig; + } + } +?> \ No newline at end of file diff --git a/system/library/games/samp/scan.php b/system/library/games/samp/scan.php new file mode 100644 index 0000000..36cac68 --- /dev/null +++ b/system/library/games/samp/scan.php @@ -0,0 +1,114 @@ +query('SELECT `address`, `game`, `name`, `map`, `online`, `players`, `status`, `time`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + include(LIB.'games/query/SampQuery.php'); + + $sq = new SampQuery($ip, $port); + + if($players_get) + $nmch = 'server_scan_mon_pl_'.$id; + else + $nmch = 'server_scan_mon_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $out = array(); + + $out['time'] = 'Арендован до: '.date('d.m.Y - H:i', $server['time']); + + if($server['status'] == 'overdue') + $out['time_end'] = 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400); + else + $out['time_end'] = 'Осталось: '.sys::date('min', $server['time']); + + if(!$sq->connect()) + { + $out['name'] = $server['name']; + $out['status'] = sys::status($server['status'], $server['game'], $server['map']); + $out['online'] = $server['online']; + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, $server['status'], $server['game']); + + if($players_get) + $out['players'] = base64_decode($server['players']); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + $info = $sq->getInfo(); + + if($players_get) + $players = scan::players($sq->getDetailedPlayers()); + + $info['map'] = htmlspecialchars(mb_convert_encoding($info['map'], 'UTF-8', 'WINDOWS-1251')); + $out['name'] = htmlspecialchars(mb_convert_encoding($info['hostname'], 'UTF-8', 'WINDOWS-1251')); + $out['status'] = sys::status('working', $server['game'], $info['map']); + $out['online'] = sys::int($info['players']); + $out['image'] = ''; + $out['buttons'] = sys::buttons($id, 'working', $server['game']); + $out['players'] = ''; + + if($players_get) + { + foreach($players as $index => $player) + { + $html->get($server['game'], 'sections/servers/players'); + + $html->set('i', $player['i']); + $html->set('name', htmlspecialchars($player['name'])); + + $html->pack('list'); + } + + $out['players'] = isset($html->arr['list']) ? $html->arr['list'] : ''; + } + + $sql->query('UPDATE `servers` set ' + .'`name`="'.$out['name'].'", ' + .'`online`="'.$out['online'].'", ' + .'`map`="'.$info['map'].'", ' + .'`status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + if($players_get) + $sql->query('UPDATE `servers` set `players`="'.base64_encode($out['players']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $out, false, $cfg['mcache_server_mon']); + + return $out; + } + + public static function players($aPlayrs) + { + $i = 1; + $aData = array(); + + foreach($aPlayrs as $n => $player) + { + $aData[$i]['i'] = $i; + $aData[$i]['name'] = $player['nickname'] == '' ? 'Подключается' : htmlspecialchars($player['nickname']); + $aData[$i]['ping'] = sys::int($player['ping']); + + $i+=1; + } + + return $aData; + } + } +?> \ No newline at end of file diff --git a/system/library/games/samp/service.php b/system/library/games/samp/service.php new file mode 100644 index 0000000..0d45d60 --- /dev/null +++ b/system/library/games/samp/service.php @@ -0,0 +1,355 @@ +query('SELECT `address`, `test` FROM `units` WHERE `id`="'.$aData['unit'].'" AND `samp`="1" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Локация не найдена.')); + + $unit = $sql->get(); + + // Проверка тарифа + $sql->query('SELECT `id` FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" AND `unit`="'.$aData['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Тариф не найден.')); + + $sql->query('SELECT ' + .'`slots_min`,' + .'`slots_max`,' + .'`port_min`,' + .'`port_max`,' + .'`hostname`,' + .'`packs`,' + .'`time`,' + .'`test`,' + .'`tests`,' + .'`discount`,' + .'`ftp`,' + .'`plugins`,' + .'`console`,' + .'`stats`,' + .'`copy`,' + .'`web`,' + .'`plugins_install`,' + .'`hdd`,' + .'`autostop`,' + .'`core_fix`,' + .'`ip`,' + .'`price`' + .' FROM `tarifs` WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + $tarif = $sql->get(); + + // Проверка сборки + if(!array_key_exists($aData['pack'], sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $test = 0; + + // Проверка периода на тест + if($aData['test']) + { + if(!$tarif['test'] || !$unit['test']) + sys::outjs(array('e' => 'Тестовый период недоступен.')); + + + // Проверка на повторный запрос + $sql->query('SELECT `id`, `game` FROM `tests` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $test_info = $sql->get(); + + if(!$cfg['tests']['game'] || $test_info['game'] == 'samp') + sys::outjs(array('e' => 'Тестовый период предоставляется один раз.')); + + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" AND `test`="1" LIMIT 1'); + if($sql->num() AND !$cfg['tests']['sametime']) + sys::outjs(array('e' => 'Чтобы получить тестовый период другой игры, дождитесь окончания текущего.')); + } + + // Проверка наличия мест на локации + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$unit['test']); + if($sql->num() == $unit['test']) + sys::outjs(array('e' => 'Свободного места для тестового периода нет.')); + + // Проверка наличия мест для выбранного тарифа + $sql->query('SELECT `id` FROM `servers` WHERE `tarif`="'.$aData['tarif'].'" AND `test`="1" AND `time`>"'.$start_point.'" LIMIT '.$tarif['tests']); + if($sql->num() == $tarif['tests']) + sys::outjs(array('e' => 'Свободного места для тестового периода выбранного тарифа нет.')); + + $test = 1; + }else + // Проверка периода + if(!$cfg['settlement_period'] AND !in_array($aData['time'], explode(':', $tarif['time']))) + sys::outjs(array('e' => 'Переданные данные периода неверны.')); + + // Проверка слот + if($aData['slots'] < $tarif['slots_min'] || $aData['slots'] > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданные данные слот неверны.')); + + // Определение суммы + if($cfg['settlement_period']) + { + // Цена аренды за расчетный период + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $start_point); + + $aData['time'] = games::define_period('buy', params::$aDayMonth); + }else + $sum = games::define_sum($tarif['discount'], $tarif['price'], $aData['slots'], $aData['time']); + + // Проверка промо-кода + $promo = games::define_promo( + $aData['promo'], + array( + 'tarif' => $aData['tarif'], + 'slots' => $aData['slots'], + 'time' => $aData['time'], + 'user' => $user['id'] + ), + $tarif['discount'], + $sum + ); + + $days = $aData['time']; // Кол-во дней аренды + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $days += $promo['days']; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort['samp']; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND (`address`="'.$ip.':'.$tarif['port_min'].'" OR `port`="'.$tarif['port_min'].'") LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + if(!$ip || !$port) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + + if($test) + $aData['time'] = games::time($start_point, $tarif['test']); + else + $aData['time'] = games::time($start_point, $days); + + $fix_one = 0; + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$aData['unit'].'" AND `tarif`="'.$aData['tarif'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $fix_one = 1; + $core = $cpu; + + break; + } + + if(!$core) + { + $sql->query('UPDATE `tarifs` set `show`="0" WHERE `id`="'.$aData['tarif'].'" LIMIT 1'); + + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + } + } + + $ram = $tarif['param_fix'] ? $aData['ram'] : $cfg['ram']['samp']*$aSDATA['slots']; + + // Массив данных + $aSDATA = array( + 'unit' => $aData['unit'], // идентификатор локации + 'tarif' => $aData['tarif'], // идентификатор тарифа + 'ram' => $ram, // значение ram + 'param_fix' => $tarif['param_fix'], // фиксированные параметры + 'pack' => $aData['pack'], // Выбранная сборка для установки + 'time' => $aData['time'], // Время аренды + 'days' => $days, // Число дней + 'sum' => $sum, // Сумма списания + 'test' => $test, // тестовый период + 'address' => $ip.':'.$port, // адрес игрового сервера + 'port' => $port, // порт игрового сервера + 'slots' => $aData['slots'], // Кол-во слот + 'autostop' => $tarif['autostop'], // Выключение при 0 онлайне + 'ftp' => $tarif['ftp'], // Использование ftp + 'plugins' => $tarif['plugins'], // Использование плагинов + 'console' => $tarif['console'], // Использование консоли + 'stats' => $tarif['stats'], // Использование графиков (ведение статистики) + 'copy' => $tarif['copy'], // Использование резервных копий + 'web' => $tarif['web'], // Использование доп услуг + 'plugins_install' => $tarif['plugins_install'], // Список установленных плагинов + 'hdd' => $tarif['hdd'], // Дисковое пространство + 'core_fix' => $core, // Выделенный поток + 'core_fix_one' => $fix_one, // Выделенный поток + 'promo' => $promo // Использование промо-кода + ); + + return $aSDATA; + } + + public static function install($aSDATA = array()) + { + global $cfg, $sql, $user, $start_point; + + include(LIB.'ssh.php'); + + // Массив данных локации (адрес,пароль) + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$aSDATA['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Массив данных тарифа (путь сборки,путь установки) + $sql->query('SELECT `path`, `install`, `hostname` FROM `tarifs` WHERE `id`="'.$aSDATA['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Получение идентификаторов игрового сервера + $sql->query('INSERT INTO `servers` set uid="1"'); + $id = $sql->id(); + $uid = $id+1000; + + // Директория сборки + $path = $tarif['path'].$aSDATA['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$uid; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -s /bin/false -d '.$install.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "cp -r '.$path.'/. .;' // Копирование файлов сборки для сервера + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 777 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['samp']].'"'); + + // Запись данных нового сервера + $sql->query('UPDATE `servers` set + `uid`="'.$uid.'", + `unit`="'.$aSDATA['unit'].'", + `tarif`="'.$aSDATA['tarif'].'", + `user`="'.$user['id'].'", + `address`="'.$aSDATA['address'].'", + `port`="'.$aSDATA['port'].'", + `game`="samp", + `slots`="'.$aSDATA['slots'].'", + `slots_start`="'.$aSDATA['slots'].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$aSDATA['pack'].'", + `plugins_use`="'.$aSDATA['plugins'].'", + `ftp_use`="'.$aSDATA['ftp'].'", + `console_use`="'.$aSDATA['console'].'", + `stats_use`="'.$aSDATA['stats'].'", + `copy_use`="'.$aSDATA['copy'].'", + `web_use`="'.$aSDATA['web'].'", + `vac`="1", + `hdd`="'.$aSDATA['hdd'].'", + `time`="'.$aSDATA['time'].'", + `date`="'.$start_point.'", + `test`="'.$aSDATA['test'].'", + `ram`="'.$aSDATA['ram'].'", + `map_start`="'.sys::passwd(8).'", + `core_fix`="'.$aSDATA['core_fix'].'", + `core_fix_one`="'.$aSDATA['core_fix_one'].'", + `autostop`="'.$aSDATA['autostop'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись установленных плагинов + if($aSDATA['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64djs($aSDATA['plugins_install']); + + if(isset($aPlugins[$aSDATA['pack']])) + { + $plugins = explode(',', $aPlugins[$aSDATA['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$aSDATA['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Запись получения тестового периода + if($aSDATA['test']) + { + $sql->query('INSERT INTO `tests` set `server`="'.$id.'", `unit`="'.$aSDATA['unit'].'", `game`="samp", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_test'), array('id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="0"'); + }else{ + // Реф. система + games::part($user['id'], $aSDATA['sum']); + + // Запись логов + if(!is_array($aSDATA['promo'])) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$aSDATA['time'].'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$aSDATA['promo']['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_server_promo'), array('days' => games::parse_day($aSDATA['days'], true), 'money' => $aSDATA['sum'], 'promo' => $aSDATA['promo']['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$aSDATA['sum'].'"'); + } + } + + return $id; + } + } +?> \ No newline at end of file diff --git a/system/library/games/samp/tarif.php b/system/library/games/samp/tarif.php new file mode 100644 index 0000000..a65da45 --- /dev/null +++ b/system/library/games/samp/tarif.php @@ -0,0 +1,179 @@ +get('extend', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif_name); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function extend_sp($server, $tarif, $sid) + { + global $cfg, $sql, $html, $start_point; + + tarifs::extend_address($server['game'], $sid); + + $sum = $tarif['slots'] ? $tarif['price'] : $tarif['price']*$server['slots']; + + $html->get('extend_sp', 'sections/servers/games/tarif'); + + if(isset($html->arr['extend_address'])) + { + $html->unit('extend_address', 1); + $html->set('extend_address', $html->arr['extend_address']); + }else + $html->unit('extend_address'); + + $html->set('id', $sid); + $html->set('time', sys::date('min', $server['time'])); + $html->set('date', $server['time'] > $start_point ? 'Сервер продлен до: '.date('d.m.Y', $server['time']) : 'Текущая дата: '.date('d.m.Y', $start_point)); + $html->set('options', ''.$options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('tarif', $tarif['name']); + $html->set('sum', $sum); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + return NULL; + } + + public static function plan() + { + return NULL; + } + + public static function unit($server, $unit_name, $tarif_name, $sid) + { + global $cfg, $sql, $html; + + if(!$cfg['change_unit'][$server['game']]) + return NULL; + + $tarifs = $sql->query('SELECT `unit` FROM `tarifs` WHERE `game`="'.$server['game'].'" AND `name`="'.$tarif_name.'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num($tarifs)) + return NULL; + + $units = 0; + + $options = ''; + + while($tarif = $sql->get($tarifs)) + { + $sql->query('SELECT `id`, `name` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + + $unit = $sql->get(); + + $options .= ''; + + $units+=1; + } + + if(!$units) + return NULL; + + $html->get('unit', 'sections/servers/games/tarif'); + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('info', ''); + $html->set('unit', $unit_name); + $html->set('tarif', $tarif_name); + + $html->pack('main'); + + return NULL; + } + + public static function unit_new($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + // Директория сборки + $path = $tarif['path'].$tarif['pack']; + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + // Пользователь сервера + $uS = 'server'.$server['uid']; + + $ssh->set('mkdir '.$install.';' // Создание директории + .'useradd -d '.$install.' -g servers -u '.$server['uid'].' '.$uS.';' // Создание пользователя сервера на локации + .'chown '.$uS.':1000 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u '.$uS.' screen -dmS i_'.$server['uid'].' cp -r '.$path.'/. .'); // Копирование файлов сборки для сервера + + $address = explode(':', $server['address']); + + $fix_one = $tarif['core_fix'] ? 1 : 0; + + // Обновление данных нового сервера + $sql->query('UPDATE `servers` set + `unit`="'.$tarif['unit'].'", + `tarif`="'.$tarif['id'].'", + `address`="'.$server['address'].'", + `port`="'.$address[1].'", + `status`="install", + `name`="'.$tarif['hostname'].'", + `pack`="'.$tarif['pack'].'", + `map_start`="'.$tarif['map'].'", + `hdd`="'.$tarif['hdd'].'", + `time`="'.$tarif['time'].'", + `autostop`="'.$tarif['autostop'].'", + `core_fix`="'.$tarif['core_fix'].'", + `core_fix_one`="'.$fix_one.'", + `reinstall`="'.$start_point.'" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Запись установленных плагинов + if($tarif['plugins']) + { + // Массив идентификаторов плагинов + $aPlugins = sys::b64js($tarif['plugins_install']); + + if(isset($aPlugins[$tarif['pack']])) + { + $plugins = explode(',', $aPlugins[$tarif['pack']]); + + foreach($plugins as $plugin) + if($plugin) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$server['id'].'", `plugin`="'.$plugin.'", `time`="'.$start_point.'"'); + } + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/games/scans.php b/system/library/games/scans.php new file mode 100644 index 0000000..5a94ea6 --- /dev/null +++ b/system/library/games/scans.php @@ -0,0 +1,237 @@ + 'hlds_', + 'cssold' => 'srcds_i686', + 'css' => 'srcds_', + 'csgo' => 'srcds_', + 'samp' => 'samp', + 'crmp' => 'samp', + 'mta' => 'mta', + 'mc' => 'java' + ); + + public static function resources($id) + { + global $cfg, $sql, $mcache; + + $nmch = 'server_resources_'.$id; + + if(is_array($mcache->get($nmch))) + return $mcache->get($nmch); + + $sql->query('SELECT `uid`, `unit`, `tarif`, `game`, `slots`, `slots_start`, `status`, `online`, `ram`, `hdd`, `hdd_use` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $server = $sql->get(); + + $resources = array( + 'usr' => 0, + 'cpu' => 0, + 'ram' => 0, + 'hdd' => $server['hdd_use'] + ); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `ram` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return $resources; + + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + return $resources; + + $resources['usr'] = ceil(100/$server['slots_start']*$server['online']); + $resources['usr'] = $resources['usr'] > 100 ? 100 : $resources['usr']; + + $cr = explode('|', $ssh->get('top -u '.$server['uid'].' -b -n 1 | grep '.(scans::$process[$server['game']]).' | sort | tail -1 | awk \'{print $9"|"$10}\'')); + + if(isset($cr[0])) + $resources['cpu'] = str_replace(',', '.', $cr[0]); + + $resources['cpu'] = $resources['cpu'] > 100 ? 100 : round($resources['cpu']); + + if(isset($cr[1])) + $resources['ram'] = str_replace(',', '.', $cr[1]); + + // ram на сервер + $ram = $server['ram'] ? $server['ram'] : $server['slots']*$cfg['ram'][$server['game']]; + + $resources['ram'] = $unit['ram']/100*$resources['ram']/($ram/100); + + $resources['ram'] = $resources['ram'] > 100 ? 100 : round($resources['ram']); + + $resources['hdd'] = ceil(sys::int($ssh->get('cd '.$tarif['install'].$server['uid'].' && du -ms'))/($server['hdd']/100)); + $resources['hdd'] = $resources['hdd'] > 100 ? 100 : $resources['hdd']; + + $sql->query('UPDATE `servers` set `ram_use`="'.$resources['ram'].'", `cpu_use`="'.$resources['cpu'].'", `hdd_use`="'.$resources['hdd'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->set($nmch, $resources, false, $cfg['mcache_server_resources']); + + return $resources; + } + + public static function status($id) + { + global $start_point, $cfg, $sql, $mcache; + + $nmch = 'server_status_'.$id; + + if($mcache->get($nmch)) + return 'mcache -> system_block_operation'; + + $mcache->set($nmch, true, false, $cfg['mcache_server_status']); + + $sql->query('SELECT `uid`, `unit`, `game`, `address`, `status`, `name`, `online`, `players`, `time`, `overdue`, `ftp`, `block` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + // Если аренда не закончилась, а сервер просрочен + if($server['time'] > $start_point && $server['status'] == 'overdue') + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> extend -> off'; + } + + // Если аренда закончилась и сервер просрочен длительное время + if($server['time'] < $start_point && $server['status'] == 'overdue' && ($server['overdue']+$cfg['server_delete']*86400) < $start_point) + { + $sql->query('UPDATE `servers` set `user`="-1" WHERE `id`="'.$id.'" LIMIT 1'); + + return 'server -> overdue -> delete'; + } + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + return 'unit error connect'; + + // Если аренда закончилась, а сервер не просрочен + if($server['time'] < $start_point && !in_array($server['status'], array('overdue', 'blocked'))) + { + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + if($server['ftp']) + $ssh->set("mysql -P ".$unit['sql_port']." -u".$unit['sql_login']." -p".$unit['sql_passwd']." --database ".$unit['sql_ftp']." -e \"DELETE FROM ftp WHERE user='".$server['uid']."'\""); + + $sql->query('UPDATE `servers` set `status`="overdue", `online`="0", `players`="", `ftp`="0", `overdue`="'.$start_point.'", `mail`="1" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'overdue', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'overdue', 'online' => 0)); + + return 'server -> overdue -> stoping'; + } + + switch($server['status']) + { + case 'working': case 'change': case 'start': case 'restart': + if(!sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off", `online`="0", `players`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> working -> off'; + } + + break; + + case 'off': + if(sys::int($ssh->get('ps aux | grep s_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="working" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'working', 'online' => $server['online'], 'players' => $server['players'])); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'working', 'online' => $server['online'])); + + return 'server -> off -> working'; + } + + break; + + case 'reinstall': + if(!sys::int($ssh->get('ps aux | grep r_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> reinstall -> end'; + } + + break; + + case 'update': + if(!sys::int($ssh->get('ps aux | grep u_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> update -> end'; + } + + break; + + case 'install': + if(!sys::int($ssh->get('ps aux | grep i_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> install -> end'; + } + + break; + + case 'recovery': + if(!sys::int($ssh->get('ps aux | grep rec_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + { + $sql->query('UPDATE `servers` set `status`="off" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + + return 'server -> recovery -> end'; + } + + break; + + case 'blocked': + if($server['block'] > $start_point) + break; + + $sql->query('UPDATE `servers` set `status`="off", `block`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::reset_mcache('server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0, 'players' => '')); + sys::reset_mcache('server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'off', 'online' => 0)); + } + + return 'server -> no change -> end scan'; + } + } +?> \ No newline at end of file diff --git a/system/library/games/services.php b/system/library/games/services.php new file mode 100644 index 0000000..4ab56b6 --- /dev/null +++ b/system/library/games/services.php @@ -0,0 +1,58 @@ +query('SELECT `id` FROM `units` WHERE `'.$game.'`="1" AND `show`="1" ORDER BY `sort` ASC'); + while($unit = $sql->get($units)) + { + $sql->query('SELECT `id` FROM `tarifs` WHERE `unit`="'.$unit['id'].'" AND `game`="'.$game.'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + continue; + else{ + $sel = $unit['id']; + break; + } + } + + return 'SELECT `id`, `test` FROM `units` WHERE `id`="'.$sel.'" LIMIT 1'; + } + + public static function units($game) + { + global $sql; + + $list = ''; + + $units = $sql->query('SELECT `id`, `name` FROM `units` WHERE `'.$game.'`="1" AND `show`="1" ORDER BY `sort` ASC'); + while($unit = $sql->get($units)) + { + $sql->query('SELECT `id` FROM `tarifs` WHERE `unit`="'.$unit['id'].'" AND `game`="'.$game.'" AND `show`="1" LIMIT 1'); + if($sql->num()) + $list .= ''; + } + + return $list; + } + + public static function tarifs($game, $unit) + { + global $sql; + + $list = ''; + + $sql->query('SELECT `id`, `name` FROM `tarifs` WHERE `game`="'.$game.'" AND `unit`="'.$unit.'" AND `show`="1" ORDER BY `sort` ASC'); + while($tarif = $sql->get()) + $list .= ''; + + return $list; + } + } +?> \ No newline at end of file diff --git a/system/library/games/tarifs.php b/system/library/games/tarifs.php new file mode 100644 index 0000000..bda7f67 --- /dev/null +++ b/system/library/games/tarifs.php @@ -0,0 +1,269 @@ +query('SELECT `aid`, `time` FROM `address_buy` WHERE `server`="'.$sid.'" LIMIT 1'); + if(!$sql->num()) + return NULL; + + $ip_buy = $sql->get(); + + $sql->query('SELECT `ip`, `price` FROM `address` WHERE `id`="'.$ip_buy['aid'].'" LIMIT 1'); + + $ip_buy = array_merge($ip_buy, $sql->get()); + + $html->get('extend_address', 'sections/servers/games/tarif'); + $html->set('address', $ip_buy['ip'].':'.params::$aDefPort[$game]); + $html->set('iptime', sys::date('max', $ip_buy['time'])); + $html->set('ipprice', $ip_buy['price']); + $html->set('cur', $cfg['currency']); + $html->pack('extend_address'); + + return NULL; + } + + public static function address($server, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $sUnit = $sql->get(); + + if(sys::first(explode(':', $sUnit['address'])) != sys::first(explode(':', $server['address']))) + { + if($cfg['buy_address'][$server['game']]) + tarif::address_extend($server['address'], $sid); + + return NULL; + } + + $options = ''; + + $sql->query('SELECT `id`, `ip`, `price` FROM `address` WHERE `unit`="'.$server['unit'].'" AND `buy`="0"'); + if(!$sql->num()) + return NULL; + + while($ip = $sql->get()) + $options .= ''; + + $html->get('address', 'sections/servers/games/tarif'); + if($cfg['buy_address'][$server['game']]){ + $html->unit('!mounth'); + $html->unit('mounth', 1); + }else{ + $html->unit('!mounth', 1); + $html->unit('mounth'); + } + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('address', $server['address']); + $html->set('cur', $cfg['currency']); + $html->pack('main'); + + return NULL; + } + + public static function address_extend($address, $sid) + { + global $cfg, $sql, $html; + + $sql->query('SELECT `aid`, `time` FROM `address_buy` WHERE `server`="'.$sid.'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $add = $sql->get(); + + $sql->query('SELECT `price` FROM `address` WHERE `id`="'.$add['aid'].'" LIMIT 1'); + + if(!$sql->num()) + return NULL; + + $add = array_merge($add, $sql->get()); + + $html->get('address_extend', 'sections/servers/games/tarif'); + $html->set('address', $address); + $html->set('time', sys::date('max', $add['time'])); + $html->set('price', $add['price']); + $html->set('cur', $cfg['currency']); + $html->pack('main'); + + return NULL; + } + + public static function address_add_sum($address, $server) + { + global $sql; + + if(!$address) + return 0; + + $ip = sys::first(explode(':', $server['address'])); + + $sql->query('SELECT `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if($address AND sys::first(explode(':', $unit['address'])) != $ip) + { + $sql->query('SELECT `price` FROM `address` WHERE `ip`="'.$ip.'" LIMIT 1'); + + if($sql->num()) + { + $add = $sql->get(); + + return $add['price']; + } + } + + return 0; + } + + public static function slots($server, $aSlots, $sid) + { + global $cfg, $html, $start_point; + + $options = ''; + + // С уменьшением (min ==> max) || закончился срок аренды + if(($cfg['change_slots'][$server['game']]['days'] AND $cfg['change_slots'][$server['game']]['down']) || $server['time'] < $start_point) + { + for($i = $aSlots['min']; $i <= $aSlots['max']; $i+=1) + $options .= ''; + + $html->get('slots', 'sections/servers/games/tarif'); + }else{ + if($server['slots'] == $aSlots['max']) + return NULL; + + $max = $aSlots['max']-$server['slots']; + + if($max < 1) + return NULL; + + for($i = 1; $i <= $max; $i+=1) + $options .= ''; + + $html->get('slots_buy', 'sections/servers/games/tarif'); + } + + $html->set('id', $sid); + $html->set('options', $options); + $html->set('slots', $server['slots']); + $html->set('cur', $cfg['currency']); + $html->pack('main'); + + return NULL; + } + + public static function price($plan) + { + $aPrice = explode(':', $plan); + + $check = $aPrice[0]; + + unset($aPrice[0]); + + if(!count($aPrice)) + return false; + + foreach($aPrice as $price) + if($check != $price) + return true; + + return false; + } + + public static function unit_old($tarif, $unit, $server, $mcache) + { + global $ssh, $sql, $user, $start_point; + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + // Убить процессы + $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;' + .'lsof -i@:'.$server['address'].' | awk '."'{print $2}'".' | xargs`; sudo -u server'.$server['uid'].' screen -wipe'); + + // Директория игрового сервера + $install = $tarif['install'].$server['uid']; + + $copys = 'screen -dmS r_copy_'.$server['uid'].' sh -c "'; + + $scopy = $sql->query('SELECT `id`, `name` FROM `copy` WHERE `server`="'.$server['id'].'"'); + while($copy = $sql->get($scopy)) + { + $copys .= 'rm /copy/'.$copy['name'].'.tar;'; + + $sql->query('DELETE FROM `copy` WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + + $copys .= '";'; + + $ssh->set($copys // Удаление резервных копий + .'screen -dmS r_'.$server['uid'].' rm -r '.$install.';' // Удаление директории сервера + .'userdel server'.$server['uid']); // Удаление пользователя сервера c локации + + // Удаление ftp доступа + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';' + .'DELETE FROM quotalimits WHERE name=\''.$server['uid'].'\';' + .'DELETE FROM quotatallies WHERE name=\''.$server['uid'].'\''; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + $sql->query('UPDATE `servers` SET `ftp`="0" WHERE `id`="'.$server['id'].'" LIMIT 1'); + + // Очистка правил FireWall + games::iptables($server['id'], 'remove', NULL, NULL, NULL, false, $ssh); + + // Удаление заданий из crontab + $sql->query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + $crons = $sql->query('SELECT `id`, `cron` FROM `crontab` WHERE `server`="'.$server['id'].'"'); + while($cron = $sql->get($crons)) + { + $ssh->set('echo "" >> /etc/crontab && cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab"); + $ssh->set('crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `crontab` WHERE `id`="'.$cron['id'].'" LIMIT 1'); + } + + // Удаление установок игрового сервера + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$server['id'].'" LIMIT 1'); + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$server['id'].'" LIMIT 1'); + + // Обновление данных выделенного адреса + $sql->query('SELECT `id`, `aid` FROM `address_buy` WHERE `server`="'.$server['id'].'" LIMIT 1'); + if($sql->num()) + { + $add = $sql->get(); + + $sql->query('UPDATE `address` set `buy`="0" WHERE `id`="'.$add['aid'].'" LIMIT 1'); + $sql->query('DELETE FROM `address_buy` WHERE `id`="'.$add['id'].'" LIMIT 1'); + } + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/geo.php b/system/library/geo.php new file mode 100644 index 0000000..443e85a --- /dev/null +++ b/system/library/geo.php @@ -0,0 +1,393 @@ +fh = fopen($db_file, 'rb'); + + $header = fread($this->fh, 40); + if(substr($header, 0, 3) != 'SxG') + die("Can't open {$db_file}\n"); + + $info = unpack('Cver/Ntime/Ctype/Ccharset/Cb_idx_len/nm_idx_len/nrange/Ndb_items/Cid_len/nmax_region/nmax_city/Nregion_size/Ncity_size/nmax_country/Ncountry_size/npack_size', substr($header, 3)); + + if($info['b_idx_len'] * $info['m_idx_len'] * $info['range'] * $info['db_items'] * $info['time'] * $info['id_len'] == 0) + die("Wrong file format {$db_file}\n"); + + $this->range = $info['range']; + $this->b_idx_len = $info['b_idx_len']; + $this->m_idx_len = $info['m_idx_len']; + $this->db_items = $info['db_items']; + $this->id_len = $info['id_len']; + $this->block_len = 3 + $this->id_len; + $this->max_region = $info['max_region']; + $this->max_city = $info['max_city']; + $this->max_country = $info['max_country']; + $this->country_size = $info['country_size']; + $this->batch_mode = $type & SXGEO_BATCH; + $this->memory_mode = $type & SXGEO_MEMORY; + $this->pack = $info['pack_size'] ? explode("\0", fread($this->fh, $info['pack_size'])) : ''; + $this->b_idx_str = fread($this->fh, $info['b_idx_len'] * 4); + $this->m_idx_str = fread($this->fh, $info['m_idx_len'] * 4); + $this->db_begin = ftell($this->fh); + + if($this->batch_mode) + { + $this->b_idx_arr = array_values(unpack("N*", $this->b_idx_str)); + + unset($this->b_idx_str); + + $this->m_idx_arr = str_split($this->m_idx_str, 4); + + unset($this->m_idx_str); + } + + if($this->memory_mode) + { + $this->db = fread($this->fh, $this->db_items * $this->block_len); + $this->regions_db = $info['region_size'] > 0 ? fread($this->fh, $info['region_size']) : ''; + $this->cities_db = $info['city_size'] > 0 ? fread($this->fh, $info['city_size']) : ''; + } + + $this->info = $info; + + $this->info['regions_begin'] = $this->db_begin + $this->db_items * $this->block_len; + $this->info['cities_begin'] = $this->info['regions_begin'] + $info['region_size']; + } + + protected function search_idx($ipn, $min, $max) + { + if($this->batch_mode) + { + while($max - $min > 8) + { + $offset = ($min + $max) >> 1; + + if($ipn > $this->m_idx_arr[$offset]) + $min = $offset; + else + $max = $offset; + } + + while ($ipn > $this->m_idx_arr[$min] && $min++ < $max){}; + }else{ + while($max - $min > 8) + { + $offset = ($min + $max) >> 1; + + if($ipn > substr($this->m_idx_str, $offset*4, 4)) + $min = $offset; + else + $max = $offset; + } + + while($ipn > substr($this->m_idx_str, $min*4, 4) && $min++ < $max){}; + } + + return $min; + } + + protected function search_db($str, $ipn, $min, $max) + { + if($max - $min > 1) + { + $ipn = substr($ipn, 1); + + while($max - $min > 8) + { + $offset = ($min + $max) >> 1; + if($ipn > substr($str, $offset * $this->block_len, 3)) + $min = $offset; + else + $max = $offset; + } + + while($ipn >= substr($str, $min * $this->block_len, 3) && ++$min < $max){}; + }else + $min++; + + return hexdec(bin2hex(substr($str, $min * $this->block_len - $this->id_len, $this->id_len))); + } + + public function get_num($ip) + { + $ip1n = (int)$ip; + + if($ip1n == 0 || $ip1n == 10 || $ip1n == 127 || $ip1n >= $this->b_idx_len || false === ($ipn = ip2long($ip))) + return false; + + $ipn = pack('N', $ipn); + $this->ip1c = chr($ip1n); + + if($this->batch_mode) + $blocks = array('min' => $this->b_idx_arr[$ip1n-1], 'max' => $this->b_idx_arr[$ip1n]); + else + $blocks = unpack("Nmin/Nmax", substr($this->b_idx_str, ($ip1n - 1) * 4, 8)); + + if($blocks['max'] - $blocks['min'] > $this->range) + { + $part = $this->search_idx($ipn, floor($blocks['min'] / $this->range), floor($blocks['max'] / $this->range)-1); + + $min = $part > 0 ? $part * $this->range : 0; + $max = $part > $this->m_idx_len ? $this->db_items : ($part+1) * $this->range; + + if($min < $blocks['min']) + $min = $blocks['min']; + + if($max > $blocks['max']) + $max = $blocks['max']; + }else{ + $min = $blocks['min']; + $max = $blocks['max']; + } + + $len = $max - $min; + + if($this->memory_mode) + return $this->search_db($this->db, $ipn, $min, $max); + + else{ + fseek($this->fh, $this->db_begin + $min * $this->block_len); + + return $this->search_db(fread($this->fh, $len * $this->block_len), $ipn, 0, $len); + } + } + + protected function readData($seek, $max, $type) + { + $raw = ''; + if($seek && $max) + { + if ($this->memory_mode) + $raw = substr($type == 1 ? $this->regions_db : $this->cities_db, $seek, $max); + else{ + fseek($this->fh, $this->info[$type == 1 ? 'regions_begin' : 'cities_begin'] + $seek); + + $raw = fread($this->fh, $max); + } + } + + return $this->unpack($this->pack[$type], $raw); + } + + protected function parseCity($seek, $full = false) + { + if(!$this->pack) + return false; + + $only_country = false; + + if($seek < $this->country_size) + { + $country = $this->readData($seek, $this->max_country, 0); + $city = $this->unpack($this->pack[2]); + $city['lat'] = $country['lat']; + $city['lon'] = $country['lon']; + $only_country = true; + }else{ + $city = $this->readData($seek, $this->max_city, 2); + $country = array('id' => $city['country_id'], 'iso' => $this->id2iso[$city['country_id']]); + unset($city['country_id']); + } + + if($full){ + $region = $this->readData($city['region_seek'], $this->max_region, 1); + + if(!$only_country) + $country = $this->readData($region['country_seek'], $this->max_country, 0); + + unset($city['region_seek']); + unset($region['country_seek']); + + return array('city' => $city, 'region' => $region, 'country' => $country); + }else{ + unset($city['region_seek']); + + return array('city' => $city, 'country' => array('id' => $country['id'], 'iso' => $country['iso'])); + } + } + + protected function unpack($pack, $item = '') + { + $unpacked = array(); + $empty = empty($item); + $pack = explode('/', $pack); + $pos = 0; + + foreach($pack AS $p) + { + list($type, $name) = explode(':', $p); + + $type0 = $type{0}; + + if($empty) + { + $unpacked[$name] = $type0 == 'b' || $type0 == 'c' ? '' : 0; + + continue; + } + + switch($type0) + { + case 't': + case 'T': $l = 1; break; + case 's': + case 'n': + case 'S': $l = 2; break; + case 'm': + case 'M': $l = 3; break; + case 'd': $l = 8; break; + case 'c': $l = (int)substr($type, 1); break; + case 'b': $l = strpos($item, "\0", $pos)-$pos; break; + default: $l = 4; + } + + $val = substr($item, $pos, $l); + + switch($type0) + { + case 't': $v = unpack('c', $val); break; + case 'T': $v = unpack('C', $val); break; + case 's': $v = unpack('s', $val); break; + case 'S': $v = unpack('S', $val); break; + case 'm': $v = unpack('l', $val . (ord($val{2}) >> 7 ? "\xff" : "\0")); break; + case 'M': $v = unpack('L', $val . "\0"); break; + case 'i': $v = unpack('l', $val); break; + case 'I': $v = unpack('L', $val); break; + case 'f': $v = unpack('f', $val); break; + case 'd': $v = unpack('d', $val); break; + + case 'n': $v = current(unpack('s', $val)) / pow(10, $type{1}); break; + case 'N': $v = current(unpack('l', $val)) / pow(10, $type{1}); break; + + case 'c': $v = rtrim($val, ' '); break; + case 'b': $v = $val; $l++; break; + } + + $pos += $l; + $unpacked[$name] = is_array($v) ? current($v) : $v; + } + + return $unpacked; + } + + public function get($ip) + { + return $this->max_city ? $this->getCity($ip) : $this->getCountry($ip); + } + + public function getCountry($ip) + { + if($this->max_city) + { + $tmp = $this->parseCity($this->get_num($ip)); + + return $tmp['country']['iso']; + }else + return $this->id2iso[$this->get_num($ip)]; + } + + public function getCountryId($ip) + { + if($this->max_city) + { + $tmp = $this->parseCity($this->get_num($ip)); + + return $tmp['country']['id']; + }else + return $this->get_num($ip); + } + + public function getCity($ip) + { + $seek = $this->get_num($ip); + + return $seek ? $this->parseCity($seek) : false; + } + + public function getCityFull($ip) + { + $seek = $this->get_num($ip); + + return $seek ? $this->parseCity($seek, 1) : false; + } + + public function about() + { + $charset = array('utf-8', 'latin1', 'cp1251'); + $types = array('n/a', 'SxGeo Country', 'SxGeo City RU', 'SxGeo City EN', 'SxGeo City', 'SxGeo City Max RU', 'SxGeo City Max EN', 'SxGeo City Max'); + + return array( + 'Created' => date('Y.m.d', $this->info['time']), + 'Timestamp' => $this->info['time'], + 'Charset' => $charset[$this->info['charset']], + 'Type' => $types[$this->info['type']], + 'Byte Index' => $this->b_idx_len, + 'Main Index' => $this->m_idx_len, + 'Blocks In Index Item' => $this->range, + 'IP Blocks' => $this->db_items, + 'Block Size' => $this->block_len, + + 'City' => array( + 'Max Length' => $this->max_city, + 'Total Size' => $this->info['city_size'], + ), + + 'Region' => array( + 'Max Length' => $this->max_region, + 'Total Size' => $this->info['region_size'], + ), + + 'Country' => array( + 'Max Length' => $this->max_country, + 'Total Size' => $this->info['country_size'], + ), + ); + } + } +?> \ No newline at end of file diff --git a/system/library/help.php b/system/library/help.php new file mode 100644 index 0000000..d94f78d --- /dev/null +++ b/system/library/help.php @@ -0,0 +1,100 @@ + $str) + { + $check = str_replace(' ', '', $str); + + if(isset($aStr[$line+1]) AND ($check == '' AND str_replace(' ', '', $aStr[$line+1]) == '')) + continue; + else{ + $etext .= rtrim(str_replace("\t", ' ', $str))."\n"; + + continue; + } + + if($check != '') + $etext .= rtrim(str_replace("\t", ' ', $str))."\n"; + } + + $str_search = array( + "#\\\n#is", + "#\[spoiler\](.+?)\[\/spoiler\]#is", + "#\[sp\](.+?)\[\/sp\]#is", + "#\[b\](.+?)\[\/b\]#is", + "#\[u\](.+?)\[\/u\]#is", + "#\[code\](.+?)\[\/code\]#is", + "#\[quote\](.+?)\[\/quote\]#is", + "#\[url=(.+?)\](.+?)\[\/url\]#is", + "#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is" + ); + + $str_replace = array( + "
    ", + "

    Посмотреть содержимое
    \\1
    ", + "
    Посмотреть содержимое
    \\1
    ", + "\\1", + "\\1", + "
    Посмотреть содержимое
    \\1
    ", + "

    \\1

    ", + "\\2", + " \\2" + ); + + return preg_replace($str_search, $str_replace, $etext); + } + + public static function ago($time, $brackets = false) + { + global $start_point; + + $diff = $start_point-$time; + + if($diff < 0) + return ''; + + if(!$diff) + $diff = 1; + + $seconds = array('секунду', 'секунды', 'секунд'); + $minutes = array('минуту', 'минуты', 'минут'); + $hours = array('час', 'часа', 'часов'); + $days = array('день', 'дня', 'дней'); + $weeks = array('неделю', 'недели', 'недель'); + $months = array('месяц', 'месяца', 'месяцев'); + $years = array('год', 'года', 'лет'); + + $phrase = array($seconds, $minutes, $hours, $days, $weeks, $months, $years); + $length = array(1, 60, 3600, 86400, 604800, 2630880, 31570560); + + for($i = 6; ($i >= 0) AND (($no = $diff/$length[$i]) <= 1); $i-=1); + + if($i < 0) + $i = 0; + + $_time = $start_point-($diff % $length[$i]); + $no = ceil($no); + + if($brackets) + return '('.$no.' '.help::parse_ago($no, $phrase[$i]).' назад)'; + + return $no.' '.help::parse_ago($no, $phrase[$i]).' назад'; + } + + private static function parse_ago($number, $titles) + { + $cases = array(2, 0, 1, 1, 1, 2); + + return $titles[($number % 100 > 4 AND $number % 100 < 20 ) ? 2 : $cases[min($number % 10, 5)]]; + } + } +?> \ No newline at end of file diff --git a/system/library/html.php b/system/library/html.php new file mode 100644 index 0000000..de631fc --- /dev/null +++ b/system/library/html.php @@ -0,0 +1,173 @@ +data['['.$name.']'] = $var; + + if($unset) + unset($this->arr[$name]); + + return NULL; + } + + public function unit($name, $var = false, $mirror = false) + { + $block = str_replace($name, "'\\|".$name."\\|(.*?)\\|_".$name."\\|'si", $name); + + $var = $var ? '\\1' : ''; + + $this->unitblock[$block] = $var; + + if($mirror) + { + $block = str_replace($name, "'\\|!".$name."\\|(.*?)\\|_!".$name."\\|'si", $name); + + $var = !$var ? '\\1' : ''; + + $this->unitblock[$block] = $var; + } + + return NULL; + } + + public function nav($name, $link = false) + { + $this->get('nav'); + if($link) + { + $this->set('link', $link); + $this->unit('link', 1, 1); + }else + $this->unit('link', 0, 1); + $this->set('name', $name); + $this->pack('nav'); + + return NULL; + } + + public function get($name, $path = '') + { + global $device, $cfg; + + $path_root = $device == '!mobile' ? '' : 'megp/'; + + $path = $path_root.$path; + + if($path != '') + $name = str_replace('//', '/', $path.'/'.$name); + + if(!file_exists($this->dir.'/'.$name.'.html')) + { + $route = explode('/', $name); + $namefile = end($route); + $dir = $this->dir.str_replace($namefile, '', $name); + + die('Error: html file '.$namefile.'.html not found in: '.$dir.''); + } + + $this->template = file_get_contents($this->dir.'/'.$name.'.html'); + $this->select_template = $this->template; + + return NULL; + } + + private function delete() + { + unset($this->data); + unset($this->unitblock); + + $this->select_template = $this->template; + + return NULL; + } + + public function pack($compile) + { + if(isset($this->unitblock)) + { + $find_preg = array(); + $replace_preg = array(); + + foreach($this->unitblock as $key_find => $key_replace) + { + $find_preg[] = $key_find; + $replace_preg[] = $key_replace; + } + + $this->select_template = preg_replace($find_preg, $replace_preg, $this->select_template); + } + + $find = array(); + $replace = array(); + + if(isset($this->data)) + { + foreach($this->data as $key_find => $key_replace) + { + $find[] = $key_find; + $replace[] = $key_replace; + } + } + + $this->select_template = str_replace($find, $replace, $this->select_template); + + if(isset($this->arr[$compile])) + $this->arr[$compile] .= $this->select_template; + else + $this->arr[$compile] = $this->select_template; + + $this->delete(); + + return NULL; + } + + public function upd($old = array(), $new = array(), $name) + { + $this->arr[$name] = str_replace($old, $new, $this->arr[$name]); + + return NULL; + } + + public function unitall($arr = array(), $name, $var = false, $mirror = false) + { + $block = str_replace($name, "'\\|".$name."\\|(.*?)\\|_".$name."\\|'si", $name); + + $var = $var ? '\\1' : ''; + + $this->unitblock[$block] = $var; + + if($mirror) + { + $block = str_replace($name, "'\\|!".$name."\\|(.*?)\\|_!".$name."\\|'si", $name); + + $var = !$var ? '\\1' : ''; + + $this->unitblock[$block] = $var; + } + + if(count($this->unitblock)) + { + foreach($this->unitblock as $key_find => $key_replace) + { + $find_preg[] = $key_find; + $replace_preg[] = $key_replace; + } + + $this->arr[$arr] = preg_replace($find_preg, $replace_preg, $this->arr[$arr]); + } + + return NULL; + } + } + + $html = new html; +?> \ No newline at end of file diff --git a/system/library/megp.php b/system/library/megp.php new file mode 100644 index 0000000..697954c --- /dev/null +++ b/system/library/megp.php @@ -0,0 +1,744 @@ + array('matches' => array( + 'application/x-obml2d', + 'application/vnd.rim.html', + 'text/vnd.wap.wml', + 'application/vnd.wap.xhtml+xml' + )), + 'HTTP_X_WAP_PROFILE' => null, + 'HTTP_X_WAP_CLIENTID' => null, + 'HTTP_WAP_CONNECTION' => null, + 'HTTP_PROFILE' => null, + 'HTTP_X_OPERAMINI_PHONE_UA' => null, + 'HTTP_X_NOKIA_GATEWAY_ID' => null, + 'HTTP_X_ORANGE_ID' => null, + 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null, + 'HTTP_X_HUAWEI_USERID' => null, + 'HTTP_UA_OS' => null, + 'HTTP_X_MOBILE_GATEWAY' => null, + 'HTTP_X_ATT_DEVICEID' => null, + 'HTTP_UA_CPU' => array('matches' => array('ARM')), + ); + + protected static $phoneDevices = array( + 'iPhone' => '\biPhone\b|\biPod\b', + 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+', + 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m', + 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6', + 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b', + 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b', + 'Samsung' => '\bSamsung\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C', + 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)', + 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533', + 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile', + 'NokiaLumia' => 'Lumia [0-9]{3,4}', + 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b', + 'Palm' => 'PalmSource|Palm', + 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', + 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790', + 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250', + 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM', + 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)', + 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b', + 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q', + 'Alcatel' => 'Alcatel', + 'Nintendo' => 'Nintendo 3DS', + 'Amoi' => 'Amoi', + 'INQ' => 'INQ', + 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser', + ); + + protected static $tabletDevices = array( + 'iPad' => 'iPad|iPad.*Mobile', + 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)', + 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone. + 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)', + 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)', + 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10', + 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z', + 'BlackBerryTablet' => 'PlayBook|RIM Tablet', + 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410', + 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', + 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2', + 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30', + 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO', + 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b', + 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b', + 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002', + 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)', + 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7', + 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b', + 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB', + 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2', + 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004', + 'IRUTablet' => 'M702pro', + 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b', + 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)', + 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)', + 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b', + 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark', + 'NokiaLumiaTablet' => 'Lumia 2520', + 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31', + 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b', + 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT', + 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010', + 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10', + 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b', + 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)', + 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A', + 'FlyTablet' => 'IQ310|Fly Vision', + 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus', + 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim', + 'NecTablet' => '\bN-06D|\bN-08D', + 'PantechTablet' => 'Pantech.*P4100', + 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)', + 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b', + 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900', + 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA', + 'NabiTablet' => 'Android.*\bNabi', + 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build', + 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b', + 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE', + 'PlaystationTablet' => 'Playstation.*(Portable|Vita)', + 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab', + 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b', + 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ', + 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1', + 'GalapadTablet' => 'Android.*\bG1\b', + 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b', + 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b', + 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide', + 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b', + 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026', + 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503', + 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G + 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10', + 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)', + 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync', + 'DPSTablet' => 'DPS Dream 9|DPS Dual 7', + 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10', + 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989', + 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b', + 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan', + 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042', + 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003', + 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b', + 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1', + 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab', + 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497', + 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2', + 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711', + 'iMobileTablet' => 'i-mobile i-note', + 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine', + 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b', + 'AMPETablet' => 'Android.* A78 ', + 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)', + 'TecnoTablet' => 'TECNO P9', + 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b', + 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)', + 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10', + 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151', + 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a', + 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10', + 'CaptivaTablet' => 'CAPTIVA PAD', + 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S', + 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi', + 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+', + 'JaytechTablet' => 'TPC-PA762', + 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010', + 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b', + 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b', + 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b', + 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712', + 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010', + 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b', + 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b', + 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b', + 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One', + 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI', + 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100', + 'UbislateTablet' => 'UbiSlate[\s]?7C', + 'PocketBookTablet' => 'Pocketbook', + 'KocasoTablet' => '\b(TB-1207)\b', + 'HisenseTablet' => '\b(F5281|E2371)\b', + 'Hudl' => 'Hudl HT7S3|Hudl 2', + 'TelstraTablet' => 'T-Hub2', + 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b' + ); + + protected static $operatingSystems = array( + 'AndroidOS' => 'Android', + 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os', + 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino', + 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b', + 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;', + 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;', + 'iOS' => '\biPhone.*Mobile|\biPod|\biPad', + 'MeeGoOS' => 'MeeGo', + 'MaemoOS' => 'Maemo', + 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', + 'webOS' => 'webOS|hpwOS', + 'badaOS' => '\bBada\b', + 'BREWOS' => 'BREW' + ); + + protected static $browsers = array( + 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?', + 'Dolfin' => '\bDolfin\b', + 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+', + 'Skyfire' => 'Skyfire', + 'Edge' => 'Mobile Safari/[.0-9]* Edge', + 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+ + 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS', + 'Bolt' => 'bolt', + 'TeaShark' => 'teashark', + 'Blazer' => 'Blazer', + 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari', + 'UCBrowser' => 'UC.*Browser|UCWEB', + 'baiduboxapp' => 'baiduboxapp', + 'baidubrowser' => 'baidubrowser', + 'DiigoBrowser' => 'DiigoBrowser', + 'Puffin' => 'Puffin', + 'Mercury' => '\bMercury\b', + 'ObigoBrowser' => 'Obigo', + 'NetFront' => 'NF-Browser', + 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger', + 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon' + ); + + protected static $utilities = array( + 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom', + 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2', + 'DesktopMode' => 'WPDesktop', + 'TV' => 'SonyDTV|HbbTV', // experimental + 'WebKit' => '(webkit)[ /]([\w.]+)', + 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b', + 'Watch' => 'SM-V700' + ); + + protected static $uaHttpHeaders = array( + 'HTTP_USER_AGENT', + 'HTTP_X_OPERAMINI_PHONE_UA', + 'HTTP_X_DEVICE_USER_AGENT', + 'HTTP_X_ORIGINAL_USER_AGENT', + 'HTTP_X_SKYFIRE_PHONE', + 'HTTP_X_BOLT_PHONE_UA', + 'HTTP_DEVICE_STOCK_UA', + 'HTTP_X_UCBROWSER_DEVICE_UA' + ); + + protected static $properties = array( + 'Mobile' => 'Mobile/[VER]', + 'Build' => 'Build/[VER]', + 'Version' => 'Version/[VER]', + 'VendorID' => 'VendorID/[VER]', + 'iPad' => 'iPad.*CPU[a-z ]+[VER]', + 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]', + 'iPod' => 'iPod.*CPU[a-z ]+[VER]', + 'Kindle' => 'Kindle/[VER]', + 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'), + 'Coast' => array('Coast/[VER]'), + 'Dolfin' => 'Dolfin/[VER]', + 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'), + 'Fennec' => 'Fennec/[VER]', + 'Edge' => 'Edge/[VER]', + 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'), + 'NetFront' => 'NetFront/[VER]', + 'NokiaBrowser' => 'NokiaBrowser/[VER]', + 'Opera' => array('OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]'), + 'Opera Mini' => 'Opera Mini/[VER]', + 'Opera Mobi' => 'Version/[VER]', + 'UC Browser' => 'UC Browser[VER]', + 'MQQBrowser' => 'MQQBrowser/[VER]', + 'MicroMessenger' => 'MicroMessenger/[VER]', + 'baiduboxapp' => 'baiduboxapp/[VER]', + 'baidubrowser' => 'baidubrowser/[VER]', + 'SamsungBrowser' => 'SamsungBrowser/[VER]', + 'Iron' => 'Iron/[VER]', + 'Safari' => array('Version/[VER]', 'Safari/[VER]'), + 'Skyfire' => 'Skyfire/[VER]', + 'Tizen' => 'Tizen/[VER]', + 'Webkit' => 'webkit[ /][VER]', + 'PaleMoon' => 'PaleMoon/[VER]', + 'Gecko' => 'Gecko/[VER]', + 'Trident' => 'Trident/[VER]', + 'Presto' => 'Presto/[VER]', + 'Goanna' => 'Goanna/[VER]', + 'iOS' => ' \bi?OS\b [VER][ ;]{1}', + 'Android' => 'Android [VER]', + 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'), + 'BREW' => 'BREW [VER]', + 'Java' => 'Java/[VER]', + 'Windows Phone OS' => array('Windows Phone OS [VER]', 'Windows Phone [VER]'), + 'Windows Phone' => 'Windows Phone [VER]', + 'Windows CE' => 'Windows CE/[VER]', + 'Windows NT' => 'Windows NT [VER]', + 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'), + 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];') + ); + + public function __construct(array $headers = null, $userAgent = null) + { + $this->setHttpHeaders($headers); + $this->setUserAgent($userAgent); + } + + public static function getScriptVersion() + { + return self::VERSION; + } + + public function setHttpHeaders($httpHeaders = null) + { + if(!is_array($httpHeaders) || !count($httpHeaders)) + $httpHeaders = $_SERVER; + + $this->httpHeaders = array(); + + foreach($httpHeaders as $key => $value) + { + if(substr($key, 0, 5) === 'HTTP_') + $this->httpHeaders[$key] = $value; + } + + $this->setCfHeaders($httpHeaders); + } + + public function getHttpHeaders() + { + return $this->httpHeaders; + } + + public function getHttpHeader($header) + { + if(strpos($header, '_') === false) + { + $header = str_replace('-', '_', $header); + $header = strtoupper($header); + } + + $altHeader = 'HTTP_' . $header; + + if(isset($this->httpHeaders[$header])) + return $this->httpHeaders[$header]; + elseif(isset($this->httpHeaders[$altHeader])) + return $this->httpHeaders[$altHeader]; + + return null; + } + + public function getMobileHeaders() + { + return self::$mobileHeaders; + } + + public function getUaHttpHeaders() + { + return self::$uaHttpHeaders; + } + + public function setCfHeaders($cfHeaders = null) + { + if(!is_array($cfHeaders) || !count($cfHeaders)) + $cfHeaders = $_SERVER; + + $this->cloudfrontHeaders = array(); + $response = false; + + foreach($cfHeaders as $key => $value) + { + if(substr(strtolower($key), 0, 16) === 'http_cloudfront_') + { + $this->cloudfrontHeaders[strtoupper($key)] = $value; + $response = true; + } + } + + return $response; + } + + public function getCfHeaders() + { + return $this->cloudfrontHeaders; + } + + public function setUserAgent($userAgent = null) + { + $this->cache = array(); + + if(false === empty($userAgent)) + return $this->userAgent = $userAgent; + else{ + $this->userAgent = null; + + foreach($this->getUaHttpHeaders() as $altHeader) + if(false === empty($this->httpHeaders[$altHeader])) + $this->userAgent .= $this->httpHeaders[$altHeader].' '; + + if(!empty($this->userAgent)) + return $this->userAgent = trim($this->userAgent); + } + + if(count($this->getCfHeaders()) > 0) + return $this->userAgent = 'Amazon CloudFront'; + + return $this->userAgent = null; + } + + public function getUserAgent() + { + return $this->userAgent; + } + + public function setDetectionType($type = null) + { + if($type === null) + $type = self::DETECTION_TYPE_MOBILE; + + if($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) + return; + + $this->detectionType = $type; + } + + public function getMatchingRegex() + { + return $this->matchingRegex; + } + + public function getMatchesArray() + { + return $this->matchesArray; + } + + public static function getPhoneDevices() + { + return self::$phoneDevices; + } + + public static function getTabletDevices() + { + return self::$tabletDevices; + } + + public static function getUserAgents() + { + return self::getBrowsers(); + } + + public static function getBrowsers() + { + return self::$browsers; + } + + public static function getUtilities() + { + return self::$utilities; + } + + public static function getMobileDetectionRules() + { + static $rules; + + if(!$rules) + { + $rules = array_merge( + self::$phoneDevices, + self::$tabletDevices, + self::$operatingSystems, + self::$browsers + ); + } + + return $rules; + } + + public function getMobileDetectionRulesExtended() + { + static $rules; + + if(!$rules) + { + $rules = array_merge( + self::$phoneDevices, + self::$tabletDevices, + self::$operatingSystems, + self::$browsers, + self::$utilities + ); + } + + return $rules; + } + + public function getRules() + { + if($this->detectionType == self::DETECTION_TYPE_EXTENDED) + return self::getMobileDetectionRulesExtended(); + + return self::getMobileDetectionRules(); + } + + public static function getOperatingSystems() + { + return self::$operatingSystems; + } + + public function checkHttpHeadersForMobile() + { + foreach($this->getMobileHeaders() as $mobileHeader => $matchType) + { + if(isset($this->httpHeaders[$mobileHeader])) + { + if(is_array($matchType['matches'])) + { + foreach ($matchType['matches'] as $_match) + if(strpos($this->httpHeaders[$mobileHeader], $_match) !== false) + return true; + + return false; + }else + return true; + } + } + + return false; + } + + public function __call($name, $arguments) + { + if(substr($name, 0, 2) !== 'is') + throw new BadMethodCallException('No such method exists: '.$name); + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + $key = substr($name, 2); + + return $this->matchUAAgainstKey($key); + } + + protected function matchDetectionRulesAgainstUA($userAgent = null) + { + foreach($this->getRules() as $_regex) + { + if(empty($_regex)) + continue; + + if($this->match($_regex, $userAgent)) + return true; + } + + return false; + } + + protected function matchUAAgainstKey($key) + { + $key = strtolower($key); + + if(false === isset($this->cache[$key])) + { + $_rules = array_change_key_case($this->getRules()); + + if(false === empty($_rules[$key])) + $this->cache[$key] = $this->match($_rules[$key]); + + if(false === isset($this->cache[$key])) + $this->cache[$key] = false; + } + + return $this->cache[$key]; + } + + public function isMobile($userAgent = null, $httpHeaders = null) + { + if($httpHeaders) + $this->setHttpHeaders($httpHeaders); + + if($userAgent) + $this->setUserAgent($userAgent); + + if($this->getUserAgent() === 'Amazon CloudFront') + { + $cfHeaders = $this->getCfHeaders(); + + if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') + return true; + } + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + + if($this->checkHttpHeadersForMobile()) + return true; + + return $this->matchDetectionRulesAgainstUA(); + } + + public function isTablet($userAgent = null, $httpHeaders = null) + { + if($this->getUserAgent() === 'Amazon CloudFront') + { + $cfHeaders = $this->getCfHeaders(); + + if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') + return true; + } + + $this->setDetectionType(self::DETECTION_TYPE_MOBILE); + + foreach(self::$tabletDevices as $_regex) + if($this->match($_regex, $userAgent)) + return true; + + return false; + } + + public function is($key, $userAgent = null, $httpHeaders = null) + { + if($httpHeaders) + $this->setHttpHeaders($httpHeaders); + + if($userAgent) + $this->setUserAgent($userAgent); + + $this->setDetectionType(self::DETECTION_TYPE_EXTENDED); + + return $this->matchUAAgainstKey($key); + } + + public function match($regex, $userAgent = null) + { + $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches); + + if($match) + { + $this->matchingRegex = $regex; + $this->matchesArray = $matches; + } + + return $match; + } + + public static function getProperties() + { + return self::$properties; + } + + public function prepareVersionNo($ver) + { + $ver = str_replace(array('_', ' ', '/'), '.', $ver); + $arrVer = explode('.', $ver, 2); + + if(isset($arrVer[1])) + $arrVer[1] = @str_replace('.', '', $arrVer[1]); + + return (float) implode('.', $arrVer); + } + + public function version($propertyName, $type = self::VERSION_TYPE_STRING) + { + if(empty($propertyName)) + return false; + + if($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) + $type = self::VERSION_TYPE_STRING; + + $properties = self::getProperties(); + + if(true === isset($properties[$propertyName])) + { + $properties[$propertyName] = (array) $properties[$propertyName]; + + foreach($properties[$propertyName] as $propertyMatchString) + { + $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString); + preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match); + + if(false === empty($match[1])) + { + $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]); + + return $version; + } + } + } + + return false; + } + + public function mobileGrade() + { + $isMobile = $this->isMobile(); + if($this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 || + ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) || + $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 || + $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 || + $this->match('Playbook.*Tablet') || + ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) || + $this->match('hp.*TouchPad') || + ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) || + ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) || + ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || + ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) || + $this->is('MeeGoOS') || + $this->is('Tizen') || + $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 || + ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || + ( $this->match('Kindle Fire') || + $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) || + $this->is('AndroidOS') && $this->is('NookTablet') || + $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile || + $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile || + $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile || + $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile || + $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile) + return self::MOBILE_GRADE_A; + + if($this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 || + $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 || + ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 && + ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) || + $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') || + $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')) + return self::MOBILE_GRADE_B; + + if($this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 || + $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 || + $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 || + $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 || + $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 || + $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile) + return self::MOBILE_GRADE_C; + + return self::MOBILE_GRADE_C; + } + } + + $megp = new megp; +?> \ No newline at end of file diff --git a/system/library/smtp.php b/system/library/smtp.php new file mode 100644 index 0000000..d2a3361 --- /dev/null +++ b/system/library/smtp.php @@ -0,0 +1,134 @@ +smtp_username = $smtp_username; + $this->smtp_password = $smtp_password; + $this->smtp_host = $smtp_host; + $this->smtp_from = $smtp_from; + $this->smtp_port = $smtp_port; + $this->smtp_charset = $smtp_charset; + } + + function send($mailTo, $subject, $message, $headers) + { + global $cfg; + + $contentMail = 'Date: '.date('D, d M Y H:i:s')." UT\r\n"; + $contentMail .= 'Subject: =?'.$this->smtp_charset.'?B?'.base64_encode($subject)."=?=\r\n"; + $contentMail .= $headers."\r\n"; + $contentMail .= $message."\r\n"; + + try + { + if(!$socket = @fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30)) + throw new Exception($errorNumber.'.'.$errorDescription); + + if(!$this->_parseServer($socket, '220')) + throw new Exception('Connection error'); + + $server_name = $cfg['url']; + + fputs($socket, 'HELO '.$server_name."\r\n"); + + if(!$this->_parseServer($socket, '250')) + { + fclose($socket); + throw new Exception('Error of command sending: HELO'); + } + + fputs($socket, 'AUTH LOGIN'."\r\n"); + + if(!$this->_parseServer($socket, '334')) + { + fclose($socket); + throw new Exception('Autorization error'); + } + + fputs($socket, base64_encode($this->smtp_username)."\r\n"); + + if(!$this->_parseServer($socket, '334')) + { + fclose($socket); + throw new Exception('Autorization error'); + } + + fputs($socket, base64_encode($this->smtp_password)."\r\n"); + + if(!$this->_parseServer($socket, '235')) + { + fclose($socket); + throw new Exception('Autorization error'); + } + + fputs($socket, 'MAIL FROM: <'.$this->smtp_username.">\r\n"); + + if(!$this->_parseServer($socket, '250')) + { + fclose($socket); + throw new Exception('Error of command sending: MAIL FROM'); + } + + $mailTo = ltrim($mailTo, '<'); + $mailTo = rtrim($mailTo, '>'); + + fputs($socket, 'RCPT TO: <'.$mailTo.">\r\n"); + + if(!$this->_parseServer($socket, '250')) + { + fclose($socket); + throw new Exception('Error of command sending: RCPT TO'); + } + + fputs($socket, 'DATA'."\r\n"); + + if(!$this->_parseServer($socket, "354")) + { + fclose($socket); + throw new Exception('Error of command sending: DATA'); + } + + fputs($socket, $contentMail."\r\n.\r\n"); + + if(!$this->_parseServer($socket, '250')) + { + fclose($socket); + throw new Exception('E-mail didn\'t sent'); + } + + fputs($socket, 'QUIT'."\r\n"); + fclose($socket); + } + + catch(Exception $e) + { + return $e->getMessage(); + } + + return true; + } + + private function _parseServer($socket, $response) + { + while(@substr($responseServer, 3, 1) != ' ') + if(!($responseServer = fgets($socket, 256))) + return false; + + if(!(substr($responseServer, 0, 3) == $response)) + return false; + + return true; + } + } +?> \ No newline at end of file diff --git a/system/library/sql.php b/system/library/sql.php new file mode 100644 index 0000000..477a78b --- /dev/null +++ b/system/library/sql.php @@ -0,0 +1,87 @@ +sql_id = @new mysqli($c, $u, $p, $n)) + { + if(!ERROR_DATABASE) + return NULL; + + $this->out_error(mysqli_connect_error()); + } + + mysqli_query($this->sql_id, "/*!40101 SET NAMES 'utf8' */"); + + $this->sql_connect = true; + + return NULL; + } + + public function query($query) + { + if(!$this->sql_connect) + $this->connect_mysql(CONNECT_DATABASE, USER_DATABASE, PASSWORD_DATABASE, NAME_DATABASE); + + if(!($this->query_id = mysqli_query($this->sql_id, $query)) and (mysqli_error($this->sql_id) and ERROR_DATABASE)) + $this->out_error(mysqli_error($this->sql_id), $query); + + return $this->query_id; + } + + public function get($query_id = false) + { + if(!$query_id) + $query_id = $this->query_id; + + $get = mysqli_fetch_assoc($query_id); + + return $get; + } + + public function num($query_id = false) + { + if(!$query_id) + $query_id = $this->query_id; + + return mysqli_num_rows($query_id); + } + + public function id() + { + return mysqli_insert_id($this->sql_id); + } + + public function esc() + { + mysqli_close($this->query_id); + mysqli_stmt_close($this->sql_id); + } + + private function out_error($error, $query = '') + { + global $go; + + if($go) + sys::outjs(array('e' => 'Query: '.$query.'
    Error:
    '.$error)); + + if($query != '') + echo 'Query: '.$query.'
    '; + + echo 'Error:
    '.$error; + + exit(); + } + } + + $sql = new mysql; +?> \ No newline at end of file diff --git a/system/library/ssh.php b/system/library/ssh.php new file mode 100644 index 0000000..4385ea1 --- /dev/null +++ b/system/library/ssh.php @@ -0,0 +1,99 @@ +connect($address) AND $this->auth_pwd('root', $passwd)) + return true; + + return false; + } + + public function connect($address) + { + list($host, $port) = explode(':', $address); + + if($port == '') + $port = 22; + + ini_set('default_socket_timeout', '3'); + + if($this->conn = ssh2_connect($host, $port)) + { + ini_set('default_socket_timeout', '180'); + + return true; + } + + return false; + } + + public function setfile($localFile, $remoteFile, $permision) + { + if(@ssh2_scp_send($this->conn, $localFile, $remoteFile, $permision)) + return true; + + return false; + } + + public function getfile($remoteFile, $localFile) + { + if(@ssh2_scp_recv($this->conn, $remoteFile, $localFile)) + return true; + + return false; + } + + public function set($cmd) + { + $this->stream = ssh2_exec($this->conn, $cmd); + + stream_set_blocking($this->stream, true); + } + + public function auth_pwd($u, $p) + { + if(@ssh2_auth_password($this->conn, $u, $p)) + return true; + + return false; + } + + public function get($cmd = false) + { + if($cmd) + { + $this->stream = ssh2_exec($this->conn, $cmd); + + stream_set_blocking($this->stream, true); + } + + $line = ''; + + while($get = fgets($this->stream)) + $line.= $get; + + return $line; + } + + public function esc() + { + if(function_exists('ssh2_disconnect')) + ssh2_disconnect($this->conn); + else{ + @fclose($this->conn); + unset($this->conn); + } + + return NULL; + } + } + + $ssh = new ssh; +?> \ No newline at end of file diff --git a/system/library/system.php b/system/library/system.php new file mode 100644 index 0000000..1395217 --- /dev/null +++ b/system/library/system.php @@ -0,0 +1,1463 @@ +query('UPDATE `users` set `time`="'.$start_point.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + return NULL; + } + + public static function users($users, $user, $authkey, $del = false) + { + global $mcache; + + if($del) + unset($users[md5($user['login'].$user['authkey'].$user['passwd'])]); + else + $users[md5($user['login'].$user['authkey'].$user['passwd'])] = $user; + + $mcache->set('users_auth', $users, false, 1000); + + return NULL; + } + + public static function nav($server, $sid, $active) + { + global $cfg, $html, $sql, $mcache, $start_point; + + $notice_sid = $mcache->get('notice_'.$sid); + + $notice = is_array($notice_sid) ? $notice_sid : $mcache->get('notice_'.$server['unit']); + + if(!is_array($notice)) + { + $sql->query('SELECT `server`, `text`, `color` FROM `notice` WHERE `server`="'.$sid.'" AND `time`>"'.$start_point.'" ORDER BY `id` DESC LIMIT 1'); + + if(!$sql->num()) + $sql->query('SELECT `unit`, `text`, `color` FROM `notice` WHERE `unit`="'.$server['unit'].'" AND `time`>"'.$start_point.'" ORDER BY `id` DESC LIMIT 1'); + + if($sql->num()) + { + $notice = $sql->get(); + + $nmc = $notice['server'] ? 'notice_'.$sid : 'notice_'.$server['unit']; + + $mcache->set('notice_'.$nmc, $notice, false, 10); + }else + $mcache->set('notice_'.$server['unit'], NULL, false, 10); + } + + $aUnit = array('index', 'console', 'settings', 'plugins', 'maps', 'owners', 'filetp', 'tarif', 'copy', 'graph', 'web', 'boost'); + + $html->get('gmenu', 'sections/servers/'.$server['game']); + + $html->set('id', $sid); + $html->set('home', $cfg['http']); + + if(is_array($notice)) + { + global $device; + + if($device == '!mobile') + $html->set('notice', '
    '.$notice['text'].'
    '); + else + $html->set('notice', '
    '.$notice['text'].'
    '); + }else + $html->set('notice', ''); + + if($server['console_use']) $html->unit('console_use', 1); else $html->unit('console_use'); + if($server['plugins_use']) $html->unit('plugins_use', 1); else $html->unit('plugins_use'); + if($server['ftp_use']) $html->unit('ftp_use', 1); else $html->unit('ftp_use'); + if($server['stats_use']) $html->unit('graph_use', 1); else $html->unit('graph_use'); + if($server['web_use']) $html->unit('web_use', 1); else $html->unit('web_use'); + if($server['copy_use']) $html->unit('copy_use', 1); else $html->unit('copy_use'); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('main'); + + $html->get('vmenu', 'sections/servers/'.$server['game']); + + $html->set('id', $sid); + $html->set('home', $cfg['http']); + + if($server['console_use']) $html->unit('console_use', 1); else $html->unit('console_use'); + if($server['plugins_use']) $html->unit('plugins_use', 1); else $html->unit('plugins_use'); + if($server['ftp_use']) $html->unit('ftp_use', 1); else $html->unit('ftp_use'); + if($server['stats_use']) $html->unit('graph_use', 1); else $html->unit('graph_use'); + if($server['web_use']) $html->unit('web_use', 1); else $html->unit('web_use'); + if($server['copy_use']) $html->unit('copy_use', 1); else $html->unit('copy_use'); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('vmenu'); + + return NULL; + } + + public static function route($server, $inc, $go, $all = false) + { + global $device, $start_point; + + $dir = $device == '!mobile' ? '' : 'megp/'; + $use = true; + + if(in_array($inc, array('plugins', 'ftp', 'console', 'graph', 'copy', 'web'))) + { + $server['graph_use'] = $server['stats_use']; + + if(!$server[$inc.'_use']) + $use = false; + } + + if(!$use || $server['time'] < $start_point || in_array($server['status'], array('install', 'reinstall', 'update', 'recovery', 'blocked'))) + { + if($go) + sys::out('Раздел недоступен'); + + if(!$use) + return SEC.$dir.'servers/'.$server['game'].'/index.php'; + + return SEC.$dir.'servers/noaccess.php'; + } + + if($all) + return SEC.'servers/games/'.$inc.'.php'; + + if(!file_exists(SEC.$dir.'servers/'.$server['game'].'/'.$inc.'.php')) + return SEC.$dir.'servers/'.$server['game'].'/index.php'; + + return SEC.$dir.'servers/'.$server['game'].'/'.$inc.'.php'; + } + + public static function int($data, $width = false) + { + if($width) + return preg_replace("([^0-9]{0, ".$width."})", '', $data); + + return preg_replace("([^0-9])", '', $data); + } + + public static function b64js($data) + { + return base64_encode(json_encode($data)); + } + + public static function b64djs($data) + { + return json_decode(base64_decode($data), true); + } + + public static function hb64($data) + { + return base64_encode(htmlspecialchars($data)); + } + + public static function hb64d($data) + { + return htmlspecialchars_decode(base64_decode($data)); + } + + public static function outjs($val, $cache = false) + { + global $mcache; + + if($cache) + $mcache->delete($cache); + + die(json_encode($val)); + } + + public static function out($val = '', $cache = false) + { + global $mcache; + + if($cache) + $mcache->delete($cache); + + die(''.$val.''); + } + + public static function outhtml($text, $time = 3, $url = false, $cache = false) + { + global $device, $mcache, $html, $cfg; + + if($cache) + $mcache->delete($cache); + + $tpl = $device == '!mobile' ? '' : '/megp'; + + $html->get('out'); + + $html->set('title', $cfg['name']); + $html->set('home', $cfg['http']); + $html->set('css', $cfg['http'].'template'.$tpl.'/css/'); + $html->set('js', $cfg['http'].'template'.$tpl.'/js/'); + $html->set('img', $cfg['http'].'template'.$tpl.'/images/'); + $html->set('text', $text); + + $html->pack('out'); + + if(!$url) + $url = $cfg['http']; + + header('Refresh: '.$time.'; URL='.$url); + + die($html->arr['out']); + } + + public static function valid($val, $type, $preg = '') + { + switch($type) + { + case 'promo': + if(!preg_match("/^[A-Za-z0-9]{2,20}$/", $val)) + return true; + + return false; + + case 'en': + if(!preg_match("/^[A-Za-z0-9]$/", $val)) + return true; + + return false; + + case 'ru': + if(!preg_match("/^[А-Яа-я]$/u", $val)) + return true; + + return false; + + case 'wm': + if(!preg_match('/^R[0-9]{12,12}$|^Z[0-9]{12,12}$|^U[0-9]{12,12}$/m', $val)) + return true; + + return false; + + case 'ip': + if(!preg_match("/^(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}$/", $val)) + return true; + + return false; + + case 'steamid': + if(!preg_match("/^STEAM_[0-9]:[0-9]:[0-9]{6,12}$|^HLTV$|^STEAM_ID_LAN$|^STEAM_ID_PENDING$|^VALVE_ID_LAN$|^VALVE_ID_PENDING$|^STEAM_666:88:666$/", $val)) + return true; + + return false; + + case 'steamid3': + if(!preg_match("/^\[U:[01]:[0-9]{3,12}\]$/i", $val)) + return true; + + return false; + + case 'num': + if(!preg_match('/[^0-9]/', $val)) + return true; + + return false; + + case 'md5': + if(!preg_match("/^[a-z0-9]{32,32}$/", $val)) + return true; + + return false; + + case 'other': + if(!preg_match($preg, $val)) + return true; + + return false; + } + + return true; + } + + public static function mail($name, $text, $mail) + { + global $cfg; + + require_once(LIB.'smtp.php'); + + $tpl = file_get_contents(DATA.'mail.ini', "r"); + + $text = str_replace( + array('[name]', '[text]', '[http]', '[img]', '[css]'), + array($cfg['name'], $text, $cfg['http'], $cfg['http'].'template/images/', $cfg['http'].'template/css/'), + $tpl + ); + + $smtp = new smtp($cfg['smtp_login'], $cfg['smtp_passwd'], $cfg['smtp_url'], $cfg['smtp_mail'], 465); + + $headers = "MIME-Version: 1.0\r\n"; + $headers .= "Content-type: text/html; charset=utf-8\r\n"; + $headers .= "From: ".$cfg['smtp_name']." <".$cfg['smtp_mail'].">\r\n"; + + if($smtp->send($mail, $name, $text, $headers)) + return true; + + return false; + } + + public static function mail_domain($mail) + { + $domain = explode('@', $mail); + + $domain = end($domain); + + if(in_array($domain, array('list.ru', 'bk.ru', 'inbox.ru'))) + $domain = 'mail.ru'; + + switch($domain) + { + case 'mail.ru': + return $domain; + + case 'yandex.ru': + return 'mail.yandex.ru'; + + case 'google.com': + return 'mail.google.com'; + + default: + return ''; + } + } + + public static function domain($domain) + { + $domain = explode('.', $domain); + + unset($domain[0]); + + return implode('.', $domain); + } + + public static function updtext($text, $data) + { + foreach($data as $name => $val) + $text = str_replace('['.$name.']', $val, $text); + + return $text; + } + + public static function login($mail, $lchar) + { + if(!$lchar) + return str_replace(array('.', '_', '+', '-'), '', sys::first(explode('@', $mail))); + + $list = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz0123456789'; + $a = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz'; + $selections = strlen($list)-1; + $start = strlen($a)-1; + $b = rand(0, $start); + $start = $a[$b]; + $login = array(); + + $i = 0; + + for($i; $i <= 10; $i+=1) + { + $n = rand(0, $selections); + $login[] = $list[$n]; + } + + return $start.implode('', $login); + } + + public static function passwd($length = 8) + { + $list = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz0123456789'; + $a = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz'; + $selections = strlen($list)-1; + $start = strlen($a)-1; + $b = rand(0, $start); + $start = $a[$b]; + $passwd = array(); + + $i = 0; + + for($i; $i <= $length-2; $i+=1) + { + $n = rand(0, $selections); + $passwd[] = $list[$n]; + } + + return $start.implode('', $passwd); + } + + public static function passwdkey($passwd) + { + return md5($passwd); + } + + public static function cookie($name, $value, $expires) + { + $expires = time() + ($expires * 86400); + setcookie($name, $value, $expires, "/", $_SERVER['HTTP_HOST'], null, true); + } + + public static function auth() + { + global $auth, $go, $text, $cfg; + + if($auth) + { + if($go) + sys::outjs(array('e' => sys::text('output', 'auth'))); + + global $device; + + $link = $device == '!mobile' ? 'user/section/lk' : ''; + + exit(header('Refresh: 0; URL='.$cfg['http'].$link)); + } + + return NULL; + } + + public static function noauth() + { + global $auth, $go, $text, $cfg; + + if(!$auth) + { + if($go) + sys::outjs(array('e' => sys::text('output', 'noauth'))); + + global $device; + + $link = $device == '!mobile' ? 'user/section/auth' : 'auth'; + + exit(header('Refresh: 0; URL='.$cfg['http'].$link)); + } + + return NULL; + } + + public static function browser($agent) + { + if(strpos($agent, 'Firefox') !== false) + return 'Mozilla Firefox'; + + if(strpos($agent, 'Opera') !== false) + return 'Opera'; + + if(strpos($agent, 'Chrome') !== false) + return 'Google Chrome'; + + if(strpos($agent, 'MSIE') !== false) + return 'Internet Explorer'; + + if(strpos($agent, 'Safari') !== false) + return 'Safari'; + + return 'Неизвестный'; + } + + public static function date($lenght, $date) + { + global $start_point; + + $check_time = $date-$start_point; + + if($check_time < 1) + return 'время истекло.'; + + $days = floor($check_time/86400); + $hours = floor(($check_time%86400)/3600); + $minutes = floor(($check_time%3600)/60); + $seconds = $check_time%60; + + $adata = array( + 'min' => array( + 'days' => array('день', 'дня', 'дней'), + 'hours' => array('ч.', 'ч.', 'ч.'), + 'minutes' => array('мин.', 'мин.', 'мин.'), + 'seconds' => array('сек.', 'сек.', 'сек.') + ), + 'max' => array( + 'days' => array('день', 'дня', 'дней'), + 'hours' => array('час', 'часа', 'часов'), + 'minutes' => array('минуту','минуты','минут'), + 'seconds' => array('секунду','секунды','секунд') + ) + ); + + $text = ''; + + if($days > 0) + $text .= sys::date_decl($days, $adata[$lenght]['days']); + + if($days < 1 AND $hours > 0) + $text .= ' '.sys::date_decl($hours, $adata[$lenght]['hours']); + + if($days < 1 AND $minutes > 0) + $text .= ' '.sys::date_decl($minutes, $adata[$lenght]['minutes']); + + if($days < 1 AND $seconds > 0) + $text .= ' '.sys::date_decl($seconds, $adata[$lenght]['seconds']); + + return $text; + } + + public static function date_decl($digit, $expr, $onlyword = false) + { + if(!is_array($expr)) + $expr = array_filter(explode(' ', $expr)); + + if(empty($expr[2])) + $expr[2] = $expr[1]; + + $i = sys::int($digit)%100; + + if($onlyword) + $digit = ''; + + if($i > 4 AND $i < 21) + $res = $digit.' '.$expr[2]; + else + $i%=10; + + if($i == 1) + $res = $digit.' '.$expr[0]; + elseif($i > 1 AND $i < 5) + $res = $digit.' '.$expr[1]; + else + $res = $digit.' '.$expr[2]; + + return trim($res); + } + + public static function today($time, $cp = false) + { + global $start_point; + + $today = date('d.m.Y', $start_point); + $day = date('d.m.Y', $time); + + if($day == $today) + { + if($cp) + return 'Сегодня '.date('H:i', $time); + + return 'Сегодня '.date('- H:i', $time); + } + + $yesterday_first = sys::int(sys::first(explode('.', $today)))-1; + $yesterday_full = date('m.Y', $time); + + if($day == $yesterday_first.'.'.$yesterday_full AND !$yesterday_first) + { + if($cp) + return 'Вчера '.date('H:i', $time); + + return 'Вчера '.date('- H:i', $time); + } + + if($cp) + return date('d.m.Y H:i', $time); + + return date('d.m.Y - H:i', $time); + } + + public static function day($time) + { + $days = array('день', 'дня', 'дней'); + + $time = $time % 100; + + if($n > 10 AND $n < 20) + return $days[2]; + + $time = $time % 10; + + if($time > 1 AND $time < 5) + return $days[1]; + + if($time == 1) + return $days[0]; + + return $days[2]; + } + + public static function bbc($text) + { + global $cfg; + + $lines = explode("\n", $text); + + $str_search = array( + "#\\\n#is", + "#\[spoiler\](.+?)\[\/spoiler\]#is", + "#\[sp\](.+?)\[\/sp\]#is", + "#\[b\](.+?)\[\/b\]#is", + "#\[u\](.+?)\[\/u\]#is", + "#\[code\](.+?)\[\/code\]#is", + "#\[quote\](.+?)\[\/quote\]#is", + "#\[url=(.+?)\](.+?)\[\/url\]#is", + "#\[img=(.+?)\] \[\/img\]#is", + "#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is" + ); + + $str_replace = array( + "
    ", + "
    Посмотреть содержимое
    \\1
    ", + "
    Посмотреть содержимое
    \\1
    ", + "\\1", + "\\1", + "
    Посмотреть содержимое
    \\1
    ", + "

    \\1

    ", + "\\2", + "Изображение", + " \\2" + ); + + $uptext = ''; + + foreach($lines as $line) + $uptext .= preg_replace($str_search, $str_replace, $line)."
    "; + + return $uptext; + } + + public static function first($array = array()) + { + return $array[0]; + } + + public static function back($url) + { + exit(header('Refresh: 0; URL='.$url)); + } + + public static function strlen($str) + { + return iconv_strlen($str, 'UTF-8'); + } + + public static function text($section, $name) + { + global $cfg, $user; + + $group = isset($user['group']) ? $user['group'] : 'user'; + + if($section != 'error' || !$cfg['text_group']) + $group = 'all'; + + include(DATA.'text/'.$section.'.php'); + + return isset($text[$name][$group]) ? $text[$name][$group] : $text[$name]; + } + + public static function key($param = 'defegp') + { + return md5(sha1(rand(1, 15).$param.rand(16, 30).rand(200, 1000).rand(1, 100))); + } + + public static function captcha($type, $ip) + { + global $mcache; + + $cod = ''; + $width = 100; + $height = 45; + $font_size = 16; + $symbols = 3; + $symbols_fon = 20; + $font = LIB.'captcha/text.ttf'; + + $chars = array('a','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7','9'); + $colors = array('20','50','80','100'); + + $src = imagecreatetruecolor($width, $height); + $fon = imagecolorallocate($src, 255, 255, 255); + + imagefill($src, 0, 0, $fon); + + $i = 0; + for($i; $i < $symbols_fon; $i+=1) + { + $color = imagecolorallocatealpha($src, rand(0,255), rand(0,255), rand(0,255), 100); + $char = $chars[rand(0, sizeof($chars)-1)]; + $size = rand($font_size-2, $font_size+2); + + imagettftext($src, $size, rand(0,45), rand($width*0.1,$width-$width*0.1), rand($height*0.2,$height), $color, $font, $char); + } + + $i = 0; + for($i; $i < $symbols; $i+=1) + { + $color = imagecolorallocatealpha($src, $colors[rand(0,sizeof($colors)-1)], $colors[rand(0,sizeof($colors)-1)], $colors[rand(0,sizeof($colors)-1)], rand(20,40)); + $char = $chars[rand(0, sizeof($chars)-1)]; + $size = rand($font_size*2.1-2, $font_size*2.1+2); + + $x = ($i+1)*$font_size + rand(6,8); + $y = (($height*2)/3) + rand(3,7); + + $cod .= $char; + + imagettftext($src, $size, rand(0,15), $x, $y, $color, $font, $char); + } + + $mcache->set($type.'_captcha_'.$ip, $cod, false, 120); + + header("Content-type: image/gif"); + imagegif($src); + imagedestroy($src); + exit; + } + + public static function captcha_check($type, $ip, $cod = '') + { + global $cfg, $mcache; + + // Если повтор ввода капчи выключен и в кеше есть подтвержденный сеанс + if(!$cfg['recaptcha'] AND $mcache->get($type.'_captcha_valid_'.$ip)) + return false; + + if($mcache->get($type.'_captcha_'.$ip) != strtolower($cod)) + { + $mcache->set($type.'_captcha_valid_'.$ip, true, false, 60); + + return true; + } + + return false; + } + + public static function ismail($data) + { + $aData = explode('@', $data); + + if(count($aData) > 1) + return true; + + return false; + } + + public static function smscode() + { + return rand(1,9).rand(100,500).rand(10,99); + } + + public static function code($length = 8) + { + $list = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz0123456789'; + $a = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuWwXxYyZz'; + $selections = strlen($list)-1; + $start = strlen($a)-1; + $b = rand(0, $start); + $start = $a[$b]; + $code = array(); + + $i = 0; + + for($i; $i <= $length-2; $i+=1) + { + $n = rand(0, $selections); + $code[] = $list[$n]; + } + + return $start.implode('', $code); + } + + public static function sms($text, $phone) + { + global $cfg; + + $out = file_get_contents($cfg['sms_gateway'].'&'.$cfg['sms_to'].'='.$phone.'&'.$cfg['sms_text'].'='.urlencode($text)); + + $aOut = explode("\n", $out); + + if(trim($aOut[0]) == $cfg['sms_ok']) + return true; + + return false; + } + + public static function find($text, $find) + { + $words = explode(' ', $find); + + foreach($words as $word) + if(strlen($word) >= 2) + $text = preg_replace('#'.quotemeta($word).'#iu', '$0', $text); + + return $text; + } + + public static function str_first_replace($search, $replace, $text) + { + $pos = strpos($text, $search); + + return $pos!==false ? substr_replace($text, $replace, $pos, strlen($search)) : $text; + } + + public static function cmd($command) + { + $text = preg_replace('/\\$/', '$ы', trim($command)); + + mb_internal_encoding('UTF-8'); + + if(mb_substr($text, -1) == 'ы') + $text = quotemeta(substr($text, 0, -2)); + + return $text; + } + + public static function map($map) + { + $name = quotemeta(trim($map)); + + if(substr($name, -1) == '$') + $name = substr($name, 0, -2).'$'; + + return str_replace(array('\.', '\*'), array('.', '*'), $name); + } + + public static function temp($text) + { + $temp = TEMP.md5(time().rand(5, 100).rand(10, 20).rand(1, 20).rand(40, 80)); + + $file = fopen($temp, "w"); + + fputs($file, $text); + + fclose($file); + + return $temp; + } + + public static function size($val) + { + $aSize = array(' Байт', ' Кб', ' Мб', ' Гб', ' Тб', ' Пб'); + + return $val ? round($val/pow(1024, ($i = floor(log($val, 1024)))), 2) . $aSize[$i] : '0 Байт'; + } + + public static function unidate($date) + { + $aDate = explode('-', $date); + + $aFirst = explode(' ', $aDate[2]); + + return $aFirst[1].' - '.$aFirst[0].'.'.$aDate[1].'.'.$aDate[0]; + } + + public static function page($page, $nums, $num) + { + $ceil = ceil($nums/$num); + + if($page > $ceil) + $page = $ceil; + + $next = $page*$num; + + if($next <= $nums) + $next = $next-$num; + + if($next > $nums) + $next = $next-$num; + + if($next < 1) + $next = 0; + + $num_go = $next; + if($page == '') + $page = 1; + + $aPage = array( + 'page' => $page, + 'num' => $num_go, + 'ceil' => $ceil + ); + + return $aPage; + } + + public static function page_list($countnum, $actnum) + { + if($countnum == 0 || $countnum == 1) + return array(); + + if($countnum > 10) + { + if($actnum <= 4 || $actnum + 3 >= $countnum) + { + for($i = 0; $i <= 4; $i++) + $numlist[$i] = $i + 1; + + $numlist[5] = '...'; + for($j = 6, $k = 4; $j <= 10; $j+=1, $k-=1) + $numlist[$j] = $countnum - $k; + }else{ + $numlist[0] = 1; + $numlist[1] = 2; + $numlist[2] = '...'; + $numlist[3] = $actnum - 2; + $numlist[4] = $actnum - 1; + $numlist[5] = $actnum; + $numlist[6] = $actnum + 1; + $numlist[7] = $actnum + 2; + $numlist[8] = '...'; + $numlist[9] = $countnum - 1; + $numlist[10] = $countnum; + } + }else + for($n = 0; $n < $countnum; $n+=1) + $numlist[$n] = $n + 1; + + return $numlist; + } + + public static function page_gen($ceil, $page, $actnum, $section) + { + global $cfg, $html; + + $aNum = sys::page_list($ceil, $actnum); + + $pages = ''; + + $html->get('pages'); + + if($ceil) + { + if($page != 1) + { + $next = $page-1; + $pages .= 'Предыдущая'; + } + + foreach($aNum as $v) + { + if($v != $page && $v != '...') + $pages .= ''.$v.''; + + if($v == $page) + $pages .= ''.$v.''; + + if($v == '...') + $pages .= '...'; + } + + if($ceil > $page) + { + if($page < $ceil) + { + $next = $page+1; + $pages .= 'Следующая'; + }else + $pages .= 'Следующая'; + } + } + + $html->set('pages', $pages); + + $html->pack('pages'); + + return NULL; + } + + public static function country($name) + { + global $cfg; + + $fileimg = file_exists(TPL.'/images/country/'.$name.'.png'); + + if($fileimg) + return $cfg['http'].'template/images/country/'.$name.'.png'; + + return $cfg['http'].'template/images/country/none.png'; + } + + public static function ipproxy() + { + global $_SERVER; + + if(isset($_SERVER['HTTP_CF_CONNECTING_IP']) && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) + return $_SERVER['HTTP_CF_CONNECTING_IP']; + + return NULL; + } + + public static function ip() + { + $ip = sys::ipproxy(); + + if(sys::valid($ip, 'ip')) + return $_SERVER['REMOTE_ADDR']; + + return $ip; + } + + public static function whois($ip) + { + $stack = fsockopen('whois.ripe.net', 43, $errno, $errstr); + + if(!$stack) + return 'не определена'; + + fputs($stack, $ip."\r\n"); + + $subnetwork = ''; + + while(!feof($stack)) + { + $str = fgets($stack, 128); + + if(strpos($str, 'route:') !== FALSE) + { + $subnetwork = trim(str_replace('route:', '', $str)); + + break; + } + } + + fclose($stack); + + return isset($subnetwork{0}) ? $subnetwork : 'не определена'; + } + + public static function rep_act($name, $time = 20) + { + global $go, $mcache; + + if(!$go) + return NULL; + + if($mcache->get($name)) + sys::outjs(array('e' => sys::text('other', 'mcache'))); + + $mcache->set($name, true, false, $time); + + return $name; + } + + public static function check_php_config($file, &$error) + { + exec('php -l '.$file, $error, $code); + + if(!$code) + return true; + + return false; + } + + public static function cpu_idle($pros_stat = array(), $unit, $fcpu = false, $ctrl = false) + { + return sys::cpu_get_idle(sys::parse_cpu($pros_stat[0]), sys::parse_cpu($pros_stat[1]), $unit, $fcpu, $ctrl); + } + + public static function cpu_get_idle($first, $second, $unit, $fcpu, $ctrl) + { + global $sql; + + if(count($first) !== count($second)) + return; + + $cpus = array(); + + for($i = 0, $l = count($first); $i < $l; $i+=1) + { + $dif = array(); + $dif['use'] = $second[$i]['use']-$first[$i]['use']; + $dif['nice'] = $second[$i]['nice']-$first[$i]['nice']; + $dif['sys'] = $second[$i]['sys']-$first[$i]['sys']; + $dif['idle'] = $second[$i]['idle']-$first[$i]['idle']; + $total = array_sum($dif); + $cpu = array(); + + foreach($dif as $x => $y) + $cpu[$x] = $y ? round($y/$total*100, 1) : 0; + + $cpus['cpu'.$i] = $cpu; + } + + if($fcpu) + return $cpus; + + $threads = array(); + + $l = count($first); + + for($i = 0; $i < $l; $i+=1) + $threads[$i] = $cpus['cpu'.$i]['idle']; + + if(count($first) > 1) + unset($threads[0]); + + $max = max($threads); + + foreach($threads as $idle) + { + $core = array_search($max, $threads); + + if($ctrl) + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$unit.'" AND `core_fix`="'.($core+1).'" LIMIT 1'); + else + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$unit.'" AND `core_fix`="'.($core+1).'" AND `core_fix_one`="1" LIMIT 1'); + if($sql->num()) + { + unset($threads[$core]); + + if(!count($threads)) + return NULL; + + $max = max($threads); + } + } + + return array_search($max, $threads); + } + + public static function parse_cpu($data) + { + $data = explode("\n", $data); + + $cpu = array(); + + foreach($data as $line) + { + if(preg_match('/^cpu[0-9]/', $line)) + { + $info = explode(' ', $line); + + $cpu[] = array( + 'use' => $info[1], + 'nice' => $info[2], + 'sys' => $info[3], + 'idle' => $info[4] + ); + } + } + + return $cpu; + } + + public static function reset_mcache($nmch, $id, $data = array(), $ctrl = false) + { + global $mcache; + + $cache = array( + 'name' => $data['name'], + 'status' => sys::status($data['status'], $data['game']), + 'online' => $data['online'], + 'image' => '', + ); + + $cache = $ctrl ? sys::buttons($id, $data['status'], $data['game'], $ctrl) : sys::buttons($id, $data['status'], $data['game']); + + if(isset($data['players'])) + $cache['players'] = $data['players']; + + $mcache->set($nmch, $cache, false, 5); + + return NULL; + } + + public static function status($status, $game, $map = '', $get = 'text') + { + global $cfg; + + switch($status) + { + case 'working': + if($get == 'img') + { + if(in_array($game, array('samp', 'crmp', 'mta', 'mc'))) + $map = $game; + + return sys::img($map, $game); + } + + return 'Карта: '.($map == '' ? '-' : $map); + + case 'off': + if($get == 'img') + return $cfg['http'].'template/images/status/off.jpg'; + + return 'Статус: выключен'; + + case 'start': + if($get == 'img') + return $cfg['http'].'template/images/status/start.gif'; + + return 'Статус: запускается'; + + case 'restart': + if($get == 'img') + return $cfg['http'].'template/images/status/restart.gif'; + + return 'Статус: перезапускается'; + + case 'change': + if($get == 'img') + return $cfg['http'].'template/images/status/change.gif'; + + return 'Статус: меняется карта'; + + case 'install': + if($get == 'img') + return $cfg['http'].'template/images/status/install.gif'; + + return 'Статус: устанавливается'; + + case 'reinstall': + if($get == 'img') + return $cfg['http'].'template/images/status/reinstall.gif'; + + return 'Статус: переустанавливается'; + + case 'update': + if($get == 'img') + return $cfg['http'].'template/images/status/update.gif'; + + return 'Статус: обновляется'; + + case 'recovery': + if($get == 'img') + return $cfg['http'].'template/images/status/recovery.gif'; + + return 'Статус: восстанавливается'; + + case 'overdue': + if($get == 'img') + return $cfg['http'].'template/images/status/overdue.jpg'; + + return 'Статус: просрочен'; + + case 'blocked': + if($get == 'img') + return $cfg['http'].'template/images/status/blocked.jpg'; + + return 'Статус: заблокирован'; + } + } + + public static function img($name, $game) + { + global $cfg; + + $filename = 'http://cdn.enginegp.ru/maps/'.$game.'/'.$name.'.jpg'; + $file_headers = @get_headers($filename) ; + $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://"; + if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found' ||trim($file_headers[0]) == 'HTTP/1.1 403 Forbidden') { + return $cfg['http'].'template/images/status/none.jpg'; + } + else { + return '' . $protocol .'cdn.enginegp.ru/maps/'.$game.'/'.$name.'.jpg'; + } + } + + public static function buttons($id, $status, $game = false, $ctrl = false) + { + global $html; + + if(isset($html->arr['buttons'])) + unset($html->arr['buttons']); + + $other = in_array($game, array('samp', 'crmp', 'mta', 'mc')); + + $dir = $ctrl ? 'control/servers' : 'servers'; + + if(in_array($status, array('working', 'change', 'start', 'restart'))) + { + $html->get('stop', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + + $html->get('restart', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + + if(!$other) + { + $html->get('change', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + } + + return $html->arr['buttons']; + } + + if($status == 'off') + { + $html->get('start', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + + $html->get('reinstall', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + + if(!$other) + { + $html->get('update', 'sections/'.$dir.'/buttons'); + + $html->set('id', $id); + if($ctrl) + $html->set('ctrl', $ctrl); + + $html->pack('buttons'); + } + + return $html->arr['buttons']; + } + + $html->get('other', 'sections/'.$dir.'/buttons'); + $html->pack('buttons'); + + return $html->arr['buttons']; + } + + public static function entoru($month) + { + $ru = array( + 1 => 'Янв', 2 => 'Фев', 3 => 'Мар', 4 => 'Апр', + 5 => 'Май', 6 => 'Июн', 7 => 'Июл', 8 => 'Авг', + 9 => 'Сен', 10 => 'Окт', 11 => 'Ноя', 12 => 'Дек' + ); + + return $ru[$month]; + } + + public static function head($head) + { + global $route, $header; + + if($head == 'description') + { + global $description; + + if(isset($description)) + { + $text = str_replace(array('"', '-'), array('', '—'), strip_tags($description)); + + if(strlen($text) > 160) + { + mb_internal_encoding('UTF-8'); + + $text = mb_substr($text, 0, 157).'...'; + } + + return $text; + } + }else{ + global $keywords; + + if(isset($keywords)) + return str_replace(array('"', '-'), array('', '—'), strip_tags($keywords)); + } + + return array_key_exists($route, $header) ? $header[$route][$head] : $header['index'][$head]; + } + + public static function tags($tags) + { + $aTags = explode(',', $tags); + + $text = ''; + + foreach($aTags as $tag) + $text .= ''.trim($tag).', '; + + return isset($text{0}) ? substr($text, 0, -2) : 'отсутствуют'; + } + + public static function benefitblock($id, $nmch = false) + { + global $cfg, $sql, $start_point; + + if($cfg['benefitblock']) + { + $sql->query('SELECT `benefit` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $info = $sql->get(); + + if($info['benefit'] > $start_point) + sys::outjs(array('e' => 'Операция недоступна до '.date('d.m.Y - H:i:s', $info['benefit'])), $nmch); + } + + return NULL; + } + + function outfile($file, $name, $del = false) + { + if(file_exists($file)) + { + if(ob_get_level()) + ob_end_clean(); + + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename='.$name); + header('Content-Transfer-Encoding: binary'); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: '.filesize($file)); + + readfile($file); + + if($del) + unlink($file); + + exit; + } + } + } +?> \ No newline at end of file diff --git a/system/library/users.php b/system/library/users.php new file mode 100644 index 0000000..732d68a --- /dev/null +++ b/system/library/users.php @@ -0,0 +1,53 @@ +get('gmenu', 'sections/user'); + + $html->set('home', $cfg['http']); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('main'); + + $html->get('vmenu', 'sections/user'); + + $html->set('home', $cfg['http']); + + foreach($aUnit as $unit) + if($unit == $active) $html->unit($unit, 1); else $html->unit($unit); + + $html->pack('vmenu'); + + return NULL; + } + } +?> \ No newline at end of file diff --git a/system/library/web/free.php b/system/library/web/free.php new file mode 100644 index 0000000..fef8c55 --- /dev/null +++ b/system/library/web/free.php @@ -0,0 +1,496 @@ + 'Дополнительная услуга недоступна для установки.'), $mcache); + + // Проверка на наличие уже установленной выбранной услуги + if($sql->num(web::stack($aData, '`id`'))) + sys::outjs(array('i' => 'Дополнительная услуга уже установлена.'), $mcache); + + // Проверка на наличие уже установленной подобной услуги + switch($aWebInstall[$aData['server']['game']][$aData['type']]) + { + case 'server': + foreach($aWebOne[$aData['server']['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `server`="'.$aData['server']['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $mcache); + } + + break; + + case 'user': + foreach($aWebOne[$aData['server']['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `user`="'.$aData['server']['user'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $mcache); + } + + break; + + case 'unit': + foreach($aWebOne[$aData['server']['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `user`="'.$aData['server']['user'].'" AND `unit`="'.$aData['server']['unit'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $mcache); + } + } + + // Проверка валидности поддомена + if(sys::valid($aData['subdomain'], 'other', "/^[a-z0-9]+$/")) + sys::outjs(array('e' => 'Адрес должен состоять из букв a-z и цифр.'), $mcache); + + // Проверка длины поддомена + if(!isset($aData['subdomain']{3}) || isset($aData['subdomain']{15})) + sys::outjs(array('e' => 'Длина адреса не должна превышать 16-и символов и быть не менее 4-х символов.'), $mcache); + + // Проверка запрещенного поддомена + if(in_array($aData['subdomain'], $aWebUnit['subdomains'])) + sys::outjs(array('e' => 'Нельзя создать данный адрес, придумайте другой.'), $mcache); + + // Проверка наличия домена + if(!in_array($aData['domain'], $aWebUnit['domains'])) + sys::outjs(array('e' => 'Выбранный домен не найден.'), $mcache); + + // Проверка поддомена на занятость + $sql->query('SELECT `id` FROM `web` WHERE `domain`="'.$aData['subdomain'].'.'.$aData['domain'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес уже занят.'), $mcache); + + // Проверка наличия шаблона + if(!array_key_exists($aData['desing'], $aWebParam[$aData['type']]['desing'])) + sys::outjs(array('e' => 'Выбранный шаблон не найден.'), $mcache); + + if(isset($aData['passwd'])) + { + // Если не указан пароль сгенерировать + if($aData['passwd'] == '') + $aData['passwd'] = sys::passwd($aWebParam[$aData['type']]['passwd']); + + // Проверка длинны пароля + if(!isset($aData['passwd']{5}) || isset($aData['passwd']{15})) + sys::outjs(array('e' => 'Необходимо указать пароль длинной не менее 6-и символов и не более 16-и.'), $mcache); + + // Проверка валидности пароля + if(sys::valid($aData['passwd'], 'other', "/^[A-Za-z0-9]{6,16}$/")) + sys::outjs(array('e' => 'Пароль должен состоять из букв a-z и цифр.'), $mcache); + } + + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $aData['server']['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + // Директория файлов услуги + $path = $aWebUnit['path'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$aData['desing']; + + // Директория дополнительной услуги + $install = $aWebUnit['install'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$aData['subdomain'].'.'.$aData['domain']; + + $sql->query('INSERT INTO `web` set `type`="'.$aData['type'].'", `server`="'.$aData['server']['id'].'", `user`="'.$aData['server']['user'].'", `unit`="'.$aData['server']['unit'].'", `config`=""'); + $wid = $sql->id(); + $uid = $wid+10000; + + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$aData['server']['user'].'" LIMIT 1'); + if(!$sql->num()) + { + $sql->query('DELETE FROM `web` WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('e' => 'Необходимо указать пользователя сервера.'), $mcache); + } + + $u = $sql->get(); + + // Данные + $login = 'w'.$uid; + $passwd = sys::passwd(10); + $ip = sys::first(explode(':', $unit['address'])); + $host = $aWebUnit['unit'][$aData['type']] == 'local' ? '127.0.0.1' : $ip; + + $conf = array( + 'address' => $aData['server']['address'], + 'install' => $install, + 'login' => $login, + 'passwd' => $passwd, + 'host' => $host, + 'url' => $cfg['http'], + 'domain' => $aData['subdomain'].'.'.$aData['domain'] + ); + + $aData['config_sql'] = sys::updtext($aData['config_sql'], $conf); + + if(isset($aWebdbConf[$aData['type']])) + { + $aData['config_php'] = sys::updtext($aData['config_php'], $conf); + + $temp = sys::temp($aData['config_php']); + $ssh->setfile($temp, $path.$aWebdbConf[$aData['type']]['file'], $aWebdbConf[$aData['type']]['chmod']); + + unlink($temp); + } + + if(isset($aWebothPath[$aData['type']])) + { + $aData['config_oth'] = sys::updtext($aData['config_oth'], $conf); + + $temp = sys::temp($aData['config_oth']); + $ssh->setfile($temp, $path.$aWebothPath[$aData['type']]['file'], $aWebothPath[$aData['type']]['chmod']); + + unlink($temp); + } + + // Создание поддомена + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['domain']['create'], array('subdomain' => $aData['subdomain'], 'ip' => $ip, 'domain' => $aData['domain']))), true); + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + { + $sql->query('DELETE FROM `web` WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('e' => 'Не удалось создать поддомен, обратитесь в тех.поддержку.'), $mcache); + } + + // Создание задания crontab + if(isset($aWebUnit['isp']['crontab'][$aData['type']]['install'])) + { + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['crontab'][$aData['type']]['install'], array('subdomain' => $aData['subdomain'], 'domain' => $aData['domain']))), true); + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + { + $sql->query('DELETE FROM `web` WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('e' => 'Не удалось создать задание, обратитесь в тех.поддержку.'), $mcache); + } + } + + $a2 = ''.PHP_EOL + .' ServerName '.$aData['subdomain'].'.'.$aData['domain'].PHP_EOL + .' DocumentRoot '.$install.PHP_EOL + .' AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml'.PHP_EOL + .' AddType application/x-httpd-php-source .phps'.PHP_EOL + .''; + + // Смена прав на файлы/папки + $chmod = isset($aWebChmod[$aData['type']]) ? $aWebChmod[$aData['type']] : ''; + + $sql_q = ''; + + if(isset($aWebSQL[$aData['type']])) + { + $sql_q .= 'mysql --login-path=local -e "CREATE DATABASE '.$login.';' + ."CREATE USER '".$login."'@'%' IDENTIFIED BY '".$passwd."';" + .'GRANT ALL PRIVILEGES ON '.$login.' . * TO \''.$login.'\'@\'%\';";' + .'mysql --login-path=local '.$login.' < '.$aWebUnit['path'][$aWebUnit['unit'][$aData['type']]][$aData['type']].'dump.sql;'; + + if(isset($aWebSQL[$aData['type']]['install'])) + foreach($aWebSQL[$aData['type']]['install'] as $query) + $sql_q .= "mysql --login-path=local ".$login." -e \"".sys::updtext($query, + array( + 'url' => $cfg['http'], + 'passwd' => $aData['passwd'], + 'mail' => $u['mail'], + 'folder' => $install) + )."\";"; + } + + // Установка + $ssh->set('echo "'.$a2.'" > /etc/apache2/sites-enabled/'.$aData['subdomain'].'.'.$aData['domain'].';' // Настроки апач + .'mkdir -p '.$install.';' // Создание директории + .'useradd -d '.$install.' -g web -u '.$uid.' web'.$uid.';' // Создание пользователя услуги на локации + .'chown -R web'.$uid.':999 '.$install.';' // Изменение владельца и группы директории + .'cd '.$install.' && sudo -u web'.$uid.' screen -dmS i_w_'.$uid.' sh -c "cp -r '.$path.'/. .; '.$chmod.'";' // Копирование файлов услуги + .'screen -dmS apache_reload_'.$uid.' service apache2 reload;' // Перезагрузить конфигурации апач + .$sql_q); // sql запросы + + $aData['passwd'] = isset($aData['passwd']) ? $aData['passwd'] : ''; + + // Обновление данных + $sql->query('UPDATE `web` set `uid`="'.$uid.'", `desing`="'.$aData['desing'].'", ' + .'`domain`="'.$aData['subdomain'].'.'.$aData['domain'].'", ' + .'`passwd`="'.$aData['passwd'].'", `config`="'.base64_encode($aData['config_sql']).'", ' + .'`login`="'.$login.'", `date`="'.$start_point.'" ' + .'WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + public static function update($aData = array(), $mcache) + { + global $sql, $start_point; + + include(DATA.'web.php'); + + $stack = web::stack($aData, '`id`, `uid`, `unit`, `login`, `desing`, `domain`, `update`'); + + if(!$sql->num($stack)) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $mcache); + + $web = $sql->get($stack); + + // Проверка времени последнего обновления + include(LIB.'games/games.php'); + + $upd = $web['update']+86400; + + if($upd > $start_point) + sys::outjs(array('e' => 'Для повторного обновления должно пройти: '.games::date('max', $upd))); + + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + $install = $aWebUnit['install'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$web['domain']; + + $path = $aWebUnit['path'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$web['desing']; + + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$aData['server']['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо указать пользователя сервера.'), $mcache); + + $u = $sql->get(); + + // sql запросы + $sql_q = ''; + + if(isset($aWebSQL[$aData['type']]['update'])) + foreach($aWebSQL[$aData['type']]['update'] as $query) + $sql_q .= "mysql --login-path=local ".$web['login']." -e \"".sys::updtext($query, array('passwd' => $aData['passwd'], 'mail' => $u['mail']))."\";"; + + $cat = isset($aWebdbConf[$aData['type']]) ? 'cat '.$install.$aWebdbConf[$aData['type']]['file'].' > '.$path.$aWebdbConf[$aData['type']]['file'].';' : ''; + $chmod = isset($aWebChmod[$aData['type']]) ? $aWebChmod[$aData['type']] : ''; + + $ssh->set($cat + .'cd '.$install.' && sudo -u web'.$web['uid'].' screen -dmS u_w_'.$web['uid'].' sh -c "YES | cp -rf '.$path.'/. .; '.$chmod.'";' + .$sql_q); // sql запрос + + $sql->query('UPDATE `web` set `update`="'.$start_point.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + public static function delete($aData = array(), $mcache) + { + global $sql; + + include(DATA.'web.php'); + + $stack = web::stack($aData, '`id`, `uid`, `unit`, `domain`, `login`'); + + if(!$sql->num($stack)) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $mcache); + + $web = $sql->get($stack); + + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + // Директория дополнительной услуги + $delete = ''; + + if($web['domain'] != '') + $delete = 'screen -dmS r_w_'.$web['uid'].' rm -r '.$aWebUnit['install'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$web['domain'].';'; + + $ip = sys::first(explode(':', $unit['address'])); + + $aDomain = explode('.', $web['domain']); + $zone = array_pop($aDomain); + + // Удаление поддомена + if($aData['type'] != 'mysql') + { + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['domain']['delete'], array('subdomain' => $web['domain'], 'domain' => end($aDomain).'.'.$zone, 'ip' => $ip))), true); + + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + sys::outjs(array('e' => 'Не удалось удалить поддомен, обратитесь в тех.поддержку.'), $mcache); + } + + // Удаление задания crontab + if(isset($aWebUnit['isp']['crontab'][$aData['type']]['delete']) && isset($aData['cron'])) + { + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['crontab'][$aData['type']]['delete'], array('data' => $aData['cron']))), true); + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + sys::outjs(array('e' => 'Не удалось удалить задание, обратитесь в тех.поддержку.'), $mcache); + } + + $sql_q = isset($aWebSQL[$aData['type']]) ? "mysql --login-path=local -e \"DROP DATABASE IF EXISTS ".$web['login']."; DROP USER ".$web['login']."\"" : ''; + + $ssh->set('rm /etc/apache2/sites-enabled/'.$web['domain'].';' // Удаление настроек апач + .$delete // Удаление файлов + .'userdel web'.$web['uid'].';' // Удаление пользователя + .'screen -dmS apache_reload_'.$web['uid'].' service apache2 reload;' // Перезагрузить конфигурации апач + .$sql_q); // sql запрос + + $sql->query('DELETE FROM `web` WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + public static function connect($aData = array(), $mcache) + { + global $cfg, $sql, $start_point; + + include(DATA.'web.php'); + + $sql->query('SELECT `id`, `uid`, `unit`, `game`, `user`, `tarif`, `address`, `status`, `name` FROM `servers` WHERE `id`="'.$aData['server'].'" AND `user`="'.$aData['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Игровой сервер не найден.'), $mcache); + + $server = $sql->get(); + + // Проверка статуса игрового сервера + if(!in_array($server['status'], array('working', 'off', 'start', 'restart', 'change'))) + sys::outjs(array('e' => 'Игровой сервер недоступен для подключения.'), $mcache); + + // Проверка установки плагина + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$server['id'].'" AND `plugin`="'.$aWebConnect[$aData['type']][$server['game']].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('i' => 'Для подключения, необходимо установить плагин.', 'pid' => $aWebConnect[$aData['type']][$server['game']]), $mcache); + + $aData['server'] = array_merge($server, array('id' => $aData['server'])); + + $stack = web::stack($aData, '`config`, `unit`, `login`'); + + if(!$sql->num($stack)) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $mcache); + + $web = $sql->get($stack); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `passwd`, `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория игр. сервера + $dir = $tarif['install'].$server['uid'].'/'; + + // Взять rcon_password + $get = explode(' ', str_replace('"', '', trim($ssh->get('cat '.$dir.$aData['cfg'].' | grep rcon_password')))); + + $rcon = trim(end($get)); + + if(!isset($rcon{0})) + sys::outjs(array('r' => 'Необходимо установить rcon пароль (rcon_password).', 'url' => $cfg['http'].'servers/id/'.$server['id'].'/section/settings/subsection/server'), $mcache); + + $temp = sys::temp(sys::updtext(base64_decode($web['config']), $aData['orcfg'])); + + $ssh->setfile($temp, $dir.$aData['file'], 0644); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + // sql запросы + $sql_q = ''; + + list($ip, $port) = explode(':', $server['address']); + + if(isset($aWebSQL[$aData['type']]['connect'])) + foreach($aWebSQL[$aData['type']]['connect'] as $query) + $sql_q .= "mysql --login-path=local ".$web['login']." -e \"".sys::updtext($query, + array_merge(array('id' => $aData['server']['id'], 'rcon' => $rcon, 'address' => $server['address'], 'ip' => $ip, 'port' => $port, 'name' => $server['name'], 'time' => $start_point), $aData['orsql']))."\";"; + + $ssh->set('chown server'.$server['uid'].':servers '.$dir.$aData['file'].';' // Смена владельца файла + .$sql_q); // sql запросы + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + public static function passwd($aData = array(), $mcache) + { + global $sql; + + include(DATA.'web.php'); + + $stack = web::stack($aData); + + if(!$sql->num($stack)) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $mcache); + + $web = $sql->get($stack); + + $passwd = sys::passwd($aWebParam[$aData['type']]['passwd']); + + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $mcache); + + $sql_q = ''; + + if(isset($aWebSQL[$aData['type']]['passwd'])) + foreach($aWebSQL[$aData['type']]['passwd'] as $query) + $sql_q .= "mysql --login-path=local ".$web['login']." -e \"".sys::updtext($query, array('passwd' => $passwd))."\";"; + + $ssh->set($sql_q); + + $sql->query('UPDATE `web` set `passwd`="'.$passwd.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $mcache); + } + + public static function stack($aData, $select = '`id`, `unit`, `login`') + { + global $sql; + + include(DATA.'web.php'); + + switch($aWebInstall[$aData['server']['game']][$aData['type']]) + { + case 'server': + return $sql->query('SELECT '.$select.' FROM `web` WHERE `type`="'.$aData['type'].'" AND `server`="'.$aData['server']['id'].'" LIMIT 1'); + + case 'user': + return $sql->query('SELECT '.$select.' FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$aData['server']['user'].'" LIMIT 1'); + + case 'unit': + return $sql->query('SELECT '.$select.' FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$aData['server']['user'].'" AND `unit`="'.$aData['server']['unit'].'" LIMIT 1'); + } + + return NULL; + } + + public static function unit($aWebUnit, $type, $id) + { + global $sql; + + if($aWebUnit['unit'][$type] == 'local') + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + return $sql->get(); + } + + return array('address' => $aWebUnit['address'], 'passwd' => $aWebUnit['passwd']); + } + } +?> \ No newline at end of file diff --git a/system/library/zip.php b/system/library/zip.php new file mode 100644 index 0000000..8f46a05 --- /dev/null +++ b/system/library/zip.php @@ -0,0 +1,5696 @@ +zipname = $p_zipname; + $this->zip_fd = 0; + $this->magic_quotes_status = -1; + + // ----- Return + return; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // create($p_filelist, $p_add_dir="", $p_remove_dir="") + // create($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two different synopsis. The first one is historical. + // This method creates a Zip Archive. The Zip file is created in the + // filesystem. The files and directories indicated in $p_filelist + // are added in the archive. See the parameters description for the + // supported format of $p_filelist. + // When a directory is in the list, the directory and its content is added + // in the archive. + // In this synopsis, the function takes an optional variable list of + // options. See bellow the supported options. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function create($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove from the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Invalid number / type of arguments"); + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + if ($v_string != '') { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + else { + } + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // add($p_filelist, $p_add_dir="", $p_remove_dir="") + // add($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two synopsis. The first one is historical. + // This methods add the list of files in an existing archive. + // If a file with the same name already exists, it is added at the end of the + // archive, the first one is still present. + // If the archive does not exist, it is created. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_OPT_ADD_COMMENT : + // PCLZIP_OPT_PREPEND_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function add($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_ADD_COMMENT => 'optional', + PCLZIP_OPT_PREPEND_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : listContent() + // Description : + // This public method, gives the list of the files and directories, with their + // properties. + // The properties of each entries in the list are (used also in other functions) : + // filename : Name of the file. For a create or add action it is the filename + // given by the user. For an extract function it is the filename + // of the extracted file. + // stored_filename : Name of the file / directory stored in the archive. + // size : Size of the stored file. + // compressed_size : Size of the file's data compressed in the archive + // (without the headers overhead) + // mtime : Last known modification date of the file (UNIX timestamp) + // comment : Comment associated with the file + // folder : true | false + // index : index of the file in the archive + // status : status of the action (depending of the action) : + // Values are : + // ok : OK ! + // filtered : the file / dir is not extracted (filtered by user) + // already_a_directory : the file can not be extracted because a + // directory with the same name already exists + // write_protected : the file can not be extracted because a file + // with the same name already exists and is + // write protected + // newer_exist : the file was not extracted because a newer file exists + // path_creation_fail : the file is not extracted because the folder + // does not exist and can not be created + // write_error : the file was not extracted because there was a + // error while writing the file + // read_error : the file was not extracted because there was a error + // while reading the file + // invalid_header : the file was not extracted because of an archive + // format error (bad file header) + // Note that each time a method can continue operating when there + // is an action error on a file, the error is only logged in the file status. + // Return Values : + // 0 on an unrecoverable failure, + // The list of the files in the archive. + // -------------------------------------------------------------------------------- + function listContent() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Call the extracting fct + $p_list = array(); + if (($v_result = $this->privList($p_list)) != 1) + { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // extract($p_path="./", $p_remove_path="") + // extract([$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method extract all the files / directories from the archive to the + // folder indicated in $p_path. + // If you want to ignore the 'root' part of path of the memorized files + // you can indicate this in the optional $p_remove_path parameter. + // By default, if a newer file with the same name already exists, the + // file is not extracted. + // + // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions + // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append + // at the end of the path value of PCLZIP_OPT_PATH. + // Parameters : + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 or a negative value on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function extract() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Trace + + // ----- Call the extracting fct + $p_list = array(); + $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, + $v_remove_all_path, $v_options); + if ($v_result < 1) { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + + // -------------------------------------------------------------------------------- + // Function : + // extractByIndex($p_index, $p_path="./", $p_remove_path="") + // extractByIndex($p_index, [$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method is doing a partial extract of the archive. + // The extracted files or folders are identified by their index in the + // archive (from 0 to n). + // Note that if the index identify a folder, only the folder entry is + // extracted, not all the files included in the archive. + // Parameters : + // $p_index : A single index (integer) or a string of indexes of files to + // extract. The form of the string is "0,4-6,8-12" with only numbers + // and '-' for range or ',' to separate ranges. No spaces or ';' + // are allowed. + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and + // not as files. + // The resulting content is in a new field 'content' in the file + // structure. + // This option must be used alone (any other options are ignored). + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + //function extractByIndex($p_index, options...) + function extractByIndex($p_index) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + } + else { + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Trace + + // ----- Trick + // Here I want to reuse extractByRule(), so I need to parse the $p_index + // with privParseOptions() + $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); + $v_options_trick = array(); + $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, + array (PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Call the extracting fct + if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // delete([$p_option, $p_option_value, ...]) + // Description : + // This method removes files from the archive. + // If no parameters are given, then all the archive is emptied. + // Parameters : + // None or optional arguments. + // Options : + // PCLZIP_OPT_BY_INDEX : + // PCLZIP_OPT_BY_NAME : + // PCLZIP_OPT_BY_EREG : + // PCLZIP_OPT_BY_PREG : + // Return Values : + // 0 on failure, + // The list of the files which are still present in the archive. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function delete() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Call the delete fct + $v_list = array(); + if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { + $this->privSwapBackMagicQuotes(); + unset($v_list); + return(0); + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : deleteByIndex() + // Description : + // ***** Deprecated ***** + // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. + // -------------------------------------------------------------------------------- + function deleteByIndex($p_index) + { + + $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : properties() + // Description : + // This method gives the properties of the archive. + // The properties are : + // nb : Number of files in the archive + // comment : Comment associated with the archive file + // status : not_exist, ok + // Parameters : + // None + // Return Values : + // 0 on failure, + // An array with the archive properties. + // -------------------------------------------------------------------------------- + function properties() + { + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + $this->privSwapBackMagicQuotes(); + return(0); + } + + // ----- Default properties + $v_prop = array(); + $v_prop['comment'] = ''; + $v_prop['nb'] = 0; + $v_prop['status'] = 'not_exist'; + + // ----- Look if file exists + if (@is_file($this->zipname)) + { + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return 0; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return 0; + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Set the user attributes + $v_prop['comment'] = $v_central_dir['comment']; + $v_prop['nb'] = $v_central_dir['entries']; + $v_prop['status'] = 'ok'; + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_prop; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : duplicate() + // Description : + // This method creates an archive by copying the content of an other one. If + // the archive already exist, it is replaced by the new one without any warning. + // Parameters : + // $p_archive : The filename of a valid archive, or + // a valid PclZip object. + // Return Values : + // 1 on success. + // 0 or a negative value on error (error code). + // -------------------------------------------------------------------------------- + function duplicate($p_archive) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the $p_archive is a PclZip object + if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) + { + + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive->zipname); + } + + // ----- Look if the $p_archive is a string (so a filename) + else if (is_string($p_archive)) + { + + // ----- Check that $p_archive is a valid zip file + // TBC : Should also check the archive format + if (!is_file($p_archive)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); + $v_result = PCLZIP_ERR_MISSING_FILE; + } + else { + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive); + } + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : merge() + // Description : + // This method merge the $p_archive_to_add archive at the end of the current + // one ($this). + // If the archive ($this) does not exist, the merge becomes a duplicate. + // If the $p_archive_to_add archive does not exist, the merge is a success. + // Parameters : + // $p_archive_to_add : It can be directly the filename of a valid zip archive, + // or a PclZip object archive. + // Return Values : + // 1 on success, + // 0 or negative values on error (see below). + // -------------------------------------------------------------------------------- + function merge($p_archive_to_add) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Look if the $p_archive_to_add is a PclZip object + if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) + { + + // ----- Merge the archive + $v_result = $this->privMerge($p_archive_to_add); + } + + // ----- Look if the $p_archive_to_add is a string (so a filename) + else if (is_string($p_archive_to_add)) + { + + // ----- Create a temporary archive + $v_object_archive = new PclZip($p_archive_to_add); + + // ----- Merge the archive + $v_result = $this->privMerge($v_object_archive); + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : errorCode() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorCode() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorCode()); + } + else { + return($this->error_code); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorName() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorName($p_with_code=false) + { + $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', + PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', + PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', + PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', + PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', + PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', + PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', + PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', + PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', + PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', + PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', + PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', + PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', + PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', + PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', + PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', + PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', + PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', + PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' + ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' + ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' + ); + + if (isset($v_name[$this->error_code])) { + $v_value = $v_name[$this->error_code]; + } + else { + $v_value = 'NoName'; + } + + if ($p_with_code) { + return($v_value.' ('.$this->error_code.')'); + } + else { + return($v_value); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorInfo() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorInfo($p_full=false) + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorString()); + } + else { + if ($p_full) { + return($this->errorName(true)." : ".$this->error_string); + } + else { + return($this->error_string." [code ".$this->error_code."]"); + } + } + } + // -------------------------------------------------------------------------------- + + +// -------------------------------------------------------------------------------- +// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** +// ***** ***** +// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** +// -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : privCheckFormat() + // Description : + // This method check that the archive exists and is a valid zip archive. + // Several level of check exists. (futur) + // Parameters : + // $p_level : Level of check. Default 0. + // 0 : Check the first bytes (magic codes) (default value)) + // 1 : 0 + Check the central directory (futur) + // 2 : 1 + Check each file header (futur) + // Return Values : + // true on success, + // false on error, the error code is set. + // -------------------------------------------------------------------------------- + function privCheckFormat($p_level=0) + { + $v_result = true; + + // ----- Reset the file system cache + clearstatcache(); + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the file exits + if (!is_file($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); + return(false); + } + + // ----- Check that the file is readeable + if (!is_readable($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); + return(false); + } + + // ----- Check the magic code + // TBC + + // ----- Check the central header + // TBC + + // ----- Check each file header + // TBC + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privParseOptions() + // Description : + // This internal methods reads the variable list of arguments ($p_options_list, + // $p_size) and generate an array with the options and values ($v_result_list). + // $v_requested_options contains the options that can be present and those that + // must be present. + // $v_requested_options is an array, with the option value as key, and 'optional', + // or 'mandatory' as value. + // Parameters : + // See above. + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) + { + $v_result=1; + + // ----- Read the options + $i=0; + while ($i<$p_size) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$p_options_list[$i]])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for next option + switch ($p_options_list[$i]) { + // ----- Look for options that request a path value + case PCLZIP_OPT_PATH : + case PCLZIP_OPT_REMOVE_PATH : + case PCLZIP_OPT_ADD_PATH : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_THRESHOLD : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + // ----- Check the value + $v_value = $p_options_list[$i+1]; + if ((!is_integer($v_value)) || ($v_value<0)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Get the value (and convert it in bytes) + $v_result_list[$p_options_list[$i]] = $v_value*1048576; + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_ON : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_TEMP_FILE_OFF : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'"); + return PclZip::errorCode(); + } + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if ( is_string($p_options_list[$i+1]) + && ($p_options_list[$i+1] != '')) { + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + } + else { + } + break; + + // ----- Look for options that request an array of string for value + case PCLZIP_OPT_BY_NAME : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an EREG or PREG expression + case PCLZIP_OPT_BY_EREG : + // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG + // to PCLZIP_OPT_BY_PREG + $p_options_list[$i] = PCLZIP_OPT_BY_PREG; + case PCLZIP_OPT_BY_PREG : + //case PCLZIP_OPT_CRYPT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that takes a string + case PCLZIP_OPT_COMMENT : + case PCLZIP_OPT_ADD_COMMENT : + case PCLZIP_OPT_PREPEND_COMMENT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, + "Missing parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, + "Wrong parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an array of index + case PCLZIP_OPT_BY_INDEX : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_work_list = array(); + if (is_string($p_options_list[$i+1])) { + + // ----- Remove spaces + $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); + + // ----- Parse items + $v_work_list = explode(",", $p_options_list[$i+1]); + } + else if (is_integer($p_options_list[$i+1])) { + $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_work_list = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Reduce the index list + // each index item in the list must be a couple with a start and + // an end value : [0,3], [5-5], [8-10], ... + // ----- Check the format of each item + $v_sort_flag=false; + $v_sort_value=0; + for ($j=0; $j= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + $i++; + break; + + // ----- Look for options that request a call-back + case PCLZIP_CB_PRE_EXTRACT : + case PCLZIP_CB_POST_EXTRACT : + case PCLZIP_CB_PRE_ADD : + case PCLZIP_CB_POST_ADD : + /* for futur use + case PCLZIP_CB_PRE_DELETE : + case PCLZIP_CB_POST_DELETE : + case PCLZIP_CB_PRE_LIST : + case PCLZIP_CB_POST_LIST : + */ + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_function_name = $p_options_list[$i+1]; + + // ----- Check that the value is a valid existing function + if (!function_exists($v_function_name)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Set the attribute + $v_result_list[$p_options_list[$i]] = $v_function_name; + $i++; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '" + .$p_options_list[$i]."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Next options + $i++; + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($v_result_list[$key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + + // ----- Return + return PclZip::errorCode(); + } + } + } + } + + // ----- Look for default values + if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOptionDefaultThreshold() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privOptionDefaultThreshold(&$p_options) + { + $v_result=1; + + if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) { + return $v_result; + } + + // ----- Get 'memory_limit' configuration value + $v_memory_limit = ini_get('memory_limit'); + $v_memory_limit = trim($v_memory_limit); + $last = strtolower(substr($v_memory_limit, -1)); + + if($last == 'g') + //$v_memory_limit = $v_memory_limit*1024*1024*1024; + $v_memory_limit = $v_memory_limit*1073741824; + if($last == 'm') + //$v_memory_limit = $v_memory_limit*1024*1024; + $v_memory_limit = $v_memory_limit*1048576; + if($last == 'k') + $v_memory_limit = $v_memory_limit*1024; + + $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO); + + + // ----- Sanity check : No threshold if value lower than 1M + if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) { + unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrParseAtt() + // Description : + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) + { + $v_result=1; + + // ----- For each file in the list check the attributes + foreach ($p_file_list as $v_key => $v_value) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$v_key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for attribute + switch ($v_key) { + case PCLZIP_ATT_FILE_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['filename'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['filename'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + break; + + case PCLZIP_ATT_FILE_NEW_SHORT_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_short_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + case PCLZIP_ATT_FILE_NEW_FULL_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_full_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + // ----- Look for options that takes a string + case PCLZIP_ATT_FILE_COMMENT : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['comment'] = $v_value; + break; + + case PCLZIP_ATT_FILE_MTIME : + if (!is_integer($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['mtime'] = $v_value; + break; + + case PCLZIP_ATT_FILE_CONTENT : + $p_filedescr['content'] = $v_value; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '".$v_key."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($p_file_list[$key])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + return PclZip::errorCode(); + } + } + } + } + + // end foreach + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrExpand() + // Description : + // This method look for each item of the list to see if its a file, a folder + // or a string to be added as file. For any other type of files (link, other) + // just ignore the item. + // Then prepare the information that will be stored for that file. + // When its a folder, expand the folder with all the files that are in that + // folder (recursively). + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrExpand(&$p_filedescr_list, &$p_options) + { + $v_result=1; + + // ----- Create a result list + $v_result_list = array(); + + // ----- Look each entry + for ($i=0; $iprivCalculateStoredFilename($v_descr, $p_options); + + // ----- Add the descriptor in result list + $v_result_list[sizeof($v_result_list)] = $v_descr; + + // ----- Look for folder + if ($v_descr['type'] == 'folder') { + // ----- List of items in folder + $v_dirlist_descr = array(); + $v_dirlist_nb = 0; + if ($v_folder_handler = @opendir($v_descr['filename'])) { + while (($v_item_handler = @readdir($v_folder_handler)) !== false) { + + // ----- Skip '.' and '..' + if (($v_item_handler == '.') || ($v_item_handler == '..')) { + continue; + } + + // ----- Compose the full filename + $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; + + // ----- Look for different stored filename + // Because the name of the folder was changed, the name of the + // files/sub-folders also change + if (($v_descr['stored_filename'] != $v_descr['filename']) + && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) { + if ($v_descr['stored_filename'] != '') { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; + } + else { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; + } + } + + $v_dirlist_nb++; + } + + @closedir($v_folder_handler); + } + else { + // TBC : unable to open folder in read mode + } + + // ----- Expand each element of the list + if ($v_dirlist_nb != 0) { + // ----- Expand + if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { + return $v_result; + } + + // ----- Concat the resulting list + $v_result_list = array_merge($v_result_list, $v_dirlist_descr); + } + else { + } + + // ----- Free local array + unset($v_dirlist_descr); + } + } + + // ----- Get the result list + $p_filedescr_list = $v_result_list; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCreate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCreate($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the file in write mode + if (($v_result = $this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Add the list of files + $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); + + // ----- Close + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAdd() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAdd($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Look if the archive exists or is empty + if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) + { + + // ----- Do a create + $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); + + // ----- Return + return $v_result; + } + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Create the Central Dir files header + for ($i=0, $v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = $v_central_dir['comment']; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { + $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOpenFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privOpenFd($p_mode) + { + $v_result=1; + + // ----- Look if already open + if ($this->zip_fd != 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCloseFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privCloseFd() + { + $v_result=1; + + if ($this->zip_fd != 0) + @fclose($this->zip_fd); + $this->zip_fd = 0; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddList() + // Description : + // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is + // different from the real path of the file. This is usefull if you want to have PclTar + // running in any directory, and memorize relative path from an other directory. + // Parameters : + // $p_list : An array containing the file or directory names to add in the tar + // $p_result_list : list of added files with their properties (specially the status field) + // $p_add_dir : Path to add in the filename path archived + // $p_remove_dir : Path to remove in the filename path archived + // Return Values : + // -------------------------------------------------------------------------------- +// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) + function privAddList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Create the Central Dir files header + for ($i=0,$v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileList() + // Description : + // Parameters : + // $p_filedescr_list : An array containing the file description + // or directory names to add in the zip + // $p_result_list : list of added files with their properties (specially the status field) + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_header = array(); + + // ----- Recuperate the current number of elt in list + $v_nb = sizeof($p_result_list); + + // ----- Loop on the files + for ($j=0; ($jprivAddFile($p_filedescr_list[$j], $v_header, + $p_options); + if ($v_result != 1) { + return $v_result; + } + + // ----- Store the file infos + $p_result_list[$v_nb++] = $v_header; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=1; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + // TBC : Already done in the fileAtt check ... ? + if ($p_filename == "") { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for a stored different filename + /* TBC : Removed + if (isset($p_filedescr['stored_filename'])) { + $v_stored_filename = $p_filedescr['stored_filename']; + } + else { + $v_stored_filename = $p_filedescr['stored_filename']; + } + */ + + // ----- Set the file properties + clearstatcache(); + $p_header['version'] = 20; + $p_header['version_extracted'] = 10; + $p_header['flag'] = 0; + $p_header['compression'] = 0; + $p_header['crc'] = 0; + $p_header['compressed_size'] = 0; + $p_header['filename_len'] = strlen($p_filename); + $p_header['extra_len'] = 0; + $p_header['disk'] = 0; + $p_header['internal'] = 0; + $p_header['offset'] = 0; + $p_header['filename'] = $p_filename; +// TBC : Removed $p_header['stored_filename'] = $v_stored_filename; + $p_header['stored_filename'] = $p_filedescr['stored_filename']; + $p_header['extra'] = ''; + $p_header['status'] = 'ok'; + $p_header['index'] = -1; + + // ----- Look for regular file + if ($p_filedescr['type']=='file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for regular folder + else if ($p_filedescr['type']=='folder') { + $p_header['external'] = 0x00000010; + $p_header['mtime'] = filemtime($p_filename); + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for virtual file + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = strlen($p_filedescr['content']); + } + + + // ----- Look for filetime + if (isset($p_filedescr['mtime'])) { + $p_header['mtime'] = $p_filedescr['mtime']; + } + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['mtime'] = time(); + } + else { + $p_header['mtime'] = filemtime($p_filename); + } + + // ------ Look for file comment + if (isset($p_filedescr['comment'])) { + $p_header['comment_len'] = strlen($p_filedescr['comment']); + $p_header['comment'] = $p_filedescr['comment']; + } + else { + $p_header['comment_len'] = 0; + $p_header['comment'] = ''; + } + + // ----- Look for pre-add callback + if (isset($p_options[PCLZIP_CB_PRE_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_header['status'] = "skipped"; + $v_result = 1; + } + + // ----- Update the informations + // Only some fields can be modified + if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { + $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); + } + } + + // ----- Look for empty stored filename + if ($p_header['stored_filename'] == "") { + $p_header['status'] = "filtered"; + } + + // ----- Check the path length + if (strlen($p_header['stored_filename']) > 0xFF) { + $p_header['status'] = 'filename_too_long'; + } + + // ----- Look if no error, or file not skipped + if ($p_header['status'] == 'ok') { + + // ----- Look for a file + if ($p_filedescr['type'] == 'file') { + // ----- Look for using temporary file to zip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) { + $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Use "in memory" zip algo + else { + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Read the file content + $v_content = @fread($v_file, $p_header['size']); + + // ----- Close the file + @fclose($v_file); + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + + } + + } + + // ----- Look for a virtual file (a file from string) + else if ($p_filedescr['type'] == 'virtual_file') { + + $v_content = $p_filedescr['content']; + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + } + + // ----- Look for a directory + else if ($p_filedescr['type'] == 'folder') { + // ----- Look for directory last '/' + if (@substr($p_header['stored_filename'], -1) != '/') { + $p_header['stored_filename'] .= '/'; + } + + // ----- Set the file properties + $p_header['size'] = 0; + //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked + $p_header['external'] = 0x00000010; // Value for a folder : to be checked + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) + { + return $v_result; + } + } + } + + // ----- Look for post-add callback + if (isset($p_options[PCLZIP_CB_POST_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Ignored + $v_result = 1; + } + + // ----- Update the informations + // Nothing can be modified + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=PCLZIP_ERR_NO_ERROR; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Creates a compressed temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = filesize($p_filename); + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @gzputs($v_file_compressed, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file); + @gzclose($v_file_compressed); + + // ----- Check the minimum file size + if (filesize($v_gzip_temp_name) < 18) { + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes'); + return PclZip::errorCode(); + } + + // ----- Extract the compressed attributes + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the gzip file header + $v_binary_data = @fread($v_file_compressed, 10); + $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data); + + // ----- Check some parameters + $v_data_header['os'] = bin2hex($v_data_header['os']); + + // ----- Read the gzip file footer + @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8); + $v_binary_data = @fread($v_file_compressed, 8); + $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data); + + // ----- Set the attributes + $p_header['compression'] = ord($v_data_header['cm']); + //$p_header['mtime'] = $v_data_header['mtime']; + $p_header['crc'] = $v_data_footer['crc']; + $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18; + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + return $v_result; + } + + // ----- Add the compressed data + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) + { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + fseek($v_file_compressed, 10); + $v_size = $p_header['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file_compressed, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Unlink the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCalculateStoredFilename() + // Description : + // Based on file descriptor properties and global options, this method + // calculate the filename that will be stored in the archive. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCalculateStoredFilename(&$p_filedescr, &$p_options) + { + $v_result=1; + + // ----- Working variables + $p_filename = $p_filedescr['filename']; + if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { + $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; + } + else { + $p_add_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { + $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; + } + else { + $p_remove_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + else { + $p_remove_all_dir = 0; + } + + + // ----- Look for full name change + if (isset($p_filedescr['new_full_name'])) { + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']); + } + + // ----- Look for path and/or short name change + else { + + // ----- Look for short name change + // Its when we cahnge just the filename but not the path + if (isset($p_filedescr['new_short_name'])) { + $v_path_info = pathinfo($p_filename); + $v_dir = ''; + if ($v_path_info['dirname'] != '') { + $v_dir = $v_path_info['dirname'].'/'; + } + $v_stored_filename = $v_dir.$p_filedescr['new_short_name']; + } + else { + // ----- Calculate the stored filename + $v_stored_filename = $p_filename; + } + + // ----- Look for all path to remove + if ($p_remove_all_dir) { + $v_stored_filename = basename($p_filename); + } + // ----- Look for partial path remove + else if ($p_remove_dir != "") { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= "/"; + + if ( (substr($p_filename, 0, 2) == "./") + || (substr($p_remove_dir, 0, 2) == "./")) { + + if ( (substr($p_filename, 0, 2) == "./") + && (substr($p_remove_dir, 0, 2) != "./")) { + $p_remove_dir = "./".$p_remove_dir; + } + if ( (substr($p_filename, 0, 2) != "./") + && (substr($p_remove_dir, 0, 2) == "./")) { + $p_remove_dir = substr($p_remove_dir, 2); + } + } + + $v_compare = PclZipUtilPathInclusion($p_remove_dir, + $v_stored_filename); + if ($v_compare > 0) { + if ($v_compare == 2) { + $v_stored_filename = ""; + } + else { + $v_stored_filename = substr($v_stored_filename, + strlen($p_remove_dir)); + } + } + } + + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename); + + // ----- Look for path to add + if ($p_add_dir != "") { + if (substr($p_add_dir, -1) == "/") + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir."/".$v_stored_filename; + } + } + + // ----- Filename (reduce the path of stored name) + $v_stored_filename = PclZipUtilPathReduction($v_stored_filename); + $p_filedescr['stored_filename'] = $v_stored_filename; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteFileHeader(&$p_header) + { + $v_result=1; + + // ----- Store the offset position of the file + $p_header['offset'] = ftell($this->zip_fd); + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + // ----- Packed data + $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, + $p_header['version_extracted'], $p_header['flag'], + $p_header['compression'], $v_mtime, $v_mdate, + $p_header['crc'], $p_header['compressed_size'], + $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len']); + + // ----- Write the first 148 bytes of the header in the archive + fputs($this->zip_fd, $v_binary_data, 30); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralFileHeader(&$p_header) + { + $v_result=1; + + // TBC + //for(reset($p_header); $key = key($p_header); next($p_header)) { + //} + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + + // ----- Packed data + $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, + $p_header['version'], $p_header['version_extracted'], + $p_header['flag'], $p_header['compression'], + $v_mtime, $v_mdate, $p_header['crc'], + $p_header['compressed_size'], $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len'], $p_header['comment_len'], + $p_header['disk'], $p_header['internal'], + $p_header['external'], $p_header['offset']); + + // ----- Write the 42 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 46); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + if ($p_header['comment_len'] != 0) + { + fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) + { + $v_result=1; + + // ----- Packed data + $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, + $p_nb_entries, $p_size, + $p_offset, strlen($p_comment)); + + // ----- Write the 22 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 22); + + // ----- Write the variable fields + if (strlen($p_comment) != 0) + { + fputs($this->zip_fd, $p_comment, strlen($p_comment)); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privList() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privList(&$p_list) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of Central Dir + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_central_dir['offset'])) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + for ($i=0; $i<$v_central_dir['entries']; $i++) + { + // ----- Read the file header + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + $v_header['index'] = $i; + + // ----- Get the only interesting attributes + $this->privConvertHeader2FileInfo($v_header, $p_list[$i]); + unset($v_header); + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privConvertHeader2FileInfo() + // Description : + // This function takes the file informations from the central directory + // entries and extract the interesting parameters that will be given back. + // The resulting file infos are set in the array $p_info + // $p_info['filename'] : Filename with full path. Given by user (add), + // extracted in the filesystem (extract). + // $p_info['stored_filename'] : Stored filename in the archive. + // $p_info['size'] = Size of the file. + // $p_info['compressed_size'] = Compressed size of the file. + // $p_info['mtime'] = Last modification date of the file. + // $p_info['comment'] = Comment associated with the file. + // $p_info['folder'] = true/false : indicates if the entry is a folder or not. + // $p_info['status'] = status of the action on the file. + // $p_info['crc'] = CRC of the file content. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privConvertHeader2FileInfo($p_header, &$p_info) + { + $v_result=1; + + // ----- Get the interesting attributes + $v_temp_path = PclZipUtilPathReduction($p_header['filename']); + $p_info['filename'] = $v_temp_path; + $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']); + $p_info['stored_filename'] = $v_temp_path; + $p_info['size'] = $p_header['size']; + $p_info['compressed_size'] = $p_header['compressed_size']; + $p_info['mtime'] = $p_header['mtime']; + $p_info['comment'] = $p_header['comment']; + $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); + $p_info['index'] = $p_header['index']; + $p_info['status'] = $p_header['status']; + $p_info['crc'] = $p_header['crc']; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractByRule() + // Description : + // Extract a file or directory depending of rules (by index, by name, ...) + // Parameters : + // $p_file_list : An array where will be placed the properties of each + // extracted file + // $p_path : Path to add while writing the extracted files + // $p_remove_path : Path to remove (from the file memorized path) while writing the + // extracted files. If the path does not match the file path, + // the file is extracted with its memorized path. + // $p_remove_path does not apply to 'list' mode. + // $p_path and $p_remove_path are commulative. + // Return Values : + // 1 on success,0 or less on error (see error code list) + // -------------------------------------------------------------------------------- + function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check the path + if ( ($p_path == "") + || ( (substr($p_path, 0, 1) != "/") + && (substr($p_path, 0, 3) != "../") + && (substr($p_path,1,2)!=":/"))) + $p_path = "./".$p_path; + + // ----- Reduce the path last (and duplicated) '/' + if (($p_path != "./") && ($p_path != "/")) + { + // ----- Look for the path end '/' + while (substr($p_path, -1) == "/") + { + $p_path = substr($p_path, 0, strlen($p_path)-1); + } + } + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) + { + $p_remove_path .= '/'; + } + $p_remove_path_size = strlen($p_remove_path); + + // ----- Open the zip file + if (($v_result = $this->privOpenFd('rb')) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + + // ----- Read each entry + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read next Central dir entry + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Store the index + $v_header['index'] = $i; + + // ----- Store the file position + $v_pos_entry = ftell($this->zip_fd); + + // ----- Look for the specific extract rules + $v_extract = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_extract = true; + } + } + // ----- Look for a filename + elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_extract = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_extract = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + + // ----- Look for no rule, which means extract all the archive + else { + $v_extract = true; + } + + // ----- Check compression method + if ( ($v_extract) + && ( ($v_header['compression'] != 8) + && ($v_header['compression'] != 0))) { + $v_header['status'] = 'unsupported_compression'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, + "Filename '".$v_header['stored_filename']."' is " + ."compressed by an unsupported compression " + ."method (".$v_header['compression'].") "); + + return PclZip::errorCode(); + } + } + + // ----- Check encrypted files + if (($v_extract) && (($v_header['flag'] & 1) == 1)) { + $v_header['status'] = 'unsupported_encryption'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, + "Unsupported encryption for " + ." filename '".$v_header['stored_filename'] + ."'"); + + return PclZip::errorCode(); + } + } + + // ----- Look for real extraction + if (($v_extract) && ($v_header['status'] != 'ok')) { + $v_result = $this->privConvertHeader2FileInfo($v_header, + $p_file_list[$v_nb_extracted++]); + if ($v_result != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + $v_extract = false; + } + + // ----- Look for real extraction + if ($v_extract) + { + + // ----- Go to the file position + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_header['offset'])) + { + // ----- Close the zip file + $this->privCloseFd(); + + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for extraction as string + if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { + + $v_string = ''; + + // ----- Extracting the file + $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Set the file content + $p_file_list[$v_nb_extracted]['content'] = $v_string; + + // ----- Next extracted file + $v_nb_extracted++; + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for extraction in standard output + elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) + && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { + // ----- Extracting the file in standard output + $v_result1 = $this->privExtractFileInOutput($v_header, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for normal extraction + else { + // ----- Extracting the file + $v_result1 = $this->privExtractFile($v_header, + $p_path, $p_remove_path, + $p_remove_all_path, + $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + } + } + + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFile() + // Description : + // Parameters : + // Return Values : + // + // 1 : ... ? + // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback + // -------------------------------------------------------------------------------- + function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for all path to remove + if ($p_remove_all_path == true) { + // ----- Look for folder entry that not need to be extracted + if (($p_entry['external']&0x00000010)==0x00000010) { + + $p_entry['status'] = "filtered"; + + return $v_result; + } + + // ----- Get the basename of the path + $p_entry['filename'] = basename($p_entry['filename']); + } + + // ----- Look for path to remove + else if ($p_remove_path != "") + { + if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) + { + + // ----- Change the file status + $p_entry['status'] = "filtered"; + + // ----- Return + return $v_result; + } + + $p_remove_path_size = strlen($p_remove_path); + if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) + { + + // ----- Remove the path + $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); + + } + } + + // ----- Add the path + if ($p_path != '') { + $p_entry['filename'] = $p_path."/".$p_entry['filename']; + } + + // ----- Check a base_dir_restriction + if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { + $v_inclusion + = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], + $p_entry['filename']); + if ($v_inclusion == 0) { + + PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, + "Filename '".$p_entry['filename']."' is " + ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); + + return PclZip::errorCode(); + } + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Look for specific actions while the file exist + if (file_exists($p_entry['filename'])) + { + + // ----- Look if file is a directory + if (is_dir($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "already_a_directory"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, + "Filename '".$p_entry['filename']."' is " + ."already used by an existing directory"); + + return PclZip::errorCode(); + } + } + // ----- Look if file is write protected + else if (!is_writeable($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "write_protected"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Filename '".$p_entry['filename']."' exists " + ."and is write protected"); + + return PclZip::errorCode(); + } + } + + // ----- Look if the extracted file is older + else if (filemtime($p_entry['filename']) > $p_entry['mtime']) + { + // ----- Change the file status + if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) + && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { + } + else { + $p_entry['status'] = "newer_exist"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Newer version of '".$p_entry['filename']."' exists " + ."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); + + return PclZip::errorCode(); + } + } + } + else { + } + } + + // ----- Check the directory availability and create it if necessary + else { + if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) + $v_dir_to_check = $p_entry['filename']; + else if (!strstr($p_entry['filename'], "/")) + $v_dir_to_check = ""; + else + $v_dir_to_check = dirname($p_entry['filename']); + + if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { + + // ----- Change the file status + $p_entry['status'] = "path_creation_fail"; + + // ----- Return + //return $v_result; + $v_result = 1; + } + } + } + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) + { + // ----- Look for not compressed file + if ($p_entry['compression'] == 0) { + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) + { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + // ----- Return + return $v_result; + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + /* Try to speed up the code + $v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_binary_data, $v_read_size); + */ + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Closing the destination file + fclose($v_dest_file); + + // ----- Change the file mtime + touch($p_entry['filename'], $p_entry['mtime']); + + + } + else { + // ----- TBC + // Need to be finished + if (($p_entry['flag'] & 1) == 1) { + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.'); + return PclZip::errorCode(); + } + + + // ----- Look for using temporary file to unzip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) { + $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Look for extract in memory + else { + + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = @gzinflate($v_buffer); + unset($v_buffer); + if ($v_file_content === FALSE) { + + // ----- Change the file status + // TBC + $p_entry['status'] = "error"; + + return $v_result; + } + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + return $v_result; + } + + // ----- Write the uncompressed data + @fwrite($v_dest_file, $v_file_content, $p_entry['size']); + unset($v_file_content); + + // ----- Closing the destination file + @fclose($v_dest_file); + + } + + // ----- Change the file mtime + @touch($p_entry['filename'], $p_entry['mtime']); + } + + // ----- Look for chmod option + if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { + + // ----- Change the mode of the file + @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); + } + + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileUsingTempFile(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Creates a temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + + // ----- Write gz file format header + $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)); + @fwrite($v_dest_file, $v_binary_data, 10); + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Write gz file format footer + $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']); + @fwrite($v_dest_file, $v_binary_data, 8); + + // ----- Close the temporary file + @fclose($v_dest_file); + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + $p_entry['status'] = "write_error"; + return $v_result; + } + + // ----- Open the temporary gz file + if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) { + @fclose($v_dest_file); + $p_entry['status'] = "read_error"; + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['size']; + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($v_src_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + @fclose($v_dest_file); + @gzclose($v_src_file); + + // ----- Delete the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileInOutput() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileInOutput(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) { + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + // ----- Trace + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + if ($p_entry['compressed_size'] == $p_entry['size']) { + + // ----- Read the file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Send the file to the output + echo $v_buffer; + unset($v_buffer); + } + else { + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = gzinflate($v_buffer); + unset($v_buffer); + + // ----- Send the file to the output + echo $v_file_content; + unset($v_file_content); + } + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileAsString() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) + { + $v_result=1; + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + // if ($p_entry['compressed_size'] == $p_entry['size']) + if ($p_entry['compression'] == 0) { + + // ----- Reading the file + $p_string = @fread($this->zip_fd, $p_entry['compressed_size']); + } + else { + + // ----- Reading the file + $v_data = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + if (($p_string = @gzinflate($v_data)) === FALSE) { + // TBC + } + } + + // ----- Trace + } + else { + // TBC : error : can not extract a folder in a string + } + + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Swap the content to header + $v_local_header['content'] = $p_string; + $p_string = ''; + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Swap back the content to header + $p_string = $v_local_header['content']; + unset($v_local_header['content']); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x04034b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 26); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 26) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); + + // ----- Get filename + $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); + + // ----- Get extra_fields + if ($v_data['extra_len'] != 0) { + $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); + } + else { + $p_header['extra'] = ''; + } + + // ----- Extract properties + $p_header['version_extracted'] = $v_data['version']; + $p_header['compression'] = $v_data['compression']; + $p_header['size'] = $v_data['size']; + $p_header['compressed_size'] = $v_data['compressed_size']; + $p_header['crc'] = $v_data['crc']; + $p_header['flag'] = $v_data['flag']; + $p_header['filename_len'] = $v_data['filename_len']; + + // ----- Recuperate date in UNIX format + $p_header['mdate'] = $v_data['mdate']; + $p_header['mtime'] = $v_data['mtime']; + if ($p_header['mdate'] && $p_header['mtime']) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // TBC + //for(reset($v_data); $key = key($v_data); next($v_data)) { + //} + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set the status field + $p_header['status'] = "ok"; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadCentralFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x02014b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 42); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 42) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); + + // ----- Get filename + if ($p_header['filename_len'] != 0) + $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); + else + $p_header['filename'] = ''; + + // ----- Get extra + if ($p_header['extra_len'] != 0) + $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); + else + $p_header['extra'] = ''; + + // ----- Get comment + if ($p_header['comment_len'] != 0) + $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); + else + $p_header['comment'] = ''; + + // ----- Extract properties + + // ----- Recuperate date in UNIX format + //if ($p_header['mdate'] && $p_header['mtime']) + // TBC : bug : this was ignoring time with 0/0/0 + if (1) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set default status to ok + $p_header['status'] = 'ok'; + + // ----- Look if it is a directory + if (substr($p_header['filename'], -1) == '/') { + //$p_header['external'] = 0x41FF0010; + $p_header['external'] = 0x00000010; + } + + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCheckFileHeaders() + // Description : + // Parameters : + // Return Values : + // 1 on success, + // 0 on error; + // -------------------------------------------------------------------------------- + function privCheckFileHeaders(&$p_local_header, &$p_central_header) + { + $v_result=1; + + // ----- Check the static values + // TBC + if ($p_local_header['filename'] != $p_central_header['filename']) { + } + if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { + } + if ($p_local_header['flag'] != $p_central_header['flag']) { + } + if ($p_local_header['compression'] != $p_central_header['compression']) { + } + if ($p_local_header['mtime'] != $p_central_header['mtime']) { + } + if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { + } + + // ----- Look for flag bit 3 + if (($p_local_header['flag'] & 8) == 8) { + $p_local_header['size'] = $p_central_header['size']; + $p_local_header['compressed_size'] = $p_central_header['compressed_size']; + $p_local_header['crc'] = $p_central_header['crc']; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadEndCentralDir() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadEndCentralDir(&$p_central_dir) + { + $v_result=1; + + // ----- Go to the end of the zip file + $v_size = filesize($this->zipname); + @fseek($this->zip_fd, $v_size); + if (@ftell($this->zip_fd) != $v_size) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- First try : look if this is an archive with no commentaries (most of the time) + // in this case the end of central dir is at 22 bytes of the file end + $v_found = 0; + if ($v_size > 26) { + @fseek($this->zip_fd, $v_size-22); + if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read for bytes + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = @unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] == 0x06054b50) { + $v_found = 1; + } + + $v_pos = ftell($this->zip_fd); + } + + // ----- Go back to the maximum possible size of the Central Dir End Record + if (!$v_found) { + $v_maximum_size = 65557; // 0xFFFF + 22; + if ($v_maximum_size > $v_size) + $v_maximum_size = $v_size; + @fseek($this->zip_fd, $v_size-$v_maximum_size); + if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read byte per byte in order to find the signature + $v_pos = ftell($this->zip_fd); + $v_bytes = 0x00000000; + while ($v_pos < $v_size) + { + // ----- Read a byte + $v_byte = @fread($this->zip_fd, 1); + + // ----- Add the byte + //$v_bytes = ($v_bytes << 8) | Ord($v_byte); + // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number + // Otherwise on systems where we have 64bit integers the check below for the magic number will fail. + $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte); + + // ----- Compare the bytes + if ($v_bytes == 0x504b0506) + { + $v_pos++; + break; + } + + $v_pos++; + } + + // ----- Look if not found end of central dir + if ($v_pos == $v_size) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Read the first 18 bytes of the header + $v_binary_data = fread($this->zip_fd, 18); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 18) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); + + // ----- Check the global size + if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { + + // ----- Removed in release 2.2 see readme file + // The check of the file size is a little too strict. + // Some bugs where found when a zip is encrypted/decrypted with 'crypt'. + // While decrypted, zip has training 0 bytes + if (0) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, + 'The central dir is not at the end of the archive.' + .' Some trailing bytes exists after the archive.'); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Get comment + if ($v_data['comment_size'] != 0) { + $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); + } + else + $p_central_dir['comment'] = ''; + + $p_central_dir['entries'] = $v_data['entries']; + $p_central_dir['disk_entries'] = $v_data['disk_entries']; + $p_central_dir['offset'] = $v_data['offset']; + $p_central_dir['size'] = $v_data['size']; + $p_central_dir['disk'] = $v_data['disk']; + $p_central_dir['disk_start'] = $v_data['disk_start']; + + // TBC + //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { + //} + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDeleteByRule() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDeleteByRule(&$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Scan all the files + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + $v_header_list = array(); + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read the file header + $v_header_list[$v_nb_extracted] = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + + return $v_result; + } + + + // ----- Store the index + $v_header_list[$v_nb_extracted]['index'] = $i; + + // ----- Look for the specific extract rules + $v_found = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ + && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + } + // ----- Look for a filename + elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_found = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_found = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + else { + $v_found = true; + } + + // ----- Look for deletion + if ($v_found) + { + unset($v_header_list[$v_nb_extracted]); + } + else + { + $v_nb_extracted++; + } + } + + // ----- Look if something need to be deleted + if ($v_nb_extracted > 0) { + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Creates a temporary zip archive + $v_temp_zip = new PclZip($v_zip_temp_name); + + // ----- Open the temporary zip file in write mode + if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Look which file need to be kept + for ($i=0; $izip_fd); + if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_local_header = array(); + if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Check that local file header is same as central file header + if ($this->privCheckFileHeaders($v_local_header, + $v_header_list[$i]) != 1) { + // TBC + } + unset($v_local_header); + + // ----- Write the file header + if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Read/write the data block + if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_temp_zip->zip_fd); + + // ----- Re-Create the Central Dir files header + for ($i=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Transform the header to a 'usable' info + $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { + // ----- Reset the file list + unset($v_header_list); + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Close + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Destroy the temporary archive + unset($v_temp_zip); + } + + // ----- Remove every files : reset the file + else if ($v_central_dir['entries'] != 0) { + $this->privCloseFd(); + + if (($v_result = $this->privOpenFd('wb')) != 1) { + return $v_result; + } + + if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { + return $v_result; + } + + $this->privCloseFd(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDirCheck() + // Description : + // Check if a directory exists, if not it creates it and all the parents directory + // which may be useful. + // Parameters : + // $p_dir : Directory path to check. + // Return Values : + // 1 : OK + // -1 : Unable to create directory + // -------------------------------------------------------------------------------- + function privDirCheck($p_dir, $p_is_dir=false) + { + $v_result = 1; + + + // ----- Remove the final '/' + if (($p_is_dir) && (substr($p_dir, -1)=='/')) + { + $p_dir = substr($p_dir, 0, strlen($p_dir)-1); + } + + // ----- Check the directory availability + if ((is_dir($p_dir)) || ($p_dir == "")) + { + return 1; + } + + // ----- Extract parent directory + $p_parent_dir = dirname($p_dir); + + // ----- Just a check + if ($p_parent_dir != $p_dir) + { + // ----- Look for parent directory + if ($p_parent_dir != "") + { + if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) + { + return $v_result; + } + } + } + + // ----- Create the directory + if (!@mkdir($p_dir, 0777)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privMerge() + // Description : + // If $p_archive_to_add does not exist, the function exit with a success result. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privMerge(&$p_archive_to_add) + { + $v_result=1; + + // ----- Look if the archive_to_add exists + if (!is_file($p_archive_to_add->zipname)) + { + + // ----- Nothing to merge, so merge is a success + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Look if the archive exists + if (!is_file($this->zipname)) + { + + // ----- Do a duplicate + $v_result = $this->privDuplicate($p_archive_to_add->zipname); + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Open the archive_to_add file + if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) + { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir_to_add = array(); + if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + return $v_result; + } + + // ----- Go to beginning of File + @rewind($p_archive_to_add->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the files from the archive_to_add into the temporary file + $v_size = $v_central_dir_to_add['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_zip_temp_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the block of file headers from the archive_to_add + $v_size = $v_central_dir_to_add['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Merge the file comments + $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; + + // ----- Calculate the size of the (new) central header + $v_size = @ftell($v_zip_temp_fd)-$v_offset; + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive fd + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + @fclose($v_zip_temp_fd); + $this->zip_fd = null; + + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDuplicate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDuplicate($p_archive_filename) + { + $v_result=1; + + // ----- Look if the $p_archive_filename exists + if (!is_file($p_archive_filename)) + { + + // ----- Nothing to duplicate, so duplicate is a success. + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) + { + $this->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = filesize($p_archive_filename); + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorLog() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorLog($p_error_code=0, $p_error_string='') + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclError($p_error_code, $p_error_string); + } + else { + $this->error_code = $p_error_code; + $this->error_string = $p_error_string; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorReset() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorReset() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclErrorReset(); + } + else { + $this->error_code = 0; + $this->error_string = ''; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDisableMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDisableMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if already done + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Get and memorize the magic_quote value + $this->magic_quotes_status = @get_magic_quotes_runtime(); + + // ----- Disable magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime(0); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privSwapBackMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privSwapBackMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if something to do + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Swap back magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime($this->magic_quotes_status); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + } + // End of class + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathReduction() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilPathReduction($p_dir) + { + $v_result = ""; + + // ----- Look for not empty path + if ($p_dir != "") { + // ----- Explode path by directory names + $v_list = explode("/", $p_dir); + + // ----- Study directories from last to first + $v_skip = 0; + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + $v_skip++; + } + else if ($v_list[$i] == "") { + // ----- First '/' i.e. root slash + if ($i == 0) { + $v_result = "/".$v_result; + if ($v_skip > 0) { + // ----- It is an invalid path, so the path is not modified + // TBC + $v_result = $p_dir; + $v_skip = 0; + } + } + // ----- Last '/' i.e. indicates a directory + else if ($i == (sizeof($v_list)-1)) { + $v_result = $v_list[$i]; + } + // ----- Double '/' inside the path + else { + // ----- Ignore only the double '//' in path, + // but not the first and last '/' + } + } + else { + // ----- Look for item to skip + if ($v_skip > 0) { + $v_skip--; + } + else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); + } + } + } + + // ----- Look for skip + if ($v_skip > 0) { + while ($v_skip > 0) { + $v_result = '../'.$v_result; + $v_skip--; + } + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathInclusion() + // Description : + // This function indicates if the path $p_path is under the $p_dir tree. Or, + // said in an other way, if the file or sub-dir $p_path is inside the dir + // $p_dir. + // The function indicates also if the path is exactly the same as the dir. + // This function supports path with duplicated '/' like '//', but does not + // support '.' or '..' statements. + // Parameters : + // Return Values : + // 0 if $p_path is not inside directory $p_dir + // 1 if $p_path is inside directory $p_dir + // 2 if $p_path is exactly the same as $p_dir + // -------------------------------------------------------------------------------- + function PclZipUtilPathInclusion($p_dir, $p_path) + { + $v_result = 1; + + // ----- Look for path beginning by ./ + if ( ($p_dir == '.') + || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { + $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); + } + if ( ($p_path == '.') + || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { + $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); + } + + // ----- Explode dir and path by directory separator + $v_list_dir = explode("/", $p_dir); + $v_list_dir_size = sizeof($v_list_dir); + $v_list_path = explode("/", $p_path); + $v_list_path_size = sizeof($v_list_path); + + // ----- Study directories paths + $i = 0; + $j = 0; + while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { + + // ----- Look for empty dir (path reduction) + if ($v_list_dir[$i] == '') { + $i++; + continue; + } + if ($v_list_path[$j] == '') { + $j++; + continue; + } + + // ----- Compare the items + if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { + $v_result = 0; + } + + // ----- Next items + $i++; + $j++; + } + + // ----- Look if everything seems to be the same + if ($v_result) { + // ----- Skip all the empty items + while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; + while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; + + if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { + // ----- There are exactly the same + $v_result = 2; + } + else if ($i < $v_list_dir_size) { + // ----- The path is shorter than the dir + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilCopyBlock() + // Description : + // Parameters : + // $p_mode : read/write compression mode + // 0 : src & dest normal + // 1 : src gzip, dest normal + // 2 : src normal, dest gzip + // 3 : src & dest gzip + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) + { + $v_result = 1; + + if ($p_mode==0) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==1) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==2) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==3) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilRename() + // Description : + // This function tries to do a simple rename() function. If it fails, it + // tries to copy the $p_src file in a new $p_dest file and then unlink the + // first one. + // Parameters : + // $p_src : Old filename + // $p_dest : New filename + // Return Values : + // 1 on success, 0 on failure. + // -------------------------------------------------------------------------------- + function PclZipUtilRename($p_src, $p_dest) + { + $v_result = 1; + + // ----- Try to rename the files + if (!@rename($p_src, $p_dest)) { + + // ----- Try to copy & unlink the src + if (!@copy($p_src, $p_dest)) { + $v_result = 0; + } + else if (!@unlink($p_src)) { + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilOptionText() + // Description : + // Translate option value in text. Mainly for debug purpose. + // Parameters : + // $p_option : the option value. + // Return Values : + // The option text value. + // -------------------------------------------------------------------------------- + function PclZipUtilOptionText($p_option) + { + + $v_list = get_defined_constants(); + for (reset($v_list); $v_key = key($v_list); next($v_list)) { + $v_prefix = substr($v_key, 0, 10); + if (( ($v_prefix == 'PCLZIP_OPT') + || ($v_prefix == 'PCLZIP_CB_') + || ($v_prefix == 'PCLZIP_ATT')) + && ($v_list[$v_key] == $p_option)) { + return $v_key; + } + } + + $v_result = 'Unknown'; + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilTranslateWinPath() + // Description : + // Translate windows path by replacing '\' by '/' and optionally removing + // drive letter. + // Parameters : + // $p_path : path to translate. + // $p_remove_disk_letter : true | false + // Return Values : + // The path translated. + // -------------------------------------------------------------------------------- + function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) + { + if (stristr(php_uname(), 'windows')) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // -------------------------------------------------------------------------------- + + +?> diff --git a/system/mdistributor.php b/system/mdistributor.php new file mode 100644 index 0000000..50922ef --- /dev/null +++ b/system/mdistributor.php @@ -0,0 +1,122 @@ +get('users_auth'); + + $user = isset($users[$userkey]) ? $users[$userkey] : 0; + + if(!$user) + { + if((!sys::valid($aAuth['login'], 'other', $aValid['login'])) && !sys::valid($aAuth['passwd'], 'md5')) + { + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" LIMIT 1'); + if($sql->num()) + { + $sql->query('SELECT `id`, `login`, `passwd`, `balance`, `group`, `level`, `time` FROM `users` WHERE `login`="'.$aAuth['login'].'" AND `passwd`="'.$aAuth['passwd'].'" LIMIT 1'); + $user = array_merge(array('authkey' => $authkey), $sql->get()); + + $auth = 1; + + sys::users($users, $user, $authkey); + } + } + + if(!$auth) + { + sys::cookie('egp_login', 'quit', -1); + sys::cookie('egp_passwd', 'quit', -1); + sys::cookie('egp_authkeycheck', 'quit', -1); + } + }else{ + $sql->query('SELECT `balance`, `time` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + sys::user($user); + + $auth = 1; + } + } + + // Заголовок + $title = ''; + + // Подключение файла + if(in_array($route, $amRoute)) + include(ENG.'megp/'.$route.'.php'); + else + include(ENG.'megp/index.php'); + + // Обновление ссылок + if(isset($html->arr['main'])) + { + $html->upd( + array( + '[home]', + '[js]', + '[css]', + '[img]' + ), + + array( + $cfg['http'], + $cfg['http'].'template/megp/js/', + $cfg['http'].'template/megp/css/', + $cfg['http'].'template/megp/images/' + ), + 'main' + ); + } + + // Заготовка выхлопа + $html->get('all'); + $html->set('title', $title.' | '.$cfg['name']); + $html->set('home', $cfg['http']); + $html->set('js', $cfg['http'].'template/megp/js/'); + $html->set('css', $cfg['http'].'template/megp/css/'); + $html->set('img', $cfg['http'].'template/megp/images/'); + + if($auth) + $html->set('server_menu', isset($html->arr['vmenu']) ? $html->arr['vmenu'] : ''); + else + $html->set('server_menu', ''); + + $html->set('main', isset($html->arr['main']) ? $html->arr['main'] : '', true); + $html->pack('all'); + + // Блоки + if($auth) + { + // Проверка наличия игрового сервера + $servers = $sql->query('(SELECT `id` FROM `servers` WHERE `user`="'.$user['id'].'" LIMIT 1) UNION (SELECT `id` FROM `owners` WHERE `user`="'.$user['id'].'" LIMIT 1)'); + + if($sql->num()) + $html->unitall('all', 'servers', 1, 1); + else + $html->unitall('all', 'servers', 0, 1); + } +?> \ No newline at end of file diff --git a/system/sections/chat/chats.php b/system/sections/chat/chats.php new file mode 100644 index 0000000..38e4540 --- /dev/null +++ b/system/sections/chat/chats.php @@ -0,0 +1,118 @@ + 'Необходимо написать сообщение')); + + $msg = $_POST['text']; + $sql->query('INSERT INTO `chat` (`userid`, `date`, `msg`) VALUES ("'.$user['id'].'", NOW(), "'.mysqli_real_escape_string($sql->sql_id, $msg).'");'); + sys::outjs(array('s' => '')); + case 'dialog': + $q_Msgs = $sql->query('SELECT `chat`.`id`, `userid`, `msg`, `chat`.`date`, `login`, `group` FROM `chat` INNER JOIN `users` ON `chat`.`userid` = `users`.`id` ORDER BY `chat`.`date` ASC LIMIT 30'); + while($msg = $sql->get($q_Msgs)) + { + $html->get('messages_all', 'sections/chat'); + if($msg['group'] == 'admin') + $group = 'Администратор'; + else if($msg['group'] == 'support') + $group = 'Тех. Поддержка'; + else if($msg['group'] == 'user') + $group = 'Клиент'; + + $name = $msg['login'].' ('.$group.')'; + + $html->set('id', $msg['id']); + $html->set('userid', $msg['userid']); + $html->set('name', $name); + $html->set('time', $time); + $html->set('date', $msg['date']); + $html->set('msg', $msg['msg']); + $html->set('login', $msg['login']); + + $html->unit('me', $user['id'] == $userid, 1); + + for($i = 1; $i <= 32; $i++) + $html->set('emoji_'.$i, ''); + + global $cfg; + $file = 'upload/avatars/' . $resp['uid'] . '.'; + $link = $cfg['http'] . 'upload/avatars/' . $resp['uid'] . '.'; + if (file_exists(ROOT . $file . 'jpg')) + $html->set('ava', '/upload/avatars/' . $resp['uid'] . '.jpg'); + elseif (file_exists(ROOT . $file . 'png')) + $html->set('ava', '/upload/avatars/' . $resp['uid'] . '.png'); + elseif (file_exists(ROOT . $file . 'gif')) + $html->set('ava', '/upload/avatars/' . $resp['uid'] . '.gif'); + else + $html->set('ava', $cfg['http'] . 'template/images/avatar.png'); + $html->pack('dialog'); + } + sys::out(isset($html->arr['dialog']) ? $html->arr['dialog'] : ''); + case 'delete': + if($user['group'] != 'admin') + sys::outjs(array('e' => 'Недостаточно прав')); + + if(!isset($url['id'])) + sys::outjs(array('e' => 'Отсутствует идентификатор')); + + if($go) + $sql->query('DELETE FROM `chat` WHERE `userid`="'.$url['id'].'";'); + else + $sql->query('DELETE FROM `chat` WHERE `id`="'.$url['id'].'";'); + + sys::outjs(array('s' => '')); + } + } + + $html->nav($title); + + $q_Msgs = $sql->query('SELECT `chat`.`id`, `userid`, `msg`, `chat`.`date`, `login`, `group` FROM `chat` INNER JOIN `users` ON `chat`.`userid` = `users`.`id` ORDER BY `chat`.`date` ASC LIMIT 30'); + while($msg = $sql->get($q_Msgs)) + { + $html->get('messages_all', 'sections/chat'); + if($msg['group'] == 'admin') + $group = 'Администратор'; + else if($msg['group'] == 'support') + $group = 'Тех. Поддержка'; + else if($msg['group'] == 'user') + $group = 'Клиент'; + + $name = $msg['login'].' ('.$group.')'; + + $html->set('id', $msg['id']); + $html->set('userid', $msg['userid']); + $html->set('name', $name); + $html->set('time', $time); + $html->set('date', $msg['date']); + $html->set('msg', $msg['msg']); + $html->set('login', $msg['login']); + + $html->unit('me', $user['id'] == $userid, 1); + + for($i = 1; $i <= 32; $i++) + $html->set('emoji_'.$i, ''); + + global $cfg; + $file = 'upload/avatars/' . $msg['uid'] . '.'; + $link = $cfg['http'] . 'upload/avatars/' . $msg['uid'] . '.'; + if (file_exists(ROOT . $file . 'jpg')) + $html->set('ava', '/upload/avatars/' . $msg['uid'] . '.jpg'); + elseif (file_exists(ROOT . $file . 'png')) + $html->set('ava', '/upload/avatars/' . $msg['uid'] . '.png'); + elseif (file_exists(ROOT . $file . 'gif')) + $html->set('ava', '/upload/avatars/' . $msg['uid'] . '.gif'); + else + $html->set('ava', $cfg['http'] . 'template/images/avatar.png'); + $html->pack('msg_all'); + } + + $html->get('dialog', 'sections/chat'); + $html->set('chats', isset($html->arr['msg_all']) ? $html->arr['msg_all'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/chat/dialog.php b/system/sections/chat/dialog.php new file mode 100644 index 0000000..338d067 --- /dev/null +++ b/system/sections/chat/dialog.php @@ -0,0 +1,39 @@ +query('SELECT * FROM (SELECT `id`, `userid`, `msg`, `date` FROM `chat` ORDER BY `date` DESC LIMIT 30) t ORDER BY `date` ASC;'); + while($msg = $sql->get($q_Msgs)) + { + if($user['group'] == 'admin') + $group = 'Администратор'; + //elseif () + // $group = '(Клиент, серверов: 1 шт.)'; + else + $group = 'Клиент'; + + $name = $user['login'].' ('.$group.')'; // (Администратор) + // $time = '[date]'; + + $html->get('message', 'chatwin'); + + $html->set('id', $msg['id']); + $html->set('userid', $msg['userid']); + $html->set('name', $name); + $html->set('time', $time); + $html->set('date', $msg['date']); + $html->set('msg', $msg['msg']); + + $html->unit('me', $user['id'] == $userid, 1); + + for($i = 1; $i <= 32; $i++) + $html->set('emoji_'.$i, ''); + + $html->pack('dialog'); + } + + sys::out(isset($html->arr['dialog']) ? $html->arr['dialog'] : ''); +?> \ No newline at end of file diff --git a/system/sections/check/compiler.php b/system/sections/check/compiler.php new file mode 100644 index 0000000..876f903 --- /dev/null +++ b/system/sections/check/compiler.php @@ -0,0 +1,148 @@ + $value) + $aPostFields[$key] = urlencode($key).'='. urlencode($value); + + return implode('&', $aPostFields); + } + + $sql->query('SELECT `browser` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $u_sql = $sql->get(); + + $browser = base64_decode($u_sql['browser']); + + $file = $_FILES['file_code']; + + if(substr($file['name'], -4) != '.sma') + sys::outjs(array('e' => 'Только .sma разрешается загружать')); + + $text = file_get_contents($file['tmp_name']); + $textArray = explode("\n", $text); + + $postFields['fname'] = $file['name']; + $postFields['scode'] = $textArray; + $postFields['go'] = 'send'; + + $ch = curl_init('http://amxmodx.org/webcompiler.cgi'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3'); + curl_setopt($ch, CURLOPT_POSTFIELDS, createPostString($postFields)); + $tresc = curl_exec($ch); + + sys::out($tresc); + + curl_close($ch); + + if(strpos($tresc, 'Your plugin successfully compiled!')) + { + $tresc = substr($tresc, strpos($tresc, "http://www.amxmodx.org/webcompiler.cgi?")); + $ile = strpos($tresc, ""); + $link = substr($tresc, 0, $ile); + $tresc = substr($tresc, strpos($tresc, "Welcome to the AMX Mod X")); + $ile = strpos($tresc, ""); + $inf = substr($tresc, 0, $ile); + $inf = str_replace("\r\n","
    ", $inf); + + $out = ' +
    Ваш плагин скомпилирован удачно

    + Чтобы скачать пройдите по ссылке
    + + Посмотреть лог компиляции

    + +
    '; + + $good = "good.txt"; + + if(!file_exists(FILES.$good)) + { + $handle = fopen(FILES.$good, "w"); + $count_good = 0; + fwrite($handle, $count_good); + fclose($handle); + }else{ + $file = file(FILES.$good); + $count_good = $file[0]; + } + + $count_good++; + + $handle = fopen(FILES.$good, "w"); + fwrite($handle, $count_good); + fclose($handle); + }else{ + $ktory = strpos($tresc, "Your plugin failed to compile"); + $tresc = substr($tresc, $ktory + 63); + $ile = strpos($tresc, ""); + $tresc = substr($tresc, 0, $ile); + + $out = ' +
    Ваш плагин скомпилирован неудачно

    + + Посмотреть лог ошибок

    + +
    + '; + + $failed = "failed.txt"; + + if(!file_exists(FILES.$failed)) + { + $handle = fopen(FILES.$failed, "w"); + $count_failed = 0; + fwrite($handle, $count_failed); + fclose($handle); + }else{ + $file = file(FILES.$failed); + $count_failed = $file[0]; + } + + $count_failed++; + + $handle = fopen(FILES.$failed, "w"); + fwrite($handle, $count_failed); + fclose($handle); + } + }else{ + $good = "good.txt"; + $failed = "failed.txt"; + + if(!file_exists(FILES.$good)) + { + $handle = fopen(FILES.$good, "w"); + $count_good = 0; + fwrite($handle, $count_good); + fclose($handle); + }else{ + $file = file(FILES.$good); + $count_good = $file[0]; + } + + if(!file_exists(FILES.$failed)) + { + $handle = fopen(FILES.$failed, "w"); + $count_failed = 0; + fwrite($handle, $count_failed); + fclose($handle); + }else{ + $file = file(FILES.$failed); + $count_failed = $file[0]; + } + + $html->get('compiler', 'sections/check'); + $html->set('success', $count_good); + $html->set('failed', $count_failed); + $html->pack('compilers'); + + include(SEC.'check/index.php'); + } +?> \ No newline at end of file diff --git a/system/sections/check/index.php b/system/sections/check/index.php new file mode 100644 index 0000000..56d7013 --- /dev/null +++ b/system/sections/check/index.php @@ -0,0 +1,105 @@ + 'Необходимо указать проверяемый файл.')); + } + + $file = $_FILES['file']; + + if(substr($file['name'], -4) != '.sma'){ + sys::outjs(array('e' => 'Только .sma разрешается загружать')); + } + + $text = file_get_contents($file['tmp_name']); + $textArray = explode("\n", $text); + + $errors = []; + + foreach($textArray as $key => $str){ + $strNum = $key + 1; + + foreach($badCommands as $cmd){ + if(strpos($str, $cmd) !== false){ + $errors[$strNum] = $cmd; + } + } + } + + if(!empty($errors)){ + $outputErrors .= 'Номер строкиВредоносный код'; + foreach($errors as $key => $msg){ + $outputErrors .= ''.$key.''.$msg.''; + } + $outputErrors .= ''; + } + else { + if(!isset($outputErrors)){ + sys::outjs(array('s' => 'Вредоносный код не найден.')); + } + } + sys::outjs(array('sma' => $outputErrors)); + } + } + + $html->nav('Проверка плагинов на наличие бэкдоров'); + $html->get('check', 'sections/check'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/extend.php b/system/sections/control/extend.php new file mode 100644 index 0000000..07c7655 --- /dev/null +++ b/system/sections/control/extend.php @@ -0,0 +1,65 @@ +query('SELECT `price`, `time` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + include(LIB.'games/games.php'); + + if($go) + { + if(!isset($url['time']) || !in_array($url['time'], $cfg['control_time'])) + $url['time'] = array_shift($cfg['control_time']); + + $sum = games::define_sum(false, $ctrl['price'], 1, $url['time']); + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $time = $ctrl['time'] < $start_point ? $url['time']*86400 : $url['time']*86400+$ctrl['time']; + + // Обновление информации + $sql->query('UPDATE `control` set `time`="'.$time.'" WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_control'), array('days' => games::parse_day($days, true), 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok')); + } + + if(isset($url['get'])) + { + if(!isset($url['time']) || !in_array($url['time'], $cfg['control_time'])) + $url['time'] = array_shift($cfg['control_time']); + + sys::out(games::define_sum(false, $ctrl['price'], 1, $url['time'])); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Подключенный сервер #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav('Продление аренды'); + + $options = ''; + + foreach($cfg['control_time'] as $time) + $options .= ''; + + $html->get('extend', 'sections/control'); + $html->set('id', $id); + $html->set('time', $options); + $html->set('price', $ctrl); + $html->set('cur', $cfg['currency']); + + if($cfg['settlement_period']) + { + $html->set('date', date('d.m.Y', $start_point)); + $html->unit('settlement_period', true, true); + }else + $html->unit('settlement_period', false, true); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/index.php b/system/sections/control/index.php new file mode 100644 index 0000000..ff38e69 --- /dev/null +++ b/system/sections/control/index.php @@ -0,0 +1,54 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id); + + $sql->query('SELECT ' + .'`id`,' + .'`address`,' + .'`game`,' + .'`slots`,' + .'`online`,' + .'`status`,' + .'`name`,' + .'`map`' + .' FROM `control_servers` WHERE `unit`="'.$id.'" ORDER BY `id` ASC'); + + $wait_servers = ''; + $updates_servers = ''; + + while($server = $sql->get()) + { + $btn = sys::buttons($server['id'], $server['status'], $server['game'], $id); + + $html->get('list', 'sections/control/servers'); + + $html->set('ctrl', $id); + $html->set('id', $server['id']); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img', $server['game'])); + $html->set('btn', $btn); + + $html->pack('list'); + + $wait_servers .= $server['id'].':false,'; + $updates_servers .= 'setTimeout(function() {update_info(\''.$server['id'].'\', \''.$id.'\', true)}, 5000);' + .'setTimeout(function() {update_status(\''.$server['id'].'\', \''.$id.'\', true)}, 5000);' + .'setTimeout(function() {update_resources(\''.$server['id'].'\', \''.$id.'\', true)}, 3000);'; + } + + $html->get('servers', 'sections/control/servers'); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : 'Нет установленных серверов'); + $html->set('wait_servers', $wait_servers); + $html->set('updates_servers', $updates_servers); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/install.php b/system/sections/control/install.php new file mode 100644 index 0000000..5a7ea0f --- /dev/null +++ b/system/sections/control/install.php @@ -0,0 +1,85 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + + if(in_array($ctrl['status'], array('install', 'overdue', 'blocked'))) + include(SEC.'control/noaccess.php'); + else{ + if($go) + { + $game = isset($url['game']) ? $url['game'] : sys::outjs(array('e' => 'Необходимо указать игру')); + + if(!in_array($game, array('cs', 'cssold', 'css', 'csgo'))) + sys::outjs(array('e' => 'Указанная игра не найдена')); + + $sql->query('SELECT `address`, `passwd`, `limit` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" LIMIT '.$ctrl['limit']); + if($sql->num() == $ctrl['limit']) + sys::outjs(array('e' => 'На данном тарифе нельзя установить больше, чем '.$ctrl['limit'].' шт. игровых серверов')); + + $ip = $ctrl['address']; + $port = false; + + $port_min = 27015; + + // Проверка наличия свободного порта + for($port_min; $port_min <= 30000; $port_min+=1) + { + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$ip.':'.$port_min.'" LIMIT 1'); + if(!$sql->num()) + { + $port = $port_min; + + break; + } + } + + $sql->query('INSERT INTO `control_servers` set ' + .'`unit`="'.$id.'",' + .'`address`="'.$ip.':'.$port.'",' + .'`game`="'.$game.'",' + .'`slots`="32",' + .'`status`="install", '.$cfg['control_install'][$game]); + + $uid = $sql->id()+1000; + + if(in_array($game, array('css', 'csgo'))) + $screen = 'cd '.$cfg['steamcmd'].'; ./steamcmd.sh +login anonymous +force_install_dir "/servers/'.$uid.'" +app_update '.$cfg['control_steamcmd'][$game].' +quit; cd /servers/'.$uid.';'; + else{ + $zip = array_shift(array_keys($cfg['control_packs'][$game])).'.zip'; + + $screen = 'rm '.$zip.'; wget '.$cfg['control_server'].'/'.$zip.'; unzip -d . '.$zip.'; rm '.$zip.';'; + } + + include(LIB.'ssh.php'); + + if(!$ssh->auth($ctrl['passwd'], $ctrl['address'])) + sys::outjs(array('e' => 'Неудалось создать связь с физическим сервером')); + + $ssh->set('mkdir /servers/'.$uid.';' // Создание директории + .'useradd -s /bin/false -d /servers/'.$uid.' -g servers -u '.$uid.' server'.$uid.';' // Создание пользователя сервера на локации + .'chown server'.$uid.':1000 /servers/'.$uid.';' // Изменение владельца и группы директории + .'cd /servers/'.$uid.' && sudo -u server'.$uid.' screen -dmS i_'.$uid.' sh -c "'.$screen + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$game].'"'); + + $id = $uid-1000; + + $sql->query('UPDATE `control_servers` set `uid`="'.$uid.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + $html->nav('Подключенный сервер #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav('Установка игрового сервера'); + + $html->get('install', 'sections/control'); + $html->set('id', $id); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/noaccess.php b/system/sections/control/noaccess.php new file mode 100644 index 0000000..10d8add --- /dev/null +++ b/system/sections/control/noaccess.php @@ -0,0 +1,22 @@ +nav('Раздел недоступен'); + + if($ctrl['time'] < $start_point) + $html->get('overdue'); + else{ + $status = array( + 'install' => 'установки', + 'reboot' => 'перезагрузки', + 'blocked' => 'блокировки' + ); + + $html->get('noaccess'); + + $html->set('status', $status[$ctrl['status']]); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/reboot.php b/system/sections/control/reboot.php new file mode 100644 index 0000000..d993939 --- /dev/null +++ b/system/sections/control/reboot.php @@ -0,0 +1,24 @@ + 'Сервер должен быть в рабочем состоянии')); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($ctrl['passwd'], $ctrl['address'])) + sys::outjs(array('e' => 'Неудалось создать связь с физическим сервером')); + + $ssh->set('screen -dmS reboot reboot'); + + $sql->query('UPDATE `control` set `status`="reboot" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('UPDATE `control_servers` set `status`="off" WHERE `unit`="'.$id.'" LIMIT 1'); + + $mcache->set('reboot_control_'.$id, true, false, 10); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/sections/control/scan.php b/system/sections/control/scan.php new file mode 100644 index 0000000..73de2b9 --- /dev/null +++ b/system/sections/control/scan.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/system/sections/control/servers/action.php b/system/sections/control/servers/action.php new file mode 100644 index 0000000..897d1cf --- /dev/null +++ b/system/sections/control/servers/action.php @@ -0,0 +1,74 @@ +query('SELECT `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + if(!isset($url['action'])) + sys::outjs(array('e' => 'Неверный запрос для выполнения операции')); + + $nmch = 'ctrl_server_action_'.$sid; + + if($mcache->get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache'))); + + $mcache->set($nmch, true, false, 10); + + include(LIB.'control/'.$server['game'].'/action.php'); + + switch($url['action']) + { + case 'stop': + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + sys::outjs(array('e' => sys::text('error', 'ser_stop')), $nmch); + + sys::outjs(action::stop($sid), $nmch); + + case 'start': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_start')), $nmch); + + sys::outjs(action::start($sid), $nmch); + + case 'restart': + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + sys::outjs(array('e' => sys::text('error', 'ser_restart')), $nmch); + + sys::outjs(action::start($sid, 'restart'), $nmch); + + case 'change': + if($server['status'] != 'working') + { + if($server['status'] == 'change') + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + sys::outjs(array('e' => sys::text('error', 'ser_change')), $nmch); + } + + if(isset($url['change'])) + sys::outjs(action::change($sid, $url['change']), $nmch); + + sys::outjs(action::change($sid), $nmch); + + case 'reinstall': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_reinstall')), $nmch); + + sys::outjs(action::reinstall($sid), $nmch); + + case 'update': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_update')), $nmch); + + sys::outjs(action::update($sid), $nmch); + + case 'delete': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_delete')), $nmch); + + sys::outjs(action::delete($sid), $nmch); + } + + exit; +?> \ No newline at end of file diff --git a/system/sections/control/servers/boost.php b/system/sections/control/servers/boost.php new file mode 100644 index 0000000..07b9806 --- /dev/null +++ b/system/sections/control/servers/boost.php @@ -0,0 +1,11 @@ +query('SELECT `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'boost'); + + include(ctrl::route($server, 'boost', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/servers/console.php b/system/sections/control/servers/console.php new file mode 100644 index 0000000..a3e9dba --- /dev/null +++ b/system/sections/control/servers/console.php @@ -0,0 +1,11 @@ +query('SELECT `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'console'); + + include(ctrl::route($server, 'console', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/servers/copy.php b/system/sections/control/servers/copy.php new file mode 100644 index 0000000..7e526c8 --- /dev/null +++ b/system/sections/control/servers/copy.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `address`, `game`, `pack`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'copy'); + + include(ctrl::route($server, 'copy', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/boost.php b/system/sections/control/servers/cs/boost.php new file mode 100644 index 0000000..221c8b7 --- /dev/null +++ b/system/sections/control/servers/cs/boost.php @@ -0,0 +1,103 @@ + 'Необходимо указать сервис.')); + + // Проверка сервиса + if(!in_array($aData['site'], $aBoost[$server['game']]['boost'])) + sys::outjs(array('e' => 'Указанный сервис по раскрутке не найден.')); + + if(isset($url['rating'])) + { + $rating = $url['rating'] == 'up' ? '1' : '-1'; + + $sql->query('SELECT `id` FROM `boost_rating` WHERE `boost`="'.$aData['site'].'" AND `user`="'.$user['id'].'" AND `rating`="'.$rating.'" LIMIT 1'); + if($sql->num()) + sys::out('err'); + + $sql->query('DELETE FROM `boost_rating` WHERE `boost`="'.$aData['site'].'" AND `user`="'.$user['id'].'" LIMIT 1'); + $sql->query('INSERT INTO `boost_rating` set `boost`="'.$aData['site'].'", `rating`="'.$rating.'", `user`="'.$user['id'].'"'); + + $sql->query('SELECT SUM(`rating`) FROM `boost_rating` WHERE `boost`="'.$aData['site'].'"'); + $sum = $sql->get(); + + $rating = (int) $sum['SUM(`rating`)']; + + sys::out($rating, 'ctrl_server_boost_'.$sid); + } + + $aData['service'] = isset($url['service']) ? sys::int($url['service']) : sys::outjs(array('e' => 'Необходимо указать номер услуги.')); + + // Проверка номера услуги + if(!in_array($aData['service'], $aBoost[$server['game']][$aData['site']]['services'])) + sys::outjs(array('e' => 'Неправильно указан номер услуги.')); + + // Определение суммы + $sum = $aBoost[$server['game']][$aData['site']]['price'][$aData['service']]; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $name_mcache); + + include(LIB.'games/boost.php'); + + $boost = new boost($aBoost[$server['game']][$aData['site']]['key'], $aBoost[$server['game']][$aData['site']]['api']); + + $buy = $boost->$aBoost[$server['game']][$aData['site']]['type'](array('period' => $aData['service'], 'address' => $server['address'])); + + if(is_array($buy)) + sys::outjs(array('e' => $buy['error'])); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + include(LIB.'games/games.php'); + + // Реф. система + games::part($user['id'], $sum); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'ctrl_buy_boost'), + array('circles' => $aBoost[$server['game']][$aData['site']]['circles'][$aData['service']], + 'money' => $sum, 'site' => $aBoost[$server['game']][$aData['site']]['site'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="boost", `money`="'.$sum.'"'); + + $sql->query('INSERT INTO `control_boost` set `user`="'.$user['id'].'", `server`="'.$sid.'", `site`="'.$aData['site'].'", `circles`="'.$aBoost[$server['game']][$aData['site']]['circles'][$aData['service']].'", `money`="'.$sum.'", `date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Раскрутка'); + + if($mcache->get('ctrl_server_boost_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_boost_'.$sid); + else{ + $html->get('boost', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('address', $server['address']); + + foreach($aBoost[$server['game']]['boost'] as $boost) + { + $sql->query('SELECT SUM(`rating`) FROM `boost_rating` WHERE `boost`="'.$boost.'"'); + $sum = $sql->get(); + + $rating = (int) $sum['SUM(`rating`)']; + + $html->set($boost, $rating); + } + + $html->pack('main'); + + $mcache->set('ctrl_server_boost_'.$sid, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/console.php b/system/sections/control/servers/cs/console.php new file mode 100644 index 0000000..1257a30 --- /dev/null +++ b/system/sections/control/servers/cs/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `time_start` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = '/servers/'.$server['uid'].'/cstrike/'; + + $filecmd = $dir.'qconsole.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Консоль'); + + $html->get('console', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/copy.php b/system/sections/control/servers/cs/copy.php new file mode 100644 index 0000000..19cd939 --- /dev/null +++ b/system/sections/control/servers/cs/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'control/servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Резервные копии'); + + if($mcache->get('ctrl_server_copy_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_copy_'.$sid); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/control/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `control_copy` WHERE `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/control/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_copy_'.$sid, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/index.php b/system/sections/control/servers/cs/index.php new file mode 100644 index 0000000..65dccf5 --- /dev/null +++ b/system/sections/control/servers/cs/index.php @@ -0,0 +1,30 @@ +query('SELECT `slots`, `online`, `players`, `name`, `map` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address']); + + $btn = sys::buttons($sid, $server['status'], $server['game'], $id); + + $html->get('index', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/plugins.php b/system/sections/control/servers/cs/plugins.php new file mode 100644 index 0000000..2a96424 --- /dev/null +++ b/system/sections/control/servers/cs/plugins.php @@ -0,0 +1,160 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $nmch = sys::rep_act('ctrl_server_plugins_go_'.$sid, 10); + + include(SEC.'control/servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('ctrl_server_plugins_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_plugins_'.$sid); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$sid.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/control/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/control/servers/games'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_plugins_'.$sid, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/rcon.php b/system/sections/control/servers/cs/rcon.php new file mode 100644 index 0000000..c0a2da0 --- /dev/null +++ b/system/sections/control/servers/cs/rcon.php @@ -0,0 +1,56 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'amx_kick "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'amx_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/control/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings.php b/system/sections/control/servers/cs/settings.php new file mode 100644 index 0000000..717180f --- /dev/null +++ b/system/sections/control/servers/cs/settings.php @@ -0,0 +1,63 @@ +query('SELECT `uid`, `pack` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'amxlogs', 'pack', 'file'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + if($go) + $nmch = sys::rep_act('ctrl_server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'control/servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'control/servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('ctrl_server_settings_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_settings_'.$sid); + else{ + $aEditslist = 1; + $ctrlmod = true; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = $cfg['control_packs'][$server['game']]; + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'control/servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + $html->pack('main'); + + $mcache->set('ctrl_server_settings_'.$sid, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/admins.php b/system/sections/control/servers/cs/settings/admins.php new file mode 100644 index 0000000..f01a295 --- /dev/null +++ b/system/sections/control/servers/cs/settings/admins.php @@ -0,0 +1,134 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['type'] = isset($_POST['type']) ? $_POST['type'] : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $type = isset($aData['type'][$index]) ? $aData['type'][$index] : 'a'; + if(!in_array($type, array('c', 'ce', 'de', 'a'))) + $type = 'a'; + + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['passwd'][$index].'" "'.$aData['flags'][$index].'" "'.$type.'"'; + + $sql->query('INSERT INTO `control_admins_'.$server['game'].'` set' + .'`server`="'.$sid.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`type`="'.$type.'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/addons/amxmodx/configs/users.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/addons/amxmodx/configs/users.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `type`, `time`, `info` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + switch($admin['type']) + { + case 'c': + $type = ''; + break; + + case 'ce': + $type = ''; + break; + + case 'de': + $type = ''; + break; + + default: + $type = ''; + } + + $html->get('list', 'sections/control/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('type', $type); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/amxlogs.php b/system/sections/control/servers/cs/settings/amxlogs.php new file mode 100644 index 0000000..0d207e9 --- /dev/null +++ b/system/sections/control/servers/cs/settings/amxlogs.php @@ -0,0 +1,89 @@ +nav('Логи AMX'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/addons/amxmodx/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csamxlogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/amxlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'amxlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/amxlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'amxlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', 'amx'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/bans.php b/system/sections/control/servers/cs/settings/bans.php new file mode 100644 index 0000000..4e29f56 --- /dev/null +++ b/system/sections/control/servers/cs/settings/bans.php @@ -0,0 +1,165 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к файлам (banned.cfg / listip.cfg) + $folder = '/servers/'.$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_ban 0 ".$aData['value']." EGP\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_ban 0 ".$aData['value']." EGP\"\015'"); + }else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned.cfg; rm temp_banned.cfg"'); + + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_unban ".$aData['value']."\"\015'"); + }else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_ban 0 ".$aData['value']." EGP\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_ban 0 ".$aData['value']." EGP\"\015'"); + }else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' listip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/listip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из listip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat listip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > listip.cfg; rm temp_listip.cfg"'); + + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_unban ".$aData['value']."\"\015'"); + }else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' listip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле listip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле listip.cfg'), $nmch); + } + } + } + + // Содержимое banned.cfg + $ssh->set('cd '.$folder.' && cat banned.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое listip.cfg + $ssh->set('cd '.$folder.' && cat listip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/debug.php b/system/sections/control/servers/cs/settings/debug.php new file mode 100644 index 0000000..f9217af --- /dev/null +++ b/system/sections/control/servers/cs/settings/debug.php @@ -0,0 +1,25 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Чтение файла - oldstart.log + $file = '/servers/'.$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/control/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/logs.php b/system/sections/control/servers/cs/settings/logs.php new file mode 100644 index 0000000..56b63ce --- /dev/null +++ b/system/sections/control/servers/cs/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/server.php b/system/sections/control/servers/cs/settings/server.php new file mode 100644 index 0000000..e46d11b --- /dev/null +++ b/system/sections/control/servers/cs/settings/server.php @@ -0,0 +1,116 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + $file = '/servers/'.$server['uid'].'/cstrike/server.cfg'; + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $file, 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$file); + + unlink($temp); + + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "exec server.cfg"\015\';'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/control/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/start.php b/system/sections/control/servers/cs/settings/start.php new file mode 100644 index 0000000..d80313c --- /dev/null +++ b/system/sections/control/servers/cs/settings/start.php @@ -0,0 +1,185 @@ +query('SELECT `uid`, `slots`, `map_start`, `vac`, `fps`, `fastdl`, `autorestart`, `pingboost`, `core_fix` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Вывод списка потоков + if(isset($url['core'])) + ctrl::cpulist($unit, $server['core_fix']); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $map, true, $nmch, true); + + sys::outjs(array('e' => $map.' != '.$server['map_start']), $nmch); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'address': + if($server['status'] != 'off') + sys::outjs(array('e' => 'Необходимо выключить игровой сервер'), $nmch); + + $address = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$address.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером'), $nmch); + + if($address != $server['address']) + $sql->query('UPDATE `control_servers` set `address`="'.$address.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `control_servers` set `vac`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'core_fix': + $n = ctrl::cpulist($unit, $server['core_fix'], true); + + if($value > $n) + sys::outjs(array('e' => 'На физическом сервере нет такого ядра/потока'), $nmch); + + if($value < 0) + $value = 0; + + if($value != $server['core_fix']) + $sql->query('UPDATE `control_servers` set `core_fix`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > 32 ? 32 : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots']) + $sql->query('UPDATE `control_servers` set `slots`="'.$slots.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `control_servers` set `autorestart`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(in_array($value, array('300', '500', '1100'))) + $sql->query('UPDATE `control_servers` set `fps`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'pingboost': + if(in_array($value, array(0, 1, 2, 3))) + $sql->query('UPDATE `control_servers` set `pingboost`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.$unit['address'].':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, 'servers/'.$server['uid'].'/cstrike/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.'servers/'.$server['uid'].'/cstrike/fastdl.cfg;' + .'ln -s '.'servers/'.$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.'servers/'.$server['uid'].'/cstrike/server.cfg;' + .'echo "exec fastdl.cfg" >> '.'servers/'.$server['uid'].'/cstrike/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.'servers/'.$server['uid'].'/cstrike/server.cfg;' + .'rm '.'servers/'.$server['uid'].'/cstrike/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `control_servers` set `fastdl`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= 32; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + + foreach(array('300', '500', '1100') as $value) + $fps .= ''; + + $pingboost = str_replace($server['pingboost'].'"', $server['pingboost'].'" selected="select"', ''); + + $core_fix = $server['core_fix'] ? '' : ''; + + $html->get('start', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('map', $server['map_start']); + $html->set('address', $server['address']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('core_fix', $core_fix); + $html->set('slots', str_replace('"'.$server['slots'].'"', '"'.$server['slots'].'" selected="select"', $slots)); + $html->set('pingboost', $pingboost); + $html->set('fps', str_replace($server['fps'].'"', $server['fps'].'" selected="select"', $fps)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cs/settings/top.php b/system/sections/control/servers/cs/settings/top.php new file mode 100644 index 0000000..8f10482 --- /dev/null +++ b/system/sections/control/servers/cs/settings/top.php @@ -0,0 +1,20 @@ +query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Удаление файла csstats.dat + $ssh->set('rm /servers'.$server['uid'].'/cstrike/addons/amxmodx/data/csstats.dat'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + shell_exec('php cron.php '.$cfg['cron_key'].' control_server_action restart cs '.$sid); + + sys::outjs(array('s' => 'ok')); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/console.php b/system/sections/control/servers/csgo/console.php new file mode 100644 index 0000000..15438ff --- /dev/null +++ b/system/sections/control/servers/csgo/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `time_start` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = '/servers/'.$server['uid'].'/csgo/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Консоль'); + + $html->get('console', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/copy.php b/system/sections/control/servers/csgo/copy.php new file mode 100644 index 0000000..19cd939 --- /dev/null +++ b/system/sections/control/servers/csgo/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'control/servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Резервные копии'); + + if($mcache->get('ctrl_server_copy_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_copy_'.$sid); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/control/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `control_copy` WHERE `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/control/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_copy_'.$sid, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/index.php b/system/sections/control/servers/csgo/index.php new file mode 100644 index 0000000..65dccf5 --- /dev/null +++ b/system/sections/control/servers/csgo/index.php @@ -0,0 +1,30 @@ +query('SELECT `slots`, `online`, `players`, `name`, `map` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address']); + + $btn = sys::buttons($sid, $server['status'], $server['game'], $id); + + $html->get('index', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/plugins.php b/system/sections/control/servers/csgo/plugins.php new file mode 100644 index 0000000..2a96424 --- /dev/null +++ b/system/sections/control/servers/csgo/plugins.php @@ -0,0 +1,160 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $nmch = sys::rep_act('ctrl_server_plugins_go_'.$sid, 10); + + include(SEC.'control/servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('ctrl_server_plugins_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_plugins_'.$sid); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$sid.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/control/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/control/servers/games'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_plugins_'.$sid, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/rcon.php b/system/sections/control/servers/csgo/rcon.php new file mode 100644 index 0000000..14ff694 --- /dev/null +++ b/system/sections/control/servers/csgo/rcon.php @@ -0,0 +1,57 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/control/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings.php b/system/sections/control/servers/csgo/settings.php new file mode 100644 index 0000000..945b605 --- /dev/null +++ b/system/sections/control/servers/csgo/settings.php @@ -0,0 +1,63 @@ +query('SELECT `uid`, `pack` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + if($go) + $nmch = sys::rep_act('ctrl_server_settings_go_'.$sid, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'control/servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'control/servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('ctrl_server_settings_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_settings_'.$sid); + else{ + $aEditslist = 1; + $ctrlmod = true; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = $cfg['control_packs'][$server['game']]; + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'control/servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + $html->pack('main'); + + $mcache->set('ctrl_server_settings_'.$sid, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/admins.php b/system/sections/control/servers/csgo/settings/admins.php new file mode 100644 index 0000000..597fc76 --- /dev/null +++ b/system/sections/control/servers/csgo/settings/admins.php @@ -0,0 +1,112 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `control_admins_'.$server['game'].'` set' + .'`server`="'.$sid.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/csgo/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/csgo/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/control/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/bans.php b/system/sections/control/servers/csgo/settings/bans.php new file mode 100644 index 0000000..eed97f7 --- /dev/null +++ b/system/sections/control/servers/csgo/settings/bans.php @@ -0,0 +1,158 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = '/servers/'.$server['uid'].'/csgo'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/debug.php b/system/sections/control/servers/csgo/settings/debug.php new file mode 100644 index 0000000..f9217af --- /dev/null +++ b/system/sections/control/servers/csgo/settings/debug.php @@ -0,0 +1,25 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Чтение файла - oldstart.log + $file = '/servers/'.$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/control/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/logs.php b/system/sections/control/servers/csgo/settings/logs.php new file mode 100644 index 0000000..c147110 --- /dev/null +++ b/system/sections/control/servers/csgo/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/csgo/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/server.php b/system/sections/control/servers/csgo/settings/server.php new file mode 100644 index 0000000..8e41f0f --- /dev/null +++ b/system/sections/control/servers/csgo/settings/server.php @@ -0,0 +1,116 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + $file = '/servers/'.$server['uid'].'/csgo/cfg/server.cfg'; + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $file, 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$file); + + unlink($temp); + + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "exec server.cfg"\015\';'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/control/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/smlogs.php b/system/sections/control/servers/csgo/settings/smlogs.php new file mode 100644 index 0000000..e13f4d9 --- /dev/null +++ b/system/sections/control/servers/csgo/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/csgo/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/csgo/settings/start.php b/system/sections/control/servers/csgo/settings/start.php new file mode 100644 index 0000000..8182b60 --- /dev/null +++ b/system/sections/control/servers/csgo/settings/start.php @@ -0,0 +1,193 @@ +query('SELECT `uid`, `slots`, `map_start`, `vac`, `fastdl`, `autorestart`, `tickrate`, `core_fix`, `pingboost` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/csgo/maps', $server['map_start'], false); + + // Вывод списка потоков + if(isset($url['core'])) + ctrl::cpulist($unit, $server['core_fix']); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/csgo/maps', $map, true, $nmch, true); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'address': + if($server['status'] != 'off') + sys::outjs(array('e' => 'Необходимо выключить игровой сервер'), $nmch); + + $address = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$address.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером'), $nmch); + + if($address != $server['address']) + $sql->query('UPDATE `control_servers` set `address`="'.$address.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'mod': + if(in_array($value, array(1, 2, 3, 4, 5))) + $sql->query('UPDATE `control_servers` set `pingboost`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `control_servers` set `vac`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'core_fix': + $n = ctrl::cpulist($unit, $server['core_fix'], true); + + if($value > $n) + sys::outjs(array('e' => 'На физическом сервере нет такого ядра/потока'), $nmch); + + if($value < 0) + $value = 0; + + if($value != $server['core_fix']) + $sql->query('UPDATE `control_servers` set `core_fix`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > 64 ? 64 : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots']) + $sql->query('UPDATE `control_servers` set `slots`="'.$slots.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `control_servers` set `autorestart`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(in_array($value, array('64', '128'))) + $sql->query('UPDATE `control_servers` set `tickrate`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.$unit['address'].':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/csgo/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/csgo/cfg/fastdl.cfg;' + .'ln -s /servers/'.$server['uid'].'/csgo /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/csgo/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> /servers/'.$server['uid'].'/csgo/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/csgo/cfg/server.cfg;' + .'rm /servers/'.$server['uid'].'/csgo/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `control_servers` set `fastdl`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= 64; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + foreach(array('64', '128') as $value) + $tickrate .= ''; + + $core_fix = $server['core_fix'] ? '' : ''; + + // Игровой режим + $mods = '' + .'' + .'' + .'' + .''; + + if(!$server['pingboost']) + $server['pingboost'] = 2; + + $mod = str_replace('value="'.$server['pingboost'], 'value="'.$server['pingboost'].'" selected="select', $mods); + + $html->get('start', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('map', $server['map_start']); + $html->set('address', $server['address']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('core_fix', $core_fix); + $html->set('mod', $mod); + $html->set('slots', str_replace('"'.$server['slots'].'"', '"'.$server['slots'].'" selected="select"', $slots)); + $html->set('tickrate', str_replace($server['tickrate'].'"', $server['tickrate'].'" selected="select"', $tickrate)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/console.php b/system/sections/control/servers/css/console.php new file mode 100644 index 0000000..0900605 --- /dev/null +++ b/system/sections/control/servers/css/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `time_start` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = '/servers/'.$server['uid'].'/cstrike/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Консоль'); + + $html->get('console', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/copy.php b/system/sections/control/servers/css/copy.php new file mode 100644 index 0000000..1c41f2e --- /dev/null +++ b/system/sections/control/servers/css/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'control/servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Резервные копии'); + + if($mcache->get('ctrl_server_copy_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_copy_'.$sid); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/control/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `control_copy` WHERE `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/control/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_copy_'.$sid, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/index.php b/system/sections/control/servers/css/index.php new file mode 100644 index 0000000..bc4f041 --- /dev/null +++ b/system/sections/control/servers/css/index.php @@ -0,0 +1,30 @@ +query('SELECT `slots`, `online`, `players`, `name`, `pack`, `map` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address']); + + $btn = sys::buttons($sid, $server['status'], $server['game'], $id); + + $html->get('index', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/plugins.php b/system/sections/control/servers/css/plugins.php new file mode 100644 index 0000000..2a96424 --- /dev/null +++ b/system/sections/control/servers/css/plugins.php @@ -0,0 +1,160 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $nmch = sys::rep_act('ctrl_server_plugins_go_'.$sid, 10); + + include(SEC.'control/servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('ctrl_server_plugins_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_plugins_'.$sid); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$sid.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/control/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/control/servers/games'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_plugins_'.$sid, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/rcon.php b/system/sections/control/servers/css/rcon.php new file mode 100644 index 0000000..14ff694 --- /dev/null +++ b/system/sections/control/servers/css/rcon.php @@ -0,0 +1,57 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/control/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings.php b/system/sections/control/servers/css/settings.php new file mode 100644 index 0000000..646d5c3 --- /dev/null +++ b/system/sections/control/servers/css/settings.php @@ -0,0 +1,63 @@ +query('SELECT `uid`, `pack` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + if($go) + $nmch = sys::rep_act('ctrl_server_settings_go_'.$sid, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'control/servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'control/servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('ctrl_server_settings_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_settings_'.$sid); + else{ + $aEditslist = 1; + $ctrlmod = true; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = $cfg['control_packs'][$server['game']]; + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'control/servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + $html->pack('main'); + + $mcache->set('ctrl_server_settings_'.$sid, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/admins.php b/system/sections/control/servers/css/settings/admins.php new file mode 100644 index 0000000..4a85b53 --- /dev/null +++ b/system/sections/control/servers/css/settings/admins.php @@ -0,0 +1,112 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `control_admins_'.$server['game'].'` set' + .'`server`="'.$sid.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/control/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/bans.php b/system/sections/control/servers/css/settings/bans.php new file mode 100644 index 0000000..6320100 --- /dev/null +++ b/system/sections/control/servers/css/settings/bans.php @@ -0,0 +1,158 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = '/servers/'.$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/debug.php b/system/sections/control/servers/css/settings/debug.php new file mode 100644 index 0000000..f9217af --- /dev/null +++ b/system/sections/control/servers/css/settings/debug.php @@ -0,0 +1,25 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Чтение файла - oldstart.log + $file = '/servers/'.$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/control/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/logs.php b/system/sections/control/servers/css/settings/logs.php new file mode 100644 index 0000000..56b63ce --- /dev/null +++ b/system/sections/control/servers/css/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/server.php b/system/sections/control/servers/css/settings/server.php new file mode 100644 index 0000000..6ee8918 --- /dev/null +++ b/system/sections/control/servers/css/settings/server.php @@ -0,0 +1,116 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + $file = '/servers/'.$server['uid'].'/cstrike/cfg/server.cfg'; + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $file, 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$file); + + unlink($temp); + + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "exec server.cfg"\015\';'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/control/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/smlogs.php b/system/sections/control/servers/css/settings/smlogs.php new file mode 100644 index 0000000..9b545aa --- /dev/null +++ b/system/sections/control/servers/css/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/css/settings/start.php b/system/sections/control/servers/css/settings/start.php new file mode 100644 index 0000000..afc780f --- /dev/null +++ b/system/sections/control/servers/css/settings/start.php @@ -0,0 +1,173 @@ +query('SELECT `uid`, `slots`, `map_start`, `vac`, `fastdl`, `autorestart`, `tickrate`, `core_fix` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Вывод списка потоков + if(isset($url['core'])) + ctrl::cpulist($unit, $server['core_fix']); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $map, true, $nmch, true); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'address': + if($server['status'] != 'off') + sys::outjs(array('e' => 'Необходимо выключить игровой сервер'), $nmch); + + $address = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$address.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером'), $nmch); + + if($address != $server['address']) + $sql->query('UPDATE `control_servers` set `address`="'.$address.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `control_servers` set `vac`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'core_fix': + $n = ctrl::cpulist($unit, $server['core_fix'], true); + + if($value > $n) + sys::outjs(array('e' => 'На физическом сервере нет такого ядра/потока'), $nmch); + + if($value < 0) + $value = 0; + + if($value != $server['core_fix']) + $sql->query('UPDATE `control_servers` set `core_fix`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > 64 ? 64 : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots']) + $sql->query('UPDATE `control_servers` set `slots`="'.$slots.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `control_servers` set `autorestart`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(in_array($value, array('66', '100'))) + $sql->query('UPDATE `control_servers` set `tickrate`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.$unit['address'].':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s /servers/'.$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> /servers/'.$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `control_servers` set `fastdl`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= 64; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + foreach(array('66', '100') as $value) + $tickrate .= ''; + + $core_fix = $server['core_fix'] ? '' : ''; + + $html->get('start', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('map', $server['map_start']); + $html->set('address', $server['address']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('core_fix', $core_fix); + $html->set('slots', str_replace('"'.$server['slots'].'"', '"'.$server['slots'].'" selected="select"', $slots)); + $html->set('tickrate', str_replace($server['tickrate'].'"', $server['tickrate'].'" selected="select"', $tickrate)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/console.php b/system/sections/control/servers/cssold/console.php new file mode 100644 index 0000000..0900605 --- /dev/null +++ b/system/sections/control/servers/cssold/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `time_start` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = '/servers/'.$server['uid'].'/cstrike/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Консоль'); + + $html->get('console', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/copy.php b/system/sections/control/servers/cssold/copy.php new file mode 100644 index 0000000..1c41f2e --- /dev/null +++ b/system/sections/control/servers/cssold/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'control/servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Резервные копии'); + + if($mcache->get('ctrl_server_copy_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_copy_'.$sid); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/control/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `control_copy` WHERE `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/control/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_copy_'.$sid, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/index.php b/system/sections/control/servers/cssold/index.php new file mode 100644 index 0000000..bc4f041 --- /dev/null +++ b/system/sections/control/servers/cssold/index.php @@ -0,0 +1,30 @@ +query('SELECT `slots`, `online`, `players`, `name`, `pack`, `map` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address']); + + $btn = sys::buttons($sid, $server['status'], $server['game'], $id); + + $html->get('index', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/plugins.php b/system/sections/control/servers/cssold/plugins.php new file mode 100644 index 0000000..2a96424 --- /dev/null +++ b/system/sections/control/servers/cssold/plugins.php @@ -0,0 +1,160 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $nmch = sys::rep_act('ctrl_server_plugins_go_'.$sid, 10); + + include(SEC.'control/servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('ctrl_server_plugins_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_plugins_'.$sid); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$sid.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/control/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/control/servers/games'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('ctrl_server_plugins_'.$sid, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/rcon.php b/system/sections/control/servers/cssold/rcon.php new file mode 100644 index 0000000..14ff694 --- /dev/null +++ b/system/sections/control/servers/cssold/rcon.php @@ -0,0 +1,57 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/control/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/control/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings.php b/system/sections/control/servers/cssold/settings.php new file mode 100644 index 0000000..646d5c3 --- /dev/null +++ b/system/sections/control/servers/cssold/settings.php @@ -0,0 +1,63 @@ +query('SELECT `uid`, `pack` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + if($go) + $nmch = sys::rep_act('ctrl_server_settings_go_'.$sid, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'control/servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'control/servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('ctrl_server_settings_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_settings_'.$sid); + else{ + $aEditslist = 1; + $ctrlmod = true; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = $cfg['control_packs'][$server['game']]; + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'control/servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/control/servers/'.$server['game']); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + $html->pack('main'); + + $mcache->set('ctrl_server_settings_'.$sid, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/admins.php b/system/sections/control/servers/cssold/settings/admins.php new file mode 100644 index 0000000..4a85b53 --- /dev/null +++ b/system/sections/control/servers/cssold/settings/admins.php @@ -0,0 +1,112 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `control_admins_'.$server['game'].'` set' + .'`server`="'.$sid.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/control/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `control_admins_'.$server['game'].'` WHERE `server`="'.$sid.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/bans.php b/system/sections/control/servers/cssold/settings/bans.php new file mode 100644 index 0000000..6320100 --- /dev/null +++ b/system/sections/control/servers/cssold/settings/bans.php @@ -0,0 +1,158 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = '/servers/'.$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/control/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/debug.php b/system/sections/control/servers/cssold/settings/debug.php new file mode 100644 index 0000000..f9217af --- /dev/null +++ b/system/sections/control/servers/cssold/settings/debug.php @@ -0,0 +1,25 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Чтение файла - oldstart.log + $file = '/servers/'.$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/control/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/logs.php b/system/sections/control/servers/cssold/settings/logs.php new file mode 100644 index 0000000..56b63ce --- /dev/null +++ b/system/sections/control/servers/cssold/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/server.php b/system/sections/control/servers/cssold/settings/server.php new file mode 100644 index 0000000..6ee8918 --- /dev/null +++ b/system/sections/control/servers/cssold/settings/server.php @@ -0,0 +1,116 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + $file = '/servers/'.$server['uid'].'/cstrike/cfg/server.cfg'; + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $file, 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$file); + + unlink($temp); + + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "exec server.cfg"\015\';'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/control/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/smlogs.php b/system/sections/control/servers/cssold/settings/smlogs.php new file mode 100644 index 0000000..9b545aa --- /dev/null +++ b/system/sections/control/servers/cssold/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/cstrike/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/settings/start.php b/system/sections/control/servers/cssold/settings/start.php new file mode 100644 index 0000000..1d7e589 --- /dev/null +++ b/system/sections/control/servers/cssold/settings/start.php @@ -0,0 +1,186 @@ +query('SELECT `uid`, `slots`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate`, `core_fix` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Вывод списка потоков + if(isset($url['core'])) + ctrl::cpulist($unit, $server['core_fix']); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $map, true, $nmch, true); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'address': + if($server['status'] != 'off') + sys::outjs(array('e' => 'Необходимо выключить игровой сервер'), $nmch); + + $address = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$address.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером'), $nmch); + + if($address != $server['address']) + $sql->query('UPDATE `control_servers` set `address`="'.$address.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `control_servers` set `vac`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'core_fix': + $n = ctrl::cpulist($unit, $server['core_fix'], true); + + if($value > $n) + sys::outjs(array('e' => 'На физическом сервере нет такого ядра/потока'), $nmch); + + if($value < 0) + $value = 0; + + if($value != $server['core_fix']) + $sql->query('UPDATE `control_servers` set `core_fix`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > 64 ? 64 : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots']) + $sql->query('UPDATE `control_servers` set `slots`="'.$slots.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `control_servers` set `autorestart`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(in_array($value, array('300', '500', '1100'))) + $sql->query('UPDATE `control_servers` set `fps`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(in_array($value, array('33', '66', '100'))) + $sql->query('UPDATE `control_servers` set `tickrate`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.$unit['address'].':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s /servers/'.$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> /servers/'.$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `control_servers` set `fastdl`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= 64; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + + foreach(array('300', '500', '1100') as $value) + $fps .= ''; + + $tickrate = ''; + + foreach(array('33', '66', '100') as $value) + $tickrate .= ''; + + $core_fix = $server['core_fix'] ? '' : ''; + + $html->get('start', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('map', $server['map_start']); + $html->set('address', $server['address']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('core_fix', $core_fix); + $html->set('slots', str_replace('"'.$server['slots'].'"', '"'.$server['slots'].'" selected="select"', $slots)); + $html->set('tickrate', str_replace($server['tickrate'].'"', $server['tickrate'].'" selected="select"', $tickrate)); + $html->set('fps', str_replace($server['fps'].'"', $server['fps'].'" selected="select"', $fps)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/cssold/start.php b/system/sections/control/servers/cssold/start.php new file mode 100644 index 0000000..4e19134 --- /dev/null +++ b/system/sections/control/servers/cssold/start.php @@ -0,0 +1,179 @@ +query('SELECT `uid`, `slots`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate`, `core_fix` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'games/games.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Вывод списка потоков + if(isset($url['core'])) + ctrl::cpulist($unit, $server['core_fix']); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($sid, $unit, '/servers/'.$server['uid'].'/cstrike/maps', $map, true, $nmch, true); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'address': + if($server['status'] != 'off') + sys::outjs(array('e' => 'Необходимо выключить игровой сервер'), $nmch); + + $address = isset($_POST['address']) ? trim($_POST['address']) : $server['address']; + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id` FROM `control_servers` WHERE `unit`="'.$id.'" AND `address`="'.$address.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес занят другим сервером'), $nmch); + + if($address != $server['address']) + $sql->query('UPDATE `control_servers` set `address`="'.$address.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `control_servers` set `vac`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'core_fix': + $n = ctrl::cpulist($unit, $server['core_fix'], true); + + if($value > $n) + sys::outjs(array('e' => 'На физическом сервере нет такого ядра/потока'), $nmch); + + if($value < 0) + $value = 0; + + if($value != $server['core_fix']) + $sql->query('UPDATE `control_servers` set `core_fix`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > 64 ? 64 : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots']) + $sql->query('UPDATE `control_servers` set `slots`="'.$slots.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `control_servers` set `autorestart`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(in_array($value, array('66', '100'))) + $sql->query('UPDATE `control_servers` set `tickrate`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.$unit['address'].':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, '/servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s /servers/'.$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> /servers/'.$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' /servers/'.$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm /servers/'.$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `control_servers` set `fastdl`="'.$value.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_settings_'.$sid); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= 64; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + foreach(array('66', '100') as $value) + $tickrate .= ''; + + $fps = ''; + + foreach(array('300', '500', '1100') as $value) + $fps .= ''; + + $core_fix = $server['core_fix'] ? '' : ''; + + $html->get('start', 'sections/control/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('map', $server['map_start']); + $html->set('address', $server['address']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('core_fix', $core_fix); + $html->set('slots', str_replace('"'.$server['slots'].'"', '"'.$server['slots'].'" selected="select"', $slots)); + $html->set('tickrate', str_replace($server['tickrate'].'"', $server['tickrate'].'" selected="select"', $tickrate)); + $html->set('fps', str_replace($server['fps'].'"', $server['fps'].'" selected="select"', $fps)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/filetp.php b/system/sections/control/servers/filetp.php new file mode 100644 index 0000000..0c10129 --- /dev/null +++ b/system/sections/control/servers/filetp.php @@ -0,0 +1,204 @@ +query('SELECT `uid`, `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'filetp'); + + $frouter = explode('/', ctrl::route($server, 'filetp', $go)); + + if(end($frouter) == 'noaccess.php') + include(SEC.'control/servers/noaccess.php'); + else{ + $sql->query('SELECT `uid`, `ftp`, `ftp_passwd` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + $ip = sys::first(explode(':', $unit['address'])); + + $html->nav('Список подключенных серверов', $cfg['http'].'control'); + $html->nav('Список игровых серверов #'.$id, $cfg['http'].'control/id/'.$id); + $html->nav($server['address'], $cfg['http'].'control/id/'.$id.'/server/'.$sid); + $html->nav('FileTP'); + + // Путь для Proftpd + $homedir = '/servers/'.$server['uid']; + + // Путь для файлового менеджера + $dir = '/'; + + $aData = array( + 'root' => $dir, + 'host' => $ip, + 'login' => $server['uid'], + 'passwd' => $server['ftp_passwd'] + ); + + if($go) + { + if(isset($url['action']) AND in_array($url['action'], array('on', 'off', 'change', 'logs'))) + { + $sql->query('SELECT `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = array_merge($unit, $sql->get()); + + include(LIB.'ssh.php'); + + // Проверка соединения с ssh сервером + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + }else{ + include(LIB.'ftp.php'); + + $ftp = new ftp; + + // Проверка соединения с ftp сервером + if(!$ftp->auth($aData['host'], $aData['login'], $aData['passwd'])) + { + if(isset($url['action'])) + { + if($url['action'] == 'search') + sys::out('Не удалось соединиться с ftp-сервером.'); + + sys::outjs(array('e' => 'Не удалось соединиться с ftp-сервером.')); + } + + sys::out(); + } + } + + // Выполнение операций + if(isset($url['action'])) + switch($url['action']) + { + case 'on': + if($server['ftp']) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + $used = sys::int($ssh->get('cd /servers/'.$server['uid'].' && du -b | tail -1')); + + if($used < 1) + sys::back($cfg['http'].'help/action/create'); + + $bytes = $server['hdd']*1048576; + + $server['ftp_passwd'] = isset($server['ftp_passwd']{1}) ? $server['ftp_passwd'] : sys::passwd(8); + + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';' + .'INSERT INTO users set username=\''.$server['uid'].'\', password=\''.$server['ftp_passwd'].'\', uid=\''.$server['uid'].'\', gid=\'1000\', homedir=\''.$homedir.'\', shell=\'/bin/false\';'; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + $sql->query('UPDATE `control_servers` SET `ftp`="1", `ftp_passwd`="'.$server['ftp_passwd'].'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_filetp_'.$sid); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + case 'change': + if(!$server['ftp']) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + $passwd = sys::passwd(8); + + $qSql = "UPDATE users set password='".$passwd."' WHERE username='".$server['uid']."' LIMIT 1"; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e '.'"'.$qSql.'"'); + + $sql->query('UPDATE `control_servers` SET `ftp_passwd`="'.$passwd.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_filetp_'.$sid); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + case 'off': + if(!$server['ftp']) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';'; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + $sql->query('UPDATE `control_servers` SET `ftp`="0" WHERE `id`="'.$sid.'" LIMIT 1'); + + $mcache->delete('ctrl_server_filetp_'.$sid); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/filetp'); + + case 'rename': + $ftp->rename(json_decode($_POST['path']), json_decode($_POST['name']), json_decode($_POST['newname'])); + + case 'edit': + $ftp->edit_file(json_decode($_POST['path']), json_decode($_POST['name'])); + + case 'create': + if(isset($url['folder'])) + $ftp->mkdir(json_decode($_POST['path']), json_decode($_POST['name'])); + + $ftp->touch(json_decode($_POST['path']), json_decode($_POST['name']), json_decode($_POST['text'])); + + case 'delete': + if(isset($url['folder'])) + $ftp->rmdir(json_decode($_POST['path']), json_decode($_POST['name'])); + + $ftp->rmfile(json_decode($_POST['path']).'/'.json_decode($_POST['name'])); + + case 'chmod': + $ftp->chmod(json_decode($_POST['path']), json_decode($_POST['name']), sys::int($_POST['chmod'])); + + case 'search': + $text = isset($_POST['find']) ? sys::first(explode('.', json_decode($_POST['find']))) : sys::out(); + + if(!isset($text{2})) + sys::out('Для выполнения поиска, необходимо больше данных'); + + $ftp->search($text, $id); + + case 'logs': + $logs = $mcache->get('ctrl_filetp_logs_'.$sid); + + if(!$logs) + { + include(LIB.'ftp.php'); + + $ftp = new ftp; + + $logs = $ftp->logs($ssh->get('cat /var/log/proftpd/xferlog | grep "/'.$server['uid'].'/" | awk \'{print $2"\\\"$3"\\\"$4"\\\"$5"\\\"$7"\\\"$8"\\\"$9"\\\"$12}\' | tail -50'), $server['uid']); + + $mcache->set('ctrl_filetp_logs_'.$sid, $logs, false, 300); + } + + sys::out($logs); + } + + if(!isset($_POST['path'])) $_POST['path'] = json_encode($aData['root']); + + sys::out($ftp->view($ftp->read(json_decode($_POST['path'])), $sid)); + } + + if($mcache->get('ctrl_server_filetp_'.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_filetp_'.$sid); + else{ + if($server['ftp']) + { + $html->get('filetp_on', 'sections/control/servers/games/filetp'); + + $html->set('address', 'ftp://'.$aData['login'].':'.$aData['passwd'].'@'.$aData['host']); + $html->set('server', $aData['host']); + $html->set('login', $aData['login']); + $html->set('passwd', $aData['passwd']); + $html->set('path', $aData['root']); + }else + $html->get('filetp_off', 'sections/control/servers/games/filetp'); + + $html->set('id', $id); + $html->set('server', $sid); + + $html->pack('main'); + + $mcache->set('ctrl_server_filetp_'.$sid, $html->arr['main'], false, 10); + } + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/check.php b/system/sections/control/servers/games/copy/check.php new file mode 100644 index 0000000..60754ed --- /dev/null +++ b/system/sections/control/servers/games/copy/check.php @@ -0,0 +1,26 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache'))); + + $mcache->set($nmch, true, false, 10); + + $copys = $sql->query('SELECT `id` FROM `control_copy` WHERE `user`="'.$ctrl['user'].'_'.$id.'" AND `status`="0"'); + if(!$sql->num($copys)) + sys::outjs(array('e' => 'no find'), $nmch); + + while($copy = $sql->get($copys)) + { + if(!sys::int($ssh->get('ps aux | grep copy_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `control_copy` set `status`="1" WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + + // Очистка кеша + $mcache->delete('ctrl_server_copy_'.$sid); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/create.php b/system/sections/control/servers/games/copy/create.php new file mode 100644 index 0000000..59e98e6 --- /dev/null +++ b/system/sections/control/servers/games/copy/create.php @@ -0,0 +1,54 @@ +query('SELECT `id` FROM `control_copy` WHERE `server`="'.$sid.'" ORDER BY `id` DESC LIMIT 5'); + if($sql->num() > 4) + sys::outjs(array('e' => 'Для создания новой копии необходимо удалить старые.'), $nmch); + + $sql->query('SELECT `id` FROM `control_copy` WHERE `server`="'.$sid.'" AND `status`="0" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Для создания новой копии дождитесь создания предыдущей.'), $nmch); + + $aSel = array(); + + $aData = isset($_POST['copy']) ? $_POST['copy'] : sys::outjs(array('e' => 'Для создания копии необходимо выбрать директории/файлы.'), $nmch); + + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + if(!isset($aData['\''.$name.'\''])) + continue; + + $aSel[] = $name; + } + + if(!count($aSel)) + sys::outjs(array('e' => 'Для создания копии необходимо выбрать директории/файлы.'), $nmch); + + $copy = ''; + $info = ''; + $plugins = ''; + + foreach($aSel as $name) + { + $copy .= isset(params::$section_copy[$server['game']]['aCopyDir'][$name]) ? params::$section_copy[$server['game']]['aCopyDir'][$name].' ' : ''; + $copy .= isset(params::$section_copy[$server['game']]['aCopyFile'][$name]) ? params::$section_copy[$server['game']]['aCopyFile'][$name].' ' : ''; + + $info .= $name.', '; + } + + $name_copy = md5($start_point.$id.$server['game']); + + $ssh->set('cd /servers/'.$server['uid'].' && screen -dmS copy_'.$server['uid'].' sh -c "tar -cf '.$name_copy.'.tar '.$copy.'; mv '.$name_copy.'.tar /copy"'); + + $sql->query('SELECT `plugin`, `upd` FROM `control_plugins_install` WHERE `server`="'.$sid.'"'); + while($plugin = $sql->get()) + $plugins .= $plugin['plugin'].'.'.$plugin['upd'].','; + + $sql->query('INSERT INTO `control_copy` set `user`="'.$ctrl['user'].'_'.$id.'", `game`="'.$server['game'].'", `server`="'.$sid.'", `pack`="'.$server['pack'].'", `name`="'.$name_copy.'", `info`="'.substr($info, 0, -2).'", `plugins`="'.substr($plugins, 0, -1).'", `date`="'.$start_point.'", `status`="0"'); + + // Очистка кеша + $mcache->delete('ctrl_server_copy_'.$sid); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/fullcopy.php b/system/sections/control/servers/games/copy/fullcopy.php new file mode 100644 index 0000000..e920730 --- /dev/null +++ b/system/sections/control/servers/games/copy/fullcopy.php @@ -0,0 +1,25 @@ +query('SELECT `id` FROM `control_copy` WHERE `server`="'.$sid.'" AND `info`="'.params::$section_copy[$server['game']]['CopyFull'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Для создания новой копии необходимо удалить старую.'), $nmch); + + $name_copy = md5($id.$start_point.$sid.$server['game']); + + $ssh->set('cd /servers/'.$server['uid'].' && screen -dmS copy_'.$server['uid'].' sh -c "tar -cf '.$name_copy.'.tar '.params::$section_copy[$server['game']]['CopyFull'].'; mv '.$name_copy.'.tar /copy"'); + + $plugins = ''; + + $sql->query('SELECT `plugin`, `upd` FROM `control_plugins_install` WHERE `server`="'.$sid.'"'); + while($plugin = $sql->get()) + $plugins .= $plugin['plugin'].'.'.$plugin['upd'].','; + + $sql->query('INSERT INTO `control_copy` set `user`="'.$ctrl['user'].'_'.$id.'", `game`="'.$server['game'].'", `server`="'.$sid.'", `pack`="'.$server['pack'].'", `name`="'.$name_copy.'", `info`="'.params::$section_copy[$server['game']]['CopyFull'].'", `plugins`="'.substr($plugins, 0, -1).'", `date`="'.$start_point.'", `status`="0"'); + + // Очистка кеша + $mcache->delete('ctrl_server_copy_'.$sid); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/recfull.php b/system/sections/control/servers/games/copy/recfull.php new file mode 100644 index 0000000..3bb8e7d --- /dev/null +++ b/system/sections/control/servers/games/copy/recfull.php @@ -0,0 +1,76 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `id`, `pack`, `name`, `info`, `plugins`, `date`, `status` FROM `control_copy` WHERE `id`="'.$cid.'" AND `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + if($copy['pack'] != $server['pack']) + { + $aPack = $cfg['control_packs'][$server['game']]; + + sys::outjs(array('e' => 'Для восстановления необходимо установить сборку: '.$aPack[$copy['pack']].'.'), $nmch); + } + + if(params::$section_copy[$server['game']]['CopyFull'] == $copy['info']) + $rm = 'rm -r '.$copy['info']; + else{ + $rm = ''; + + $aInfo = explode(', ', $copy['info']); + + foreach($aInfo as $name) + { + $rm .= isset(params::$section_copy[$server['game']]['aCopyDir'][$name]) ? 'rm -r '.params::$section_copy[$server['game']]['aCopyDir'][$name].' ' : ''; + $rm .= isset(params::$section_copy[$server['game']]['aCopyFile'][$name]) ? 'rm '.params::$section_copy[$server['game']]['aCopyFile'][$name].' ' : ''; + } + + } + + $ssh->set('cd /servers/'.$server['uid'].' && screen -dmS rec_'.$server['uid'].' sh -c "' + .$rm.'; cp /copy/'.$copy['name'].'.tar . && tar -xf '.$copy['name'].'.tar; rm '.$copy['name'].'.tar;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].';' + .'chown -R servers'.$server['uid'].':servers ."'); + + // Удаление плагинов + $sql->query('DELETE FROM `control_plugins_install` WHERE `server`="'.$sid.'"'); + + // Установка плагинов (имитирование) + $aPlugins = explode(',', $copy['plugins']); + + foreach($aPlugins as $plugin) + { + $aPlugin = explode('.', $plugin); + + if(!count($aPlugin != 2)) + continue; + + if(!$aPlugin[0]) + continue; + + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `plugin`="'.$aPlugin[0].'" AND `server`="'.$sid.'" LIMIT 1'); + + if(!$aPlugin[1]) + $aPlugin[1] = 0; + + if(!$sql->num()) + $sql->query('INSERT INTO `control_plugins_install` set `server`="'.$sid.'", `plugin`="'.$aPlugin[0].'", `upd`="'.$aPlugin[1].'", `time`="'.$copy['date'].'"'); + } + + // Очистка кеша + $mcache->delete('ctrl_server_plugins_'.$sid); + + $sql->query('UPDATE `control_servers` set `status`="recovery" WHERE `id`="'.$sid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/recpart.php b/system/sections/control/servers/games/copy/recpart.php new file mode 100644 index 0000000..98d88f2 --- /dev/null +++ b/system/sections/control/servers/games/copy/recpart.php @@ -0,0 +1,50 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `id`, `pack`, `name`, `plugins`, `date`, `status` FROM `control_copy` WHERE `id`="'.$cid.'" AND `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + if($copy['pack'] != $server['pack']) + { + $aPack = $cfg['control_packs'][$server['game']]; + + sys::outjs(array('e' => 'Для восстановления необходимо установить сборку: '.$aPack[$copy['pack']].'.'), $nmch); + } + + $ssh->set('cd /servers/'.$server['uid'].' && screen -dmS rec_'.$server['uid'].' sh -c "' + .'cp /copy/'.$copy['name'].'.tar . && tar -xf '.$copy['name'].'.tar; rm '.$copy['name'].'.tar;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].';' + .'chown -R servers'.$server['uid'].':servers ."'); + + // Установка плагинов (имитирование) + $aPlugin = explode(',', $copy['plugins']); + + foreach($aPlugin as $plugin) + { + if(!$plugin) + continue; + + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `plugin`="'.$plugin.'" AND `server`="'.$sid.'" LIMIT 1'); + + if(!$sql->num()) + $sql->query('INSERT INTO `control_plugins_install` set `server`="'.$sid.'", `plugin`="'.$plugin.'", `time`="'.$copy['date'].'"'); + } + + // Очистка кеша + $mcache->delete('ctrl_server_plugins_'.$sid); + + $sql->query('UPDATE `control_servers` set `status`="recovery" WHERE `id`="'.$sid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/copy/remove.php b/system/sections/control/servers/games/copy/remove.php new file mode 100644 index 0000000..f876e81 --- /dev/null +++ b/system/sections/control/servers/games/copy/remove.php @@ -0,0 +1,24 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `name`, `status` FROM `control_copy` WHERE `id`="'.$cid.'" AND `user`="'.$ctrl['user'].'_'.$id.'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + $ssh->set('screen -dmS rem_copy_'.$cid.' rm /copy/'.$copy['name'].'.tar'); + + $sql->query('DELETE FROM `control_copy` WHERE `id`="'.$cid.'" LIMIT 1'); + + // Очистка кеша + $mcache->delete('ctrl_server_copy_'.$sid); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/config.php b/system/sections/control/servers/games/plugins/config.php new file mode 100644 index 0000000..1ccc740 --- /dev/null +++ b/system/sections/control/servers/games/plugins/config.php @@ -0,0 +1,83 @@ +query('SELECT `plugin`, `update`, `file` FROM `plugins_config` WHERE `id`="'.$fid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $config = $sql->get(); + + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$config['plugin'].'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + // Если обновленный плагин + if($config['update']) + $sql->query('SELECT `name` FROM `plugins_update` WHERE `id`="'.$config['update'].'" LIMIT 1'); + else + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$config['plugin'].'" LIMIT 1'); + + $plugin = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Данные файла + $file = explode('/', $config['file']); + + // Полный путь файла + $path = $tarif['install'].$server['uid'].'/'.$config['file']; + + // Сохранение + if($go) + { + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $path, 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$path); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$path.'; cat '.$path.'"'); + + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + $html->nav($plugin['name'], $cfg['http'].'servers/id/'.$id.'/section/plugins/subsection/plugin/plugin/'.$config['plugin']); + + $html->get('config', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('file', $fid); + $html->set('plugin', $config['plugin']); + $html->set('name', end($file)); + $html->set('data', htmlspecialchars($ssh->get())); + + $html->pack('main'); + +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/delete.php b/system/sections/control/servers/games/plugins/delete.php new file mode 100644 index 0000000..a8caba8 --- /dev/null +++ b/system/sections/control/servers/games/plugins/delete.php @@ -0,0 +1,84 @@ +query('SELECT `id`, `upd` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Данный плагин не установлен')); + + $plugin = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + // Директория игр. сервера + $dir = '/servers/'.$server['uid'].'/'; + + // Имя исполняемого файла + if($plugin['upd']) + { + $qsql = 'WHERE `update`="'.$plugin['upd'].'" ORDER BY `id` ASC'; + $frm = 'u'.$plugin['upd']; + }else{ + $qsql = 'WHERE `plugin`="'.$pid.'" AND `update`="0" ORDER BY `id` ASC'; + $frm = $pid; + } + + // Удаление и установка файлов + $ssh->set('cd '.$dir.' && screen -dmS delete_upd_'.$start_point.' ' + .'sudo -u server'.$server['uid'].' sh -c "' + .'wget --no-check-certificate '.$cfg['plugins'].'delete/'.$frm.'.rm && ' + .'chmod 755 '.$frm.'.rm; ./'.$frm.'.rm; rm '.$frm.'.rm"'); + + include(LIB.'control/plugins.php'); + + // Удаление добавленного при установке текста в файлах + $sql->query('SELECT `text`, `file` FROM `plugins_write` '.$qsql); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + unset($clear); + + // Добавление текста при удалении в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write_del` '.$qsql); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Удаление записи установленного плагина в базе + $sql->query('DELETE FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'"'); + + // Очистка кеша + $mcache->delete('ctrl_server_plugins_'.$id); + + if($plugin['upd']) + $sql->query('SELECT `install` FROM `plugins_delete_ins` WHERE `update`="'.$plugin['upd'].'" LIMIT 1'); + else + $sql->query('SELECT `install` FROM `plugins_delete_ins` WHERE `plugin`="'.$pid.'" AND `update`="0" LIMIT 1'); + + if($sql->num()) + { + $ins = $sql->get(); + + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$ins['install'].'" LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + sys::outjs(array('i' => $ins['install'], 'pname' => $plugin['name']), $nmch); + } + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/install.php b/system/sections/control/servers/games/plugins/install.php new file mode 100644 index 0000000..f84784a --- /dev/null +++ b/system/sections/control/servers/games/plugins/install.php @@ -0,0 +1,133 @@ +query('SELECT `name`, `cfg`, `upd`, `incompatible`, `required`, `packs`, `price` FROM `plugins` WHERE `id`="'.$pid.'" AND `game`="'.$server['game'].'" LIMIT 1'); + + if(!$sql->num()) + exit; + + $plugin = $sql->get(); + + // Проверка установки плагина + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный плагин уже установлен')); + + $upd = false; + + // Если есть более поздняя версия плагина + if($plugin['upd']) + { + $sql->query('SELECT `name`, `id`, `cfg`, `incompatible`, `required`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$pid.'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = array_merge($plugin, $sql->get()); + + $upd = true; + } + } + + $buy = false; + + // Если платный плагин + if($plugin['price']) + { + // Проверка покупки + $sql->query('SELECT `id` FROM `control_plugins_buy` WHERE `plugin`="'.$pid.'" AND `server`="'.$sid.'" LIMIT 1'); + if($sql->num()) + $buy = true; + else{ + // Проверка баланса + if($user['balance'] < $plugin['price']) + sys::outjs(array('e' => 'У вас не хватает '.(round($plugin['price']-$user['balance'], 2)).' '.$cfg['currency']), $name_mcache); + } + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + exit; + + include(LIB.'control/plugins.php'); + + // Проверка на наличие несовместимости с уже установленными плагинами + plugins::incompatible($sid, $plugin['incompatible'], $nmch); + + // Проверка на наличие необходимых установленых плагинов для устанавливаемого дополнения + plugins::required($sid, $plugin['required'], $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($upd) + { + $qsql = 'WHERE `update`="'.$plugin['id'].'" ORDER BY `id` ASC'; + $fzip = 'u'.$plugin['id']; + $upd = $plugin['id']; + }else{ + $qsql = 'WHERE `plugin`="'.$pid.'" AND `update`="0" ORDER BY `id` ASC'; + $fzip = $pid; + $upd = 0; + } + + // Директория игр. сервера + $dir = '/servers/'.$server['uid'].'/'; + + // Установка файлов на сервер + $ssh->set('cd '.$dir.' && screen -dmS install_'.$start_point.' sudo -u server'.$server['uid'].' sh -c "' + .'wget --no-check-certificate '.$cfg['plugins'].'install/'.$fzip.'.zip && unzip -o '.$fzip.'.zip; rm '.$fzip.'.zip;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + // Удаление файлов + $sql->query('SELECT `file` FROM `plugins_delete` '.$qsql); + while($delete = $sql->get()) + $ssh->set('sudo -u server'.$server['uid'].' rm '.$dir.$delete['file']); + + // Удаление текста из файлов + $sql->query('SELECT `text`, `file`, `regex` FROM `plugins_clear` '.$qsql); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + // Добавление текста в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write` '.$qsql); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Если платный плагин + if(!$buy AND $plugin['price']) + { + $sql->query('UPDATE `users` set `balance`=`balance`-"'.$plugin['price'].'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `control_plugins_buy` set `plugin`="'.$pid.'", `key`="'.md5(strip_tags($plugin['name'])).'", `server`="'.$sid.'", `price`="'.$plugin['price'].'", `time`="'.$start_point.'"'); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'ctrl_buy_plugin'), + array('plugin' => strip_tags($plugin['name']), 'money' => $plugin['price'], 'id' => $sid)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$plugin['price'].'"'); + } + + // Запись данных в базу + $sql->query('INSERT INTO `control_plugins_install` set `server`="'.$sid.'", `plugin`="'.$pid.'", `upd`="'.$upd.'", `time`="'.$start_point.'"'); + + // Очистка кеша + $mcache->delete('ctrl_server_plugins_'.$sid); + + if($plugin['cfg']) + sys::outjs(array('s' => 'cfg'), $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/plugin.php b/system/sections/control/servers/games/plugins/plugin.php new file mode 100644 index 0000000..7ba4f96 --- /dev/null +++ b/system/sections/control/servers/games/plugins/plugin.php @@ -0,0 +1,89 @@ +query('SELECT `id`, `upd` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $install = $sql->get(); + + // Если установленно обновление + if($install['upd']) + $sql->query('SELECT `name`, `info`, `images`, `upd` FROM `plugins_update` WHERE `id`="'.$install['upd'].'" LIMIT 1'); + else + $sql->query('SELECT `name`, `info`, `images`, `upd` FROM `plugins` WHERE `id`="'.$pid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + + $plugin = $sql->get(); + + $html->nav('Плагины', $cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/plugins'); + $html->nav($plugin['name']); + + // Если есть кеш + if($mcache->get('ctrl_server_plugin_'.$pid.$sid) != '') + $html->arr['main'] = $mcache->get('ctrl_server_plugin_'.$pid.$sid); + else{ + include(LIB.'control/plugins.php'); + + // Построение списка редактируемых файлов + $aConf = array(); + + $sql->query('SELECT `id`, `file` FROM `plugins_config` WHERE (`plugin`="'.$pid.'" AND `update`="0") OR (`plugin`="'.$pid.'" AND `update`="'.$install['upd'].'") ORDER BY `sort`, `id` ASC'); + while($config = $sql->get()) + { + // Исключить дублирование, путем проверки массива файлов + if(in_array($config['file'], $aConf)) + continue; + + $aConf[] = $config['file']; + + // Данные файла + $file = explode('/', $config['file']); + + $html->get('config_list', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('fid', $config['id']); + $html->set('name', end($file)); + $html->set('file', $config['file']); + + $html->pack('configs'); + } + + $images = plugins::images($plugin['images'], $pid); + + $html->get('configs', 'sections/control/servers/games/plugins'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $plugin['name']); + $html->set('info', htmlspecialchars_decode($plugin['info'])); + + // Картинки + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + // Редактируемые файлы + if(isset($html->arr['configs'])) + { + $html->set('configs', $html->arr['configs']); + $html->unit('configs', 1); + }else + $html->unit('configs'); + + $html->pack('main'); + + $mcache->set('ctrl_server_plugin_'.$pid.$sid, $html->arr['main'], false, 60); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/search.php b/system/sections/control/servers/games/plugins/search.php new file mode 100644 index 0000000..bfe215b --- /dev/null +++ b/system/sections/control/servers/games/plugins/search.php @@ -0,0 +1,201 @@ + '')); + + $mkey = md5($sid.$text.$id); + + if($mcache->get($mkey) != '') + sys::outjs(array('s' => $mcache->get($mkey))); + + if(!isset($text{2})) + sys::outjs(array('s' => 'Для выполнения поиска, необходимо больше данных', $nmch)); + + $sPlugins = array(); + $sUpdate = array(); + + // Поиск по плагинам + $plugins = $sql->query('SELECT `id`, `packs` FROM `plugins` WHERE `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 5'); + + // Поиск по обновлениям + $update = false; + + if(!$sql->num($plugins)) + { + $plugins = $sql->query('SELECT `id`, `plugin`, `packs` FROM `plugins_update` WHERE `game`="'.$server['game'].'" AND (`name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\')) AND `upd`="0" LIMIT 5'); + $update = true; + } + + // Если нет ниодного совпадения по вводимому тексту + if(!$sql->num($plugins)) + { + // Поиск по словам + if(strpos($text, ' ')) + { + // Массив слов + $aText = explode(' ', $text); + + // Метка, которая изменится в процессе, если будет найдено хоть одно совпадение + $sWord = false; + + foreach($aText as $word) + { + if($word == '' || !isset($word{2})) + continue; + + // Поиск по плагинам + $plugins = $sql->query('SELECT `id`, `packs` FROM `plugins` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 5'); + + // Поиск по обновлениям + $update = false; + + if(!$sql->num($plugins)) + { + $plugins = $sql->query('SELECT `id`, `plugin`, `packs` FROM `plugins_update` WHERE (`name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\')) AND `upd`="0" LIMIT 5'); + $update = true; + } + + if($sql->num($plugins)) + { + if(!$sWord) $sWord = true; + + $sPlugins[] = $plugins; + $sUpdate[] = $update; + } + } + + // Если нет ниодного совпадения + if(!$sWord) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + }else{ + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + }else{ + $sPlugins[] = $plugins; + $sUpdate[] = $update; + } + + // Массив для исклуючения дублирования + $aPlugins = array(); + + foreach($sPlugins as $index => $plugins) + { + while($plugin = $sql->get($plugins)) + { + // Проверка дублирования + if(($sUpdate[$index] AND in_array($plugin['plugin'], $aPlugins)) || !$sUpdate[$index] AND in_array($plugin['id'], $aPlugins)) + continue; + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':', $plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $install = false; // не установлен плагин + $upd = false; // не обновлен плагин + + if($sUpdate[$index]) + { + $sql->query('SELECT `id`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['plugin'].'" LIMIT 1'); + + $aPlugins[] = $plugin['plugin']; + }else{ + $sql->query('SELECT `id`, `upd`, `time` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + + $aPlugins[] = $plugin['id']; + } + + // Проверка на установку + if($sql->num()) + { + $install = $sql->get(); + + $upd = $install['upd']; + $time = sys::today($install['time']); + + $install = true; + } + + // Если установлен обновленный плагин + if($upd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$upd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['id'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + $html->get('search', 'sections/control/servers/games/plugins'); + + // Если установлен + if($install) + { + // Если есть обновление + if($plugin['upd'] > $upd) $html->unit('update', 1); else $html->unit('update'); + + // Если есть редактируемые файлы + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + $html->unit('install', 1); + $html->unit('!install'); + }else{ + // Обновление данных на более позднею версию плагина + $sql->query('SELECT `name`, `desc`, `status`, `cfg` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" AND `upd`="0" LIMIT 1'); + if($sql->num()) + { + $upd = $sql->get(); + + $plugin['name'] = $upd['name']; + $plugin['desc'] = $upd['desc']; + $plugin['status'] = $upd['status']; + $plugin['cfg'] = $upd['cfg']; + } + + $html->unit('install'); + $html->unit('!install', 1); + } + + if(!$plugin['status']) + { + $html->unit('unstable'); + $html->unit('stable', 1); + $html->unit('testing'); + }elseif($plugin['status'] == 2){ + $html->unit('unstable'); + $html->unit('stable'); + $html->unit('testing', 1); + }else{ + $html->unit('unstable', 1); + $html->unit('stable'); + $html->unit('testing'); + } + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('plugin', $plugin['id']); + + if($install) + $html->set('time', $time); + + $html->set('name', sys::find(htmlspecialchars_decode($plugin['name']), $text)); + $html->set('desc', sys::find(htmlspecialchars_decode($plugin['desc']), $text)); + + $html->pack('plugins'); + } + } + + $html->arr['plugins'] = isset($html->arr['plugins']) ? $html->arr['plugins'] : ''; + + $mcache->set($mkey, $html->arr['plugins'], false, 15); + + sys::outjs(array('s' => $html->arr['plugins']), $nmch); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/plugins/update.php b/system/sections/control/servers/games/plugins/update.php new file mode 100644 index 0000000..3d9fe1b --- /dev/null +++ b/system/sections/control/servers/games/plugins/update.php @@ -0,0 +1,85 @@ +query('SELECT `id` FROM `plugins_update` WHERE `plugin`="'.$pid.'" ORDER BY `id` DESC LIMIT 1'); + + if(!$sql->num()) + exit(); + + $plugin = $sql->get(); + + // Проверка установки плагина + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if(!$sql->num()) + exit(); + + // Проверка установки обновления плагина + $sql->query('SELECT `id` FROM `control_plugins_install` WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" AND `upd`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный плагин уже обновлен')); + + // Данные обновления + $sql->query('SELECT `id`, `cfg`, `incompatible`, `required` FROM `plugins_update` WHERE `id`="'.$plugin['id'].'" LIMIT 1'); + + $plugin = $sql->get(); + + include(LIB.'control/plugins.php'); + + // Проверка на наличие несовместимости с уже установленными плагинами + plugins::incompatible($sid, $plugin['incompatible'], $nmch); + + // Проверка на наличие необходимых установленых плагинов для устанавливаемого плагина + plugins::required($sid, $plugin['required'], $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + // Директория игр. сервера + $dir = '/servers/'.$server['uid'].'/'; + + // Установка файлов на сервер + $ssh->set('cd '.$dir.' && screen -dmS update_'.$start_point.' sudo -u server'.$server['uid'].' sh -c "wget --no-check-certificate '.$cfg['plugins'].'update/'.$plugin['id'].'.zip && unzip -o '.$plugin['id'].'.zip; rm '.$plugin['id'].'.zip"'); + + // Удаление файлов + $sql->query('SELECT `file` FROM `plugins_delete` WHERE `update`="'.$plugin['id'].'"'); + while($delete = $sql->get()) + $ssh->set('sudo -u server'.$server['uid'].' rm '.$dir.$delete['file']); + + unset($delete); + + // Удаление текста из файлов + $sql->query('SELECT `text`, `file`, `regex` FROM `plugins_clear` WHERE `update`="'.$plugin['id'].'"'); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + unset($clear); + + // Добавление текста в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write` WHERE `update`="'.$plugin['id'].'" ORDER BY `id` ASC'); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Обновление данных в базе + $sql->query('UPDATE `control_plugins_install` set `upd`="'.$plugin['id'].'", `time`="'.$start_point.'" WHERE `server`="'.$sid.'" AND `plugin`="'.$pid.'" LIMIT 1'); + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + if($plugin['cfg']) + sys::outjs(array('s' => 'cfg'), $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/settings/crontab.php b/system/sections/control/servers/games/settings/crontab.php new file mode 100644 index 0000000..8d534ba --- /dev/null +++ b/system/sections/control/servers/games/settings/crontab.php @@ -0,0 +1,109 @@ +nav('Планировщик задач'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + // Удаление задания + if(isset($url['action']) AND $url['action'] == 'delete') + { + $task = isset($_POST['task']) ? sys::int($_POST['task']) : sys::outjs(array('s' => 'ok'), $nmch); + + $sql->query('SELECT `cron` FROM `control_crontab` WHERE `id`="'.$task.'" AND `server`="'.$sid.'" LIMIT 1'); + if(!$sql->num()) + $sys->outjs(array('s' => 'ok'), $nmch); + + $cron = $sql->get(); + + $ssh->set('touch /etc/crontab; cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab;" + .'crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `control_crontab` WHERE `id`="'.$task.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Добавление задания + $sql->query('SELECT `id` FROM `control_crontab` WHERE `server`="'.$sid.'" LIMIT 5'); + if($sql->num() == $cfg['crontabs']) + sys::outjs(array('e' => sys::text('servers', 'crontab')), $nmch); + + $data = array(); + + $data['task'] = isset($_POST['task']) ? $_POST['task'] : 'start'; + + $task = in_array($server['game'], array('samp', 'crmp')) ? array('start', 'restart', 'stop') : array('start', 'restart', 'stop', 'console'); + + if(!in_array($data['task'], $task)) + $data['task'] = 'start'; + + $data['commands'] = isset($_POST['commands']) ? base64_encode(htmlspecialchars($_POST['commands'])) : ''; + $data['allhour'] = isset($_POST['allhour']) ? true : false; + $data['hour'] = isset($_POST['hour']) ? $_POST['hour'] : '00'; + $data['minute'] = isset($_POST['minute']) ? $_POST['minute'] : '00'; + $data['week'] = (isset($_POST['week']) AND is_array($_POST['week'])) ? $_POST['week'] : array(); + + $sql->query('INSERT INTO `control_crontab` set `server`="'.$sid.'"'); + $cid = $sql->id(); + + include(LIB.'games/games.php'); + + $cron_rule = ctrl::crontab($data, $sid, $cid); + + $ssh->set('echo "'.$cron_rule.'" >> /etc/crontab;' + ."sed -i '/^$/d' /etc/crontab;" + .'crontab -u root /etc/crontab'); + + $time = games::crontab_time($data['allhour'], $data['hour'], $data['minute']); + $week = games::crontab_week($data['week']); + + $sql->query('UPDATE `control_crontab` set `server`="'.$sid.'", `task`="'.$data['task'].'", `cron`="'.$cron_rule.'", `week`="'.$week.'", `time`="'.$time.'", `commands`="'.$data['commands'].'" WHERE `id`="'.$cid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $aTask = array( + 'start' => 'Включение сервера', + 'stop' => 'Выключение сервера', + 'restart' => 'Перезагрузка сервера', + 'console' => 'Отправка команд на сервер' + ); + + $sql->query('SELECT `id`, `task`, `week`, `time` FROM `control_crontab` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($crontab = $sql->get()) + { + $html->get('crontab_list', 'sections/control/servers/games/settings'); + $html->set('id', $crontab['id']); + $html->set('task', $aTask[$crontab['task']]); + $html->set('week', $crontab['week']); + $html->set('time', $crontab['time']); + $html->pack('crontab'); + } + + $html->get('crontab', 'sections/control/servers/'.$server['game'].'/settings'); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('time', date('H:i:s', $start_point)); + $html->set('crontab', isset($html->arr['crontab']) ? $html->arr['crontab'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/settings/file.php b/system/sections/control/servers/games/settings/file.php new file mode 100644 index 0000000..30b7c1e --- /dev/null +++ b/system/sections/control/servers/games/settings/file.php @@ -0,0 +1,59 @@ +nav('Редактирование файла: '.$file); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + } + + // Полный путь файла + $path = '/servers/'.$server['uid'].'/'.$aEdits[$server['game']]['all']['path'][$file].$file; + + if($go) + { + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $path, 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$path); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$path.'; cat '.$path.'"'); + + $html->get('file', 'sections/control/servers/games/settings'); + + $html->set('id', $id); + $html->set('server', $sid); + $html->set('file', $file); + $html->set('data', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/settings/firewall.php b/system/sections/control/servers/games/settings/firewall.php new file mode 100644 index 0000000..28da443 --- /dev/null +++ b/system/sections/control/servers/games/settings/firewall.php @@ -0,0 +1,39 @@ +nav('Блокировка на оборудовании'); + + if(isset($url['action'])) + { + include(LIB.'games/games.php'); + + // Получение информации адреса + if($url['action'] == 'info') + games::iptables_whois($nmch); + + // Добавление / удаление правил + if($go && in_array($url['action'], array('block', 'unblock'))) + { + $address = isset($_POST['address']) ? trim($_POST['address']) : sys::outjs(array('e' => sys::text('servers', 'firewall')), $nmch); + $snw = isset($_POST['subnetwork']) ? true : false; + + sys::outjs(ctrl::iptables($sid, $url['action'], $address, explode(':', $server['address']), $id, $snw), $nmch); + } + } + + $sql->query('SELECT `id`, `sip` FROM `control_firewall` WHERE `server`="'.$sid.'" ORDER BY `id` ASC'); + while($firewall = $sql->get()) + { + $html->get('list', 'sections/control/servers/games/settings/firewall'); + $html->set('id', $firewall['id']); + $html->set('address', $firewall['sip']); + $html->pack('firewall'); + } + + $html->get('firewall', 'sections/control/servers/games/settings'); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('firewall', isset($html->arr['firewall']) ? $html->arr['firewall'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/settings/pack.php b/system/sections/control/servers/games/settings/pack.php new file mode 100644 index 0000000..a70c43d --- /dev/null +++ b/system/sections/control/servers/games/settings/pack.php @@ -0,0 +1,19 @@ + 'ok')); + + // Проверка сборки + if(!array_key_exists($pack, $aPacks)) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $sql->query('UPDATE `control_servers` set `pack`="'.$pack.'" WHERE `id`="'.$sid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), 'ctrl_server_settings_'.$sid); +?> \ No newline at end of file diff --git a/system/sections/control/servers/games/settings/startlogs.php b/system/sections/control/servers/games/settings/startlogs.php new file mode 100644 index 0000000..1ad5b61 --- /dev/null +++ b/system/sections/control/servers/games/settings/startlogs.php @@ -0,0 +1,93 @@ +nav('Снимки консоли'); + + $sql->query('SELECT `ftp`, `ftp_root`, `ftp_passwd` FROM `servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings'); + + // Путь к логам + $folder = '/servers/'.$server['uid'].'/'.$aSLdir[$server['game']]; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['startlogs'])) + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/startlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/control/servers/games/settings/logs'); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'startlogs'); + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'control/id/'.$id.'/server/'.$sid.'/section/settings/subsection/startlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/control/servers/games/settings/startlogs'); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('name', end($name)); + $html->set('date', $date); + $html->set('size', $size); + + if($server['ftp']) + { + $html->unit('download', true, true); + + $html->set('url', 'ftp://'.$server['uid'].':'.$server['ftp_passwd'].'@'.sys::first(explode(':', $unit['address'])).'/'.$aSLdir[$server['game']].'/'.end($name)); + }else + $html->unit('download', false, true); + $html->pack('logs'); + } + + $html->get('startlogs', 'sections/control/servers/games/settings'); + $html->set('id', $id); + $html->set('server', $sid); + $html->set('uri', 'start'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/control/servers/index.php b/system/sections/control/servers/index.php new file mode 100644 index 0000000..bdde65d --- /dev/null +++ b/system/sections/control/servers/index.php @@ -0,0 +1,11 @@ +query('SELECT `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'index'); + + include(SEC.'control/servers/'.$server['game'].'/index.php'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/noaccess.php b/system/sections/control/servers/noaccess.php new file mode 100644 index 0000000..30a9d9b --- /dev/null +++ b/system/sections/control/servers/noaccess.php @@ -0,0 +1,17 @@ +nav('Раздел недоступен'); + + $status = array( + 'install' => 'установки', + 'reinstall' => 'переустановки', + 'update' => 'обновления', + 'recovery' => 'восстановления' + ); + + $html->get('noaccess'); + $html->set('status', $status[$server['status']]); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/control/servers/plugins.php b/system/sections/control/servers/plugins.php new file mode 100644 index 0000000..803a21d --- /dev/null +++ b/system/sections/control/servers/plugins.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'plugins'); + + include(ctrl::route($server, 'plugins', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/servers/rcon.php b/system/sections/control/servers/rcon.php new file mode 100644 index 0000000..b286ad8 --- /dev/null +++ b/system/sections/control/servers/rcon.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `address`, `game`, `status` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'rcon'); + + include(ctrl::route($server, 'rcon', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/servers/scan.php b/system/sections/control/servers/scan.php new file mode 100644 index 0000000..d59fc6a --- /dev/null +++ b/system/sections/control/servers/scan.php @@ -0,0 +1,27 @@ +query('SELECT `game` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'control/'.$server['game'].'/scan.php'); + + // Запрошена информация (статус, онлайн, название) + if(isset($url['mon'])) + sys::outjs(scan::mon($sid)); + + // Запрошена информация (статус, онлайн, название, игроки) + if(isset($url['fmon'])) + sys::outjs(scan::mon($sid, true)); + + // Запрошена информация (cpu, ram, hdd) + if(isset($url['resources'])) + sys::outjs(scan::resources($sid)); + + // Запрошена информация (работает, меняется карта, переустанавливается) + if(isset($url['status'])) + sys::outjs(scan::status($sid)); + + exit; +?> \ No newline at end of file diff --git a/system/sections/control/servers/settings.php b/system/sections/control/servers/settings.php new file mode 100644 index 0000000..8b77a3b --- /dev/null +++ b/system/sections/control/servers/settings.php @@ -0,0 +1,11 @@ +query('SELECT `address`, `game`, `status`, `pack` FROM `control_servers` WHERE `id`="'.$sid.'" LIMIT 1'); + $server = $sql->get(); + + ctrl::nav($server, $id, $sid, 'settings'); + + include(ctrl::route($server, 'settings', $go)); +?> \ No newline at end of file diff --git a/system/sections/control/settings.php b/system/sections/control/settings.php new file mode 100644 index 0000000..318b8bb --- /dev/null +++ b/system/sections/control/settings.php @@ -0,0 +1,56 @@ +nav('Список подключенных серверов', $cfg['http'].'control'); + + if(in_array($ctrl['status'], array('install', 'overdue', 'blocked'))) + include(SEC.'control/noaccess.php'); + else{ + $sql->query('SELECT `address`, `passwd`, `fcpu`, `ram`, `hdd` FROM `control` WHERE `id`="'.$id.'" LIMIT 1'); + $ctrl = $sql->get(); + + if($go) + { + $aData = array(); + + $aData['passwd'] = isset($_POST['passwd']) ? trim($_POST['passwd']) : $ctrl['passwd']; + $aData['fcpu'] = isset($_POST['fcpu']) ? sys::int($_POST['fcpu']) : $ctrl['fcpu']; + $aData['ram'] = isset($_POST['ram']) ? sys::int($_POST['ram']) : $ctrl['ram']; + $aData['hdd'] = isset($_POST['hdd']) ? sys::int($_POST['hdd']) : $ctrl['hdd']; + + include(LIB.'ssh.php'); + + if(sys::strlen($aData['passwd']) > 32) + sys::outjs(array('e' => 'Указанный пароль слишком длинный')); + + if(sys::valid($aData['passwd'], 'other', $aValid['passwd'])) + sys::outjs(array('e' => 'Пожалуйста, поменяйте пароль используя только латинские буквы и цифры')); + + if(!$ssh->auth($aData['passwd'], $ctrl['address'])) + sys::outjs(array('e' => 'Неудалось создать связь с физическим сервером')); + + $aData['fcpu'] = $aData['fcpu'] == 1 ? 1 : 0; + + if($aData['ram'] < 1 || $aData['ram'] > 9999999) + $aData['ram'] = 0; + + if($aData['hdd'] < 1 || $aData['hdd'] > 9999999) + $aData['hdd'] = 0; + + $sql->query('UPDATE `control` set `passwd`="'.$aData['passwd'].'", `fcpu`="'.$aData['fcpu'].'", `ram`="'.$aData['ram'].'", `hdd`="'.$aData['hdd'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + $html->nav('Параметры сервера #'.$id); + + $html->get('settings', 'sections/control'); + $html->set('id', $id); + $html->set('passwd', $ctrl['passwd']); + $html->set('ram', $ctrl['ram']); + $html->set('hdd', $ctrl['hdd']); + $html->set('fcpu', $ctrl['fcpu'] ? '' : ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/help/action/close.php b/system/sections/help/action/close.php new file mode 100644 index 0000000..b450420 --- /dev/null +++ b/system/sections/help/action/close.php @@ -0,0 +1,19 @@ + 'У вас нет доступа к данному действию.')); + + if($id) + { + if(in_array($user['group'], array('admin', 'support'))) + $sql->query('UPDATE `help` set `close`="1" WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('UPDATE `help` set `close`="1" WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + sys::outjs(array('e' => 'Вопрос не найден в базе.')); +?> \ No newline at end of file diff --git a/system/sections/help/action/delete.php b/system/sections/help/action/delete.php new file mode 100644 index 0000000..849a1da --- /dev/null +++ b/system/sections/help/action/delete.php @@ -0,0 +1,31 @@ + 'У вас нет доступа к данному действию.')); + + if($id) + { + $sql->query('DELETE FROM `help` WHERE `id`="'.$id.'" LIMIT 1'); + + $dialogs = $sql->query('SELECT `id`, `img` FROM `help_dialogs` WHERE `help`="'.$id.'"'); + while($dialog = $sql->get($dialogs)) + { + $aImg = sys::b64djs($dialog['img']); + + foreach($aImg as $img) + { + $sql->query('DELETE FROM `help_upload` WHERE `name`="'.$img.'" LIMIT 1'); + + unlink(ROOT.'upload/'.$img); + } + + $sql->query('DELETE FROM `help_dialogs` WHERE `id`="'.$dialog['id'].'" LIMIT 1'); + } + + sys::outjs(array('s' => 'ok')); + } + + sys::outjs(array('e' => 'Вопрос не найден в базе.')); +?> \ No newline at end of file diff --git a/system/sections/help/action/open.php b/system/sections/help/action/open.php new file mode 100644 index 0000000..aba7e2d --- /dev/null +++ b/system/sections/help/action/open.php @@ -0,0 +1,19 @@ + 'У вас нет доступа к данному действию.')); + + if($id) + { + if(in_array($user['group'], array('admin', 'support'))) + $sql->query('UPDATE `help` set `close`="0", `time`="'.$start_point.'" WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('UPDATE `help` set `close`="0", `time`="'.$start_point.'" WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + sys::outjs(array('e' => 'Вопрос не найден в базе.')); +?> \ No newline at end of file diff --git a/system/sections/help/action/read.php b/system/sections/help/action/read.php new file mode 100644 index 0000000..a764380 --- /dev/null +++ b/system/sections/help/action/read.php @@ -0,0 +1,49 @@ + 'Администратор', + 'support' => 'Техническая поддержка', + 'user' => 'Клиент' + ); + + if($id) + { + $nmch = 'read_help_'.$id; + + $cache = $mcache->get($nmch); + + // Если кеш создан + if($cache) + { + $cache[$user['id']] = $user['group'].'|'.$start_point; + + $mcache->replace($nmch, $cache, false, 10); + }else + $mcache->set($nmch, array($user['id'] => $user['group'].'|'.$start_point), false, 10); + + if($user['group'] == 'user') + sys::out('У вас нет доступа к данной информации.'); + + // Обработка кеша + $cache = $mcache->get($nmch); + + $read_now = ''; + + foreach($cache as $reader => $data) + { + list($group, $time) = explode('|', $data); + + if($time+9 > $start_point) + $read_now .= '#'.$reader.' ('.$aGroup[$group].'), '; + } + + if(isset($read_now{1})) + $read_now = substr($read_now, 0, -2); + + sys::out($read_now); + } + + sys::out('Необходимо передать номер вопроса.'); +?> \ No newline at end of file diff --git a/system/sections/help/action/remove.php b/system/sections/help/action/remove.php new file mode 100644 index 0000000..5d826dc --- /dev/null +++ b/system/sections/help/action/remove.php @@ -0,0 +1,33 @@ + 'У вас нет доступа к данному действию.')); + + if($id) + { + $msg = isset($url['msg']) ? sys::int($url['msg']) : sys::outjs(array('s' => 'ok')); + + $sql->query('SELECT `img` FROM `help_dialogs` WHERE `id`="'.$msg.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('s' => 'ok')); + + $images = $sql->get(); + + $aImg = sys::b64djs($images['img']); + + foreach($aImg as $img) + { + $sql->query('DELETE FROM `help_upload` WHERE `name`="'.$img.'" LIMIT 1'); + + unlink(ROOT.'upload/'.$img); + } + + $sql->query('DELETE FROM `help_dialogs` WHERE `id`="'.$msg.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + sys::outjs(array('e' => 'Вопрос не найден в базе.')); +?> \ No newline at end of file diff --git a/system/sections/help/action/reply.php b/system/sections/help/action/reply.php new file mode 100644 index 0000000..3993b04 --- /dev/null +++ b/system/sections/help/action/reply.php @@ -0,0 +1,112 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + // Создание сессии + $mcache->set($nmch, 1, false, 10); + + if($id) + { + if(in_array($user['group'], array('admin', 'support'))) + $sql->query('SELECT `user` FROM `help` WHERE `id`="'.$id.'" AND `close`="0" LIMIT 1'); + else + $sql->query('SELECT `user` FROM `help` WHERE `id`="'.$id.'" AND `close`="0" AND `user`="'.$user['id'].'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('с' => 'Вопрос не открыт чтобы вести диалог.'), $nmch); + + $help = $sql->get(); + }else + sys::outjs(array('e' => 'Вопрос не найден в базе.'), $nmch); + + $aData = array(); + + $aData['text'] = isset($_POST['text']) ? $_POST['text'] : sys::outjs(array('e' => 'Сообщение не найдено.'), $nmch); + $aData['images'] = isset($_POST['img']) ? $_POST['img'] : array(); + + $aData['img'] = array(); + + // Проверка сообщения + if(iconv_strlen($aData['text'], 'UTF-8') < 2 || iconv_strlen(str_replace(array(' ', "\t", "\n"),'', $aData['text']), 'UTF-8') > 1000) + sys::outjs(array('e' => 'Длина сообщения не должна быть менее 2 и не превышать 1000 символов.'), $nmch); + + include(LIB.'help.php'); + + // Обработка сообщения + $aData['text'] = help::text($aData['text']); + + // Проверка изображений + if(is_array($aData['images']) AND count($aData['images'])) + { + foreach($aData['images'] as $img) + { + $key = explode('.', $img); + + if(!is_array($key) || sys::valid($key[0], 'md5') || !in_array($key[1], array('png', 'gif', 'jpg', 'bmp'))) + continue; + + $sql->query('SELECT `id` FROM `help_upload` WHERE `name`="'.$img.'" LIMIT 1'); + if(!$sql->num()) + continue; + + $image = $sql->get(); + + $sql->query('UPDATE `help_upload` set `status`="1" WHERE `id`="'.$image['id'].'" LIMIT 1'); + + $aData['img'][] = $img; + } + } + + // Система контроля спама + if($user['group'] == 'user') + { + $i = 0; + $n = 3; + $sql->query('SELECT `user` FROM `help_dialogs` WHERE `help`="'.$id.'" ORDER BY `id` DESC LIMIT 3'); + while($msg = $sql->get()) + { + if(!$i AND !$msg['user']) + sys::outjs(array('i' => 'Пожалуйста, дождитесь ответа технической поддержки.'), $nmch); + + $i+=1; + + if($msg['user'] == $help['user']) + $n-=1; + } + + if(!$n) + { + $sql->query('INSERT INTO `help_dialogs` set `help`="'.$id.'", `user`="0", `text`="Пожалуйста, дождитесь ответа технической поддержки.", `img`="", `time`="'.$start_point.'"'); + + sys::outjs(array('i' => 'Пожалуйста, дождитесь ответа технической поддержки.'), $nmch); + } + } + + $sql->query('SELECT `text` FROM `help_dialogs` WHERE `help`="'.$id.'" ORDER BY `id` DESC LIMIT 1'); + $msg = $sql->get(); + + if(md5($msg['text']) == md5($aData['text'])) + sys::outjs(array('e' => 'Такое сообщение уже отправлено.'), $nmch); + + $sql->query('INSERT INTO `help_dialogs` set ' + .'`help`="'.$id.'",' + .'`user`="'.$user['id'].'",' + .'`text`="'.$aData['text'].'",' + .'`img`="'.sys::b64js($aData['img']).'",' + .'`time`="'.$start_point.'"'); + + if($user['group'] != 'user') + $sql->query('UPDATE `help` set `status`="0" WHERE `id`="'.$id.'" LIMIT 1'); + else{ + $sql->query('UPDATE `help` set `status`="1" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('UPDATE `help` set `notice_admin`="2" WHERE `id`="'.$id.'" LIMIT 1'); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/help/action/write.php b/system/sections/help/action/write.php new file mode 100644 index 0000000..7d1a946 --- /dev/null +++ b/system/sections/help/action/write.php @@ -0,0 +1,57 @@ + 'Администратор', + 'support' => 'Техническая поддержка', + 'user' => 'Клиент' + ); + + $write_st = isset($url['write']) ? true : false; + + if($id) + { + $nmch = 'write_help_'.$id; + + $cache = $mcache->get($nmch); + + // Если кеш создан + if($cache) + { + if($write_st) + $cache[$user['id']] = $user['group'].'|'.$start_point; + else + unset($cache[$user['id']]); + + $mcache->replace($nmch, $cache, false, 10); + }else{ + if($write_st) + $mcache->set($nmch, array($user['id'] => $user['group'].'|'.$start_point), false, 10); + } + + if($user['group'] == 'user') + sys::out('У вас нет доступа к данной информации.'); + + // Обработка кеша + $cache = $mcache->get($nmch); + + $write_now = ''; + + if(is_array($cache)) + foreach($cache as $writer => $data) + { + list($group, $time) = explode('|', $data); + + if($time+9 > $start_point) + $write_now .= '#'.$writer.' ('.$aGroup[$group].'), '; + } + + if(isset($write_now{1})) + $write_now = substr($write_now, 0, -2); + + sys::out($write_now); + } + + sys::out('Необходимо передать номер вопроса.'); +?> \ No newline at end of file diff --git a/system/sections/help/close.php b/system/sections/help/close.php new file mode 100644 index 0000000..5bc1b24 --- /dev/null +++ b/system/sections/help/close.php @@ -0,0 +1,103 @@ +query('SELECT `id`, `user`, `type`, `service`, `date`, `time` FROM `help` WHERE `close`="1"'); + else + $sql->query('SELECT `id`, `type`, `service`, `date`, `time` FROM `help` WHERE `user`="'.$user['id'].'" AND `close`="1"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'help/section/close'); + + if(in_array($user['group'], array('admin', 'support'))) + $helps = $sql->query('SELECT `id`, `user`, `type`, `service`, `date`, `time` FROM `help` WHERE `close`="1" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 20'); + else + $helps = $sql->query('SELECT `id`, `type`, `service`, `date`, `time` FROM `help` WHERE `user`="'.$user['id'].'" AND `close`="1" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 20'); + + // Массив пользователей + $uArr = array(); + + while($help = $sql->get($helps)) + { + // Создатель вопроса + if(in_array($user['group'], array('admin', 'support')) AND !isset($uArr[$help['user']])) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$help['user'].'" LIMIT 1'); + + if(!$sql->num()) + $uArr[$help['user']] = 'Пользователь удален'; + else{ + $us = $sql->get(); + $uArr[$help['user']] = $us['login']; + } + } + + // Краткая информация вопроса + switch($help['type']) + { + case 'server': + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$help['service'].'" LIMIT 1'); + if(!$sql->num()) + $name = 'Игровой сервер: #'.$help['service'].' (не найден)'; + else{ + $ser = $sql->get(); + $name = 'Игровой сервер: #'.$help['service'].' '.$ser['address']; + } + + break; + + case 'hosting': + $name = 'Виртуальных хостинг: #'.$help['service']; + + break; + + default: + $name = 'Вопрос без определенной услуги'; + } + + $html->get('question', 'sections/help/close'); + + $html->set('id', $help['id']); + + if(array_key_exists('user', $help)) + { + $html->set('uid', $help['user']); + $html->set('login', $uArr[$help['user']]); + } + + $html->set('name', $name); + $html->set('status', 'Вопрос решен'); + $html->set('date', sys::today($help['date'])); + $html->set('time', sys::today($help['time'])); + + $html->pack('question'); + } + + $html->get('close', 'sections/help'); + + $html->set('question', isset($html->arr['question']) ? $html->arr['question'] : ''); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + + if(!in_array($user['group'], array('admin', 'support'))) + { + $html->unitall('main', 'user', 1); + $html->unitall('main', 'support'); + }else{ + $html->unitall('main', 'user'); + $html->unitall('main', 'support', 1); + } + + if($user['group'] == 'admin') + $html->unitall('main', 'admin', 1); + else + $html->unitall('main', 'admin'); +?> \ No newline at end of file diff --git a/system/sections/help/create.php b/system/sections/help/create.php new file mode 100644 index 0000000..d99a172 --- /dev/null +++ b/system/sections/help/create.php @@ -0,0 +1,140 @@ +get($nmch)) + sys::outjs(array('e' => $text['mcache']), $nmch); + + // Создание сессии + $mcache->set($nmch, 1, false, 10); + + $aData = array(); + + $aData['service'] = isset($_POST['service']) ? explode('_', $_POST['service']) : exit(); + $aData['title'] = isset($_POST['title']) ? strip_tags(trim($_POST['title'])) : ''; + $aData['text'] = isset($_POST['text']) ? $_POST['text'] : exit(); + $aData['images'] = isset($_POST['img']) ? $_POST['img'] : array(); + + $aData['img'] = array(); + + /* + Проверка входных данных + */ + + // Проверка услуги + if(count($aData['service']) != 2) + { + if($aData['service'][0] != 'none') + sys::outjs(array('e' => 'Необходимо выбрать услугу связанную с вопросом.'), $nmch); + + $aData['type'] = 'none'; + $aData['service'] = 0; + }else{ + if(!in_array($aData['service'][0], array('server', 'hosting'))) + sys::outjs(array('e' => 'Необходимо выбрать услугу связанную с вопросом.'), $nmch); + + $aData['type'] = $aData['service'][0]; + $aData['service'] = sys::int($aData['service'][1]); + + switch($aData['type']) + { + case 'server': + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$aData['service'].'" AND `user`="'.$user['id'].'" LIMIT 1'); + break; + + case 'hosting': + $sql->query('SELECT `id` FROM `hosting` WHERE `id`="'.$aData['service'].'" AND `user`="'.$user['id'].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная услуга не найдена в базе.'), $nmch); + + // Защита от дублирования темы вопроса + $sql->query('SELECT `id` FROM `help` WHERE `user`="'.$user['id'].'" AND `type`="'.$aData['type'].'" AND `service`="'.$aData['service'].'" AND `close`="0" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'По выбранной услуге уже есть открытый диалог.'), $nmch); + } + + // Проверка заголовка, если указан + if(!empty($aData['title'])) + { + if(iconv_strlen($aData['title'], 'UTF-8') < 3 || iconv_strlen($aData['title'], 'UTF-8') > 40) + sys::outjs(array('e' => 'Длина загловка не должна быть менее 3 и не превышать 40 символов.'), $nmch); + } + + // Проверка сообщения + if(iconv_strlen($aData['text'], 'UTF-8') < 10 || iconv_strlen($aData['text'], 'UTF-8') > 1000) + sys::outjs(array('e' => 'Длина сообщения не должна быть менее 10 и не превышать 1000 символов.'), $nmch); + + include(LIB.'help.php'); + + // Обработка сообщения + $aData['text'] = help::text($aData['text']); + + // Проверка изображений + if(is_array($aData['images']) AND count($aData['images'])) + { + foreach($aData['images'] as $img) + { + $key = explode('.', $img); + + if(!is_array($key) || sys::valid($key[0], 'md5') || !in_array($key[1], array('png', 'gif', 'jpg', 'jpeg','bmp'))) + continue; + + $sql->query('SELECT `id` FROM `help_upload` WHERE `name`="'.$img.'" LIMIT 1'); + if(!$sql->num()) + continue; + + $image = $sql->get(); + + $sql->query('UPDATE `help_upload` set `status`="1" WHERE `id`="'.$image['id'].'" LIMIT 1'); + + $aData['img'][] = $img; + } + } + + // Проверка открытых сообщений + $sql->query('SELECT `id` FROM `help` WHERE `user`="'.$user['id'].'" AND `close`="0" LIMIT 3'); + if($sql->num() == 3) + sys::outjs(array('e' => 'У вас уже открыто 3 вопроса, чтобы создать новый необходимо их закрыть.'), $nmch); + + $sql->query('INSERT INTO `help` set ' + .'`user`="'.$user['id'].'",' + .'`type`="'.$aData['type'].'",' + .'`service`="'.$aData['service'].'",' + .'`status`="1",' + .'`date`="'.$start_point.'",' + .'`time`="'.$start_point.'",' + .'`title`="'.htmlspecialchars($aData['title']).'",' + .'`close`="0"'); + + $help = $sql->id(); + + $sql->query('INSERT INTO `help_dialogs` set ' + .'`help`="'.$help.'",' + .'`user`="'.$user['id'].'",' + .'`text`="'.$aData['text'].'",' + .'`img`="'.sys::b64js($aData['img']).'",' + .'`time`="'.$start_point.'"'); + + sys::outjs(array('s' => $help), $nmch); + } + + $services = ''; + + $sql->query('SELECT `id`, `address` FROM `servers` WHERE `user`="'.$user['id'].'" LIMIT 10'); + while($server = $sql->get()) + $services .= ''; + + $html->get('create', 'sections/help'); + + $html->set('id', $user['id']); + $html->set('services', $services); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/help/dialog.php b/system/sections/help/dialog.php new file mode 100644 index 0000000..d92e8a0 --- /dev/null +++ b/system/sections/help/dialog.php @@ -0,0 +1,203 @@ +query('SELECT `type`, `service`, `status`, `date`, `close` FROM `help` WHERE `id`="'.$id.'" LIMIT 1'); + else + $sql->query('SELECT `type`, `service`, `status`, `date`, `close` FROM `help` WHERE `id`="'.$id.'" AND `user`="'.$user['id'].'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'help/section/open'); + + $help = $sql->get(); + + // Смена статуса вопроса на "Прочитан" + if($user['group'] == 'user' AND !$help['status']) + { + $sql->query('UPDATE `help` set `status`="2", `notice`="1" WHERE `id`="'.$id.'" LIMIT 1'); + $help['status'] = 2; + } + + $aGroup = array( + 'admin' => 'Администратор', + 'support' => 'Техническая поддержка', + 'user' => 'Клиент' + ); + + include(LIB.'help.php'); + include(LIB.'users.php'); + + $aSender = array(); + + $dialogs = $sql->query('SELECT `id`, `user`, `text`, `img`, `time` FROM `help_dialogs` WHERE `help`="'.$id.'" ORDER BY `id` DESC LIMIT 50'); + while($dialog = $sql->get($dialogs)) + { + unset($html->arr['attachment']); + + $images = sys::b64djs($dialog['img']); + + if(is_array($images)) + foreach($images as $img) + { + $html->get('attachment', 'sections/help/dialog'); + + $html->set('img', $img); + $html->set('home', $cfg['http']); + + $html->pack('attachment'); + } + + $html->get('msg', 'sections/help/dialog'); + + if($user['id'] != $dialog['user']) + { + if(!$dialog['user']) + $html->set('sender', 'Автоматическое сообщение'); + else{ + if(isset($aSender[$dialog['user']])) + $html->set('sender', $aSender[$dialog['user']]); + else{ + switch($iHelp) + { + case 1: + $sql->query('SELECT `name`, `group`, `support_info` FROM `users` WHERE `id`="'.$dialog['user'].'" LIMIT 1'); + $us = $sql->get(); + + if($us['support_info'] != '') + $aSender[$dialog['user']] = $us['name'].' ('.$us['support_info'].')'; + else + $aSender[$dialog['user']] = $us['name'].' ('.$aGroup[$us['group']].')'; + + break; + case 2: + $sql->query('SELECT `login`, `group`, `support_info` FROM `users` WHERE `id`="'.$dialog['user'].'" LIMIT 1'); + $us = $sql->get(); + + if($us['support_info'] != '') + $aSender[$dialog['user']] = $us['login'].' ('.$us['support_info'].')'; + else + $aSender[$dialog['user']] = $us['login'].' ('.$aGroup[$us['group']].')'; + + break; + case 3: + $sql->query('SELECT `mail`, `group`, `support_info` FROM `users` WHERE `id`="'.$dialog['user'].'" LIMIT 1'); + $us = $sql->get(); + + if($us['support_info'] != '') + $aSender[$dialog['user']] = $us['mail'].' ('.$us['support_info'].')'; + else + $aSender[$dialog['user']] = $us['mail'].' ('.$aGroup[$us['group']].')'; + + break; + default: + $sql->query('SELECT `name`, `patronymic`, `group`, `support_info` FROM `users` WHERE `id`="'.$dialog['user'].'" LIMIT 1'); + $us = $sql->get(); + + if($us['support_info'] != '') + $aSender[$dialog['user']] = $us['name'].' '.$us['patronymic'].' ('.$us['support_info'].')'; + else + $aSender[$dialog['user']] = $us['name'].' '.$us['patronymic'].' ('.$aGroup[$us['group']].')'; + } + + $html->set('sender', $aSender[$dialog['user']]); + } + } + }else + $html->set('sender', 'Я'); + + $html->set('id', $dialog['id']); + $html->set('uid', $dialog['user']); + $html->set('help', $id); + $html->set('home', $cfg['http']); + $html->set('ava', users::ava($dialog['user'])); + $html->set('text', $dialog['text']); + + if($tHelp) + $html->set('time', $dialog['time'] < ($start_point-600) ? sys::today($dialog['time']) : help::ago($dialog['time'])); + else + $html->set('time', sys::today($dialog['time']).' '.help::ago($dialog['time'], true)); + + if(isset($html->arr['attachment'])) + { + $html->set('img', $html->arr['attachment']); + $html->unit('img', 1); + }else + $html->unit('img'); + + if($user['group'] == 'admin') + $html->unit('admin', 1); + else + $html->unit('admin'); + + $html->pack('dialog'); + } + + // Массив статусов вопроса + $status = array( + 0 => 'Есть ответ', + 1 => 'Ожидается ответ', + 2 => 'Прочитан' + ); + + if(isset($url['ajax'])) + sys::outjs(array('dialog' => (isset($html->arr['dialog']) ? $html->arr['dialog'] : ''), 'status' => ($help['close'] ? 'Вопрос решен' : $status[$help['status']]))); + + // Краткая информация вопроса + switch($help['type']) + { + case 'server': + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$help['service'].'" LIMIT 1'); + if(!$sql->num()) + $service = 'Игровой сервер: #'.$help['service'].' (не найден)'; + else{ + $ser = $sql->get(); + $service = 'Игровой сервер: #'.$help['service'].' '.$ser['address'].''; + } + + break; + + case 'hosting': + $service = 'Виртуальных хостинг: #'.$help['service'].''; + + break; + + default: + $service = 'Вопрос без определенной услуги'; + } + + $html->get('dialog', 'sections/help'); + + $html->set('id', $id); + $html->set('date', sys::today($help['date'])); + $html->set('status', $help['close'] ? 'Вопрос решен' : $status[$help['status']]); + $html->set('service', $service); + $html->set('dialog', isset($html->arr['dialog']) ? $html->arr['dialog'] : ''); + + if($user['group'] == 'user') + { + $html->unit('!user'); + $html->unit('user', 1); + }else{ + $html->unit('!user', 1); + $html->unit('user'); + } + + if($help['close']) + { + $html->unit('open'); + $html->unit('close', 1); + }else{ + $html->unit('open', 1); + $html->unit('close'); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/help/notice.php b/system/sections/help/notice.php new file mode 100644 index 0000000..f1ff116 --- /dev/null +++ b/system/sections/help/notice.php @@ -0,0 +1,49 @@ +query('SELECT `id` FROM `help` WHERE `user`="'.$user['id'].'" AND `status`="0" AND `close`="0" LIMIT 1'); + else + $sql->query('SELECT `id` FROM `help` WHERE `status`="1" AND `close`="0" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('empty' => '')); + + if($user['group'] != 'user') + { + $sql->query('SELECT `time` FROM `help` WHERE `status`="1" AND `close`="0" ORDER BY `time` DESC LIMIT 1'); + if($sql->num()) + { + $help = $sql->get(); + + sys::outjs(array('reply' => $help['time'])); + } + + sys::outjs(array('empty' => '')); + } + + $help = $sql->get(); + + $sql->query('SELECT `text`, `time` FROM `help_dialogs` WHERE `help`="'.$help['id'].'" AND `user`!="'.$user['id'].'" AND `time`>"'.($start_point-15).'" ORDER BY `id` DESC LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('reply' => '')); + + $msg = $sql->get(); + + if(strip_tags($msg['text'], '
    ,

    ') != $msg['text']) + sys::outjs(array('reply' => '')); + + include(LIB.'help.php'); + + $html->get('notice', 'sections/help'); + + $html->set('id', $help['id']); + $html->set('home', $cfg['http']); + $html->set('text', $msg['text']); + $html->set('ago', help::ago($msg['time'])); + + $html->pack('notice'); + + sys::outjs(array('notice' => $html->arr['notice'])); +?> \ No newline at end of file diff --git a/system/sections/help/open.php b/system/sections/help/open.php new file mode 100644 index 0000000..f682d9a --- /dev/null +++ b/system/sections/help/open.php @@ -0,0 +1,113 @@ + 'Есть ответ', + 1 => 'Ожидается ответ', + 2 => 'Прочитан' + ); + + if(in_array($user['group'], array('admin', 'support'))) + $sql->query('SELECT `id` FROM `help` WHERE `close`="0"'); + else + $sql->query('SELECT `id` FROM `help` WHERE `user`="'.$user['id'].'" AND `close`="0"'); + + $aPage = sys::page($page, $sql->num(), 20); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'help/section/open'); + + if(in_array($user['group'], array('admin', 'support'))) + $helps = $sql->query('SELECT `id`, `user`, `type`, `service`, `status`, `date`, `time`, `title` FROM `help` WHERE `close`="0" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 20'); + else + $helps = $sql->query('SELECT `id`, `type`, `service`, `status`, `date`, `time`, `title` FROM `help` WHERE `user`="'.$user['id'].'" AND `close`="0" ORDER BY `id` DESC LIMIT '.$aPage['num'].', 20'); + + // Массив пользователей + $uArr = array(); + + while($help = $sql->get($helps)) + { + // Создатель вопроса + if(in_array($user['group'], array('admin', 'support')) AND !isset($uArr[$help['user']])) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$help['user'].'" LIMIT 1'); + + if(!$sql->num()) + $uArr[$help['user']] = 'Пользователь удален'; + else{ + $us = $sql->get(); + $uArr[$help['user']] = $us['login']; + } + } + + // Краткая информация вопроса + switch($help['type']) + { + case 'server': + $sql->query('SELECT `address` FROM `servers` WHERE `id`="'.$help['service'].'" LIMIT 1'); + if(!$sql->num()) + $name = 'Игровой сервер: #'.$help['service'].' (не найден)'; + else{ + $ser = $sql->get(); + $name = 'Игровой сервер: #'.$help['service'].' '.$ser['address']; + } + + break; + + case 'hosting': + $name = 'Виртуальных хостинг: #'.$help['service']; + + break; + + default: + $name = 'Вопрос без определенной услуги'; + } + + if(!empty($help['title'])) + $name = $help['title']; + + $html->get('question', 'sections/help/open'); + + $html->set('id', $help['id']); + + if(array_key_exists('user', $help)) + { + $html->set('uid', $help['user']); + $html->set('login', $uArr[$help['user']]); + } + + $html->set('name', $name); + $html->set('status', $status[$help['status']]); + $html->set('date', sys::today($help['date'])); + $html->set('time', sys::today($help['time'])); + + $html->pack('question'); + } + + $html->get('open', 'sections/help'); + + $html->set('question', isset($html->arr['question']) ? $html->arr['question'] : ''); + + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + + $html->pack('main'); + + if(!in_array($user['group'], array('admin', 'support'))) + { + $html->unitall('main', 'user', 1); + $html->unitall('main', 'support'); + }else{ + $html->unitall('main', 'user'); + $html->unitall('main', 'support', 1); + } + + if($user['group'] == 'admin') + $html->unitall('main', 'admin', 1); + else + $html->unitall('main', 'admin'); +?> \ No newline at end of file diff --git a/system/sections/help/upload.php b/system/sections/help/upload.php new file mode 100644 index 0000000..8c43514 --- /dev/null +++ b/system/sections/help/upload.php @@ -0,0 +1,31 @@ +query('INSERT INTO `help_upload` set `user`="'.$user['id'].'", `name`="'.$rdmName.'", `time`="'.$start_point.'", `status`="0"'); + + exit($rdmName.':ok'); + } + + exit('Ошибка загрузки: убедитесь, что изображение не повреждено и имеет правильный формат.'); +?> \ No newline at end of file diff --git a/system/sections/megp/news/index.php b/system/sections/megp/news/index.php new file mode 100644 index 0000000..9059079 --- /dev/null +++ b/system/sections/megp/news/index.php @@ -0,0 +1,28 @@ +query('SELECT `id` FROM `news`'); + + $aPage = sys::page($page, $sql->num(), $cfg['news_page']); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'news'); + + $sql->query('SELECT `id`, `name`, `text`, `views`, `tags`, `date` FROM `news` ORDER BY `id` DESC LIMIT '.$aPage['num'].', '.$cfg['news_page']); + while($news = $sql->get()) + { + $html->get('list', 'sections/news'); + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['text'])); + $html->set('views', $news['views']); + $html->set('tags', sys::tags($news['tags'])); + $html->set('date', sys::today($news['date'])); + $html->pack('news'); + } + + $html->get('all', 'sections/news'); + $html->set('list', isset($html->arr['news']) ? $html->arr['news'] : ''); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/news/news.php b/system/sections/megp/news/news.php new file mode 100644 index 0000000..e5b8378 --- /dev/null +++ b/system/sections/megp/news/news.php @@ -0,0 +1,32 @@ +query('SELECT `id`, `name`, `full_text`, `views`, `tags`, `date` FROM `news` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + include(ENG.'404.php'); + + $news = $sql->get(); + + $sql->query('UPDATE `news` set `views`="'.($news['views']+1).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $text = htmlspecialchars_decode($news['full_text']); + + $title = $news['name']; + $description = $text; + $keywords = $news['tags']; + + $html->nav($news['name']); + + $html->get('news', 'sections/news'); + + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', $text); + $html->set('views', $news['views']); + $html->set('tags', sys::tags($news['tags'])); + $html->set('date', sys::today($news['date'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/action.php b/system/sections/megp/servers/action.php new file mode 100644 index 0000000..85e1c4b --- /dev/null +++ b/system/sections/megp/servers/action.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/system/sections/megp/servers/boost.php b/system/sections/megp/servers/boost.php new file mode 100644 index 0000000..3f9d4aa --- /dev/null +++ b/system/sections/megp/servers/boost.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'boost'); + + include(sys::route($server, 'boost', $go)); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/console.php b/system/sections/megp/servers/console.php new file mode 100644 index 0000000..f49ac21 --- /dev/null +++ b/system/sections/megp/servers/console.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'console'); + + include(sys::route($server, 'console', $go)); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/console.php b/system/sections/megp/servers/crmp/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/crmp/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/index.php b/system/sections/megp/servers/crmp/index.php new file mode 100644 index 0000000..2025c89 --- /dev/null +++ b/system/sections/megp/servers/crmp/index.php @@ -0,0 +1,35 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + $tarif['packs'] = sys::b64djs($tarif['packs']); + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + $html->set('btn', $btn); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/settings.php b/system/sections/megp/servers/crmp/settings.php new file mode 100644 index 0000000..7d7260d --- /dev/null +++ b/system/sections/megp/servers/crmp/settings.php @@ -0,0 +1,46 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/settings/start.php b/system/sections/megp/servers/crmp/settings/start.php new file mode 100644 index 0000000..c64a63b --- /dev/null +++ b/system/sections/megp/servers/crmp/settings/start.php @@ -0,0 +1,44 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/tarif.php b/system/sections/megp/servers/crmp/tarif.php new file mode 100644 index 0000000..7d95fa2 --- /dev/null +++ b/system/sections/megp/servers/crmp/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/tarif/extend.php b/system/sections/megp/servers/crmp/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/megp/servers/crmp/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/crmp/tarif/slots.php b/system/sections/megp/servers/crmp/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/megp/servers/crmp/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/boost.php b/system/sections/megp/servers/cs/boost.php new file mode 100644 index 0000000..a05aec2 --- /dev/null +++ b/system/sections/megp/servers/cs/boost.php @@ -0,0 +1,68 @@ + 'Необходимо указать сервис.')); + $aData['service'] = isset($url['service']) ? sys::int($url['service']) : sys::outjs(array('e' => 'Необходимо указать номер услуги.')); + + include(DATA.'boost.php'); + + // Проверка сервиса + if(!array_key_exists($aData['site'], $aBoost[$server['game']])) + sys::outjs(array('e' => 'Указанный сервис по раскрутке не найден.')); + + // Проверка номера услуги + if(!in_array($aData['service'], $aBoost[$server['game']][$aData['site']]['services'])) + sys::outjs(array('e' => 'Неправильно указан номер услуги.')); + + // Определение суммы + $sum = $aBoost[$server['game']][$aData['site']]['price'][$aData['service']]; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $name_mcache); + + include(LIB.'games/boost.php'); + + $boost = new boost($aBoost[$server['game']][$aData['site']]['key'], $aBoost[$server['game']][$aData['site']]['api']); + + $buy = $boost->$aBoost[$server['game']][$aData['site']]['type'](array('period' => $aData['service'], 'address' => $server['address'])); + + if(is_array($buy)) + sys::outjs(array('e' => $buy['error'])); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + include(LIB.'games/games.php'); + + // Реф. система + games::part($user['id'], $sum); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_boost'), + array('circles' => $aBoost[$server['game']][$aData['site']]['circles'][$aData['service']], + 'money' => $sum, 'site' => $aBoost[$server['game']][$aData['site']]['site'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="boost", `money`="'.$sum.'"'); + + $sql->query('INSERT INTO `boost` set `user`="'.$user['id'].'", `server`="'.$id.'", `site`="'.$aData['site'].'", `circles`="'.$aBoost[$server['game']][$aData['site']]['circles'][$aData['service']].'", `money`="'.$sum.'", `date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + if($mcache->get('server_boost_'.$id) != '') + $html->arr['main'] = $mcache->get('server_boost_'.$id); + else{ + $html->get('boost', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('address', $server['address']); + $html->set('cur', $cfg['currency']); + + $html->pack('main'); + + $mcache->set('server_boost_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/console.php b/system/sections/megp/servers/cs/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/cs/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/index.php b/system/sections/megp/servers/cs/index.php new file mode 100644 index 0000000..bd883c4 --- /dev/null +++ b/system/sections/megp/servers/cs/index.php @@ -0,0 +1,41 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `fps`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['fps'].' FPS'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/settings.php b/system/sections/megp/servers/cs/settings.php new file mode 100644 index 0000000..113f956 --- /dev/null +++ b/system/sections/megp/servers/cs/settings.php @@ -0,0 +1,51 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack', 'antiddos'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/settings/start.php b/system/sections/megp/servers/cs/settings/start.php new file mode 100644 index 0000000..93c5828 --- /dev/null +++ b/system/sections/megp/servers/cs/settings/start.php @@ -0,0 +1,159 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fps`, `fastdl`, `autorestart`, `pingboost` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `fps`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $map, true, $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['fps']))) + $sql->query('UPDATE `servers` set `fps`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'pingboost': + if($cfg['change_pingboost'] AND in_array($value, array(1, 2, 3))) + $sql->query('UPDATE `servers` set `pingboost`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/cstrike/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/cstrike/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + + if(!tarif::price($tarif['price'])) + { + $aFps = explode(':', $tarif['fps']); + + unset($aFps[array_search($server['fps'], $aFps)]); + + if(count($aFps)) + foreach($aFps as $value) + $fps .= ''; + } + + if($cfg['change_pingboost']) + $pingboost = str_replace($server['pingboost'].'"', $server['pingboost'].'" selected="select"', ''); + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if($cfg['change_pingboost']) + { + $html->unit('pingboost', true); + $html->set('pingboost', $pingboost); + }else + $html->unit('pingboost'); + + if(!tarif::price($tarif['price'])) + { + $html->unit('fps', true); + $html->set('fps', $fps); + }else + $html->unit('fps'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/tarif.php b/system/sections/megp/servers/cs/tarif.php new file mode 100644 index 0000000..49e6b9c --- /dev/null +++ b/system/sections/megp/servers/cs/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/tarif/extend.php b/system/sections/megp/servers/cs/tarif/extend.php new file mode 100644 index 0000000..0e66ff6 --- /dev/null +++ b/system/sections/megp/servers/cs/tarif/extend.php @@ -0,0 +1,52 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['fps'] = $server['fps']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($server['fps'], $aFPS)]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/tarif/plan.php b/system/sections/megp/servers/cs/tarif/plan.php new file mode 100644 index 0000000..09170db --- /dev/null +++ b/system/sections/megp/servers/cs/tarif/plan.php @@ -0,0 +1,64 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + // Проверка плана + if(array_search($plan, $aFPS) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + if($plan == $server['fps']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aFPS)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($server['fps'], $aFPS)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + $sql->query('UPDATE `servers` set `time`="'.$time.'", `fps`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cs/tarif/slots.php b/system/sections/megp/servers/cs/tarif/slots.php new file mode 100644 index 0000000..b32de8a --- /dev/null +++ b/system/sections/megp/servers/cs/tarif/slots.php @@ -0,0 +1,34 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день 1 слота + $price = $aPrice[array_search($server['fps'], $aFPS)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($server['fps'], $aFPS)]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/console.php b/system/sections/megp/servers/csgo/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/csgo/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/index.php b/system/sections/megp/servers/csgo/index.php new file mode 100644 index 0000000..bd883c4 --- /dev/null +++ b/system/sections/megp/servers/csgo/index.php @@ -0,0 +1,41 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `fps`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['fps'].' FPS'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/settings.php b/system/sections/megp/servers/csgo/settings.php new file mode 100644 index 0000000..113f956 --- /dev/null +++ b/system/sections/megp/servers/csgo/settings.php @@ -0,0 +1,51 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack', 'antiddos'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/settings/start.php b/system/sections/megp/servers/csgo/settings/start.php new file mode 100644 index 0000000..1238750 --- /dev/null +++ b/system/sections/megp/servers/csgo/settings/start.php @@ -0,0 +1,143 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/csgo/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/csgo/maps', $map, true, $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['tickrate']))) + $sql->query('UPDATE `servers` set `tickrate`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/csgo /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + if(!tarif::price($tarif['price'])) + { + $aTick = explode(':', $tarif['tickrate']); + + unset($aTick[array_search($server['tickrate'], $aTick)]); + + if(count($aTick)) + foreach($aTick as $value) + $tickrate .= ''; + } + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if(!tarif::price($tarif['price'])) + { + $html->unit('tickrate', true); + $html->set('tickrate', $tickrate); + }else + $html->unit('tickrate'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/tarif.php b/system/sections/megp/servers/csgo/tarif.php new file mode 100644 index 0000000..49e6b9c --- /dev/null +++ b/system/sections/megp/servers/csgo/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/tarif/extend.php b/system/sections/megp/servers/csgo/tarif/extend.php new file mode 100644 index 0000000..9d060bc --- /dev/null +++ b/system/sections/megp/servers/csgo/tarif/extend.php @@ -0,0 +1,51 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['tickrate'] = $server['tickrate']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($server['tickrate'], explode(':', $tarif['tickrate']))]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/tarif/plan.php b/system/sections/megp/servers/csgo/tarif/plan.php new file mode 100644 index 0000000..33988c4 --- /dev/null +++ b/system/sections/megp/servers/csgo/tarif/plan.php @@ -0,0 +1,64 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + // Проверка плана + if(array_search($plan, $aTICK) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + if($plan == $server['tickrate']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aTICK)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + $sql->query('UPDATE `servers` set `time`="'.$time.'", `tickrate`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/csgo/tarif/slots.php b/system/sections/megp/servers/csgo/tarif/slots.php new file mode 100644 index 0000000..e457286 --- /dev/null +++ b/system/sections/megp/servers/csgo/tarif/slots.php @@ -0,0 +1,34 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($server['tickrate'], $aTICK)]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/css/.htaccess b/system/sections/megp/servers/css/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/system/sections/megp/servers/cssold/console.php b/system/sections/megp/servers/cssold/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/cssold/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/index.php b/system/sections/megp/servers/cssold/index.php new file mode 100644 index 0000000..ff85fde --- /dev/null +++ b/system/sections/megp/servers/cssold/index.php @@ -0,0 +1,41 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `fps`, `tickrate`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['fps'].' FPS / '.$server['tickrate'].' TickRate'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/settings.php b/system/sections/megp/servers/cssold/settings.php new file mode 100644 index 0000000..113f956 --- /dev/null +++ b/system/sections/megp/servers/cssold/settings.php @@ -0,0 +1,51 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack', 'antiddos'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/settings/start.php b/system/sections/megp/servers/cssold/settings/start.php new file mode 100644 index 0000000..a681458 --- /dev/null +++ b/system/sections/megp/servers/cssold/settings/start.php @@ -0,0 +1,163 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `fps`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $map, true, $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['fps']))) + $sql->query('UPDATE `servers` set `fps`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['tickrate']))) + $sql->query('UPDATE `servers` set `tickrate`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + $tickrate = ''; + + if(!tarif::price($tarif['price'])) + { + $aFps = explode(':', $tarif['fps']); + + unset($aFps[array_search($server['fps'], $aFps)]); + + if(count($aFps)) + foreach($aFps as $value) + $fps .= ''; + + $aTick = explode(':', $tarif['tickrate']); + + unset($aTick[array_search($server['tickrate'], $aTick)]); + + if(count($aTick)) + foreach($aTick as $value) + $tickrate .= ''; + } + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if(!tarif::price($tarif['price'])) + { + $html->unit('fps', true); + $html->set('fps', $fps); + + $html->unit('tickrate', true); + $html->set('tickrate', $tickrate); + }else{ + $html->unit('fps'); + $html->unit('tickrate'); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/tarif.php b/system/sections/megp/servers/cssold/tarif.php new file mode 100644 index 0000000..a24eff3 --- /dev/null +++ b/system/sections/megp/servers/cssold/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `tickrate`, `ram`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/tarif/extend.php b/system/sections/megp/servers/cssold/tarif/extend.php new file mode 100644 index 0000000..5125e5f --- /dev/null +++ b/system/sections/megp/servers/cssold/tarif/extend.php @@ -0,0 +1,52 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['fps'] = $server['fps']; + $aData['tickrate'] = $server['tickrate']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = sys::b64djs($tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[$server['tickrate'].'_'.$server['fps']]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/tarif/plan.php b/system/sections/megp/servers/cssold/tarif/plan.php new file mode 100644 index 0000000..2ed7cd4 --- /dev/null +++ b/system/sections/megp/servers/cssold/tarif/plan.php @@ -0,0 +1,65 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = sys::b64djs($tarif['price']); + + // Проверка плана + if(!array_key_exists($plan, $aPrice)) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + list($tickrate, $fps) = explode('_', $plan); + + if($tickrate == $server['tickrate'] AND $fps == $server['fps']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день (по новому тарифному плану) + $price = $aPrice[$plan]/30*$server['slots']; + + // Цена аренды за остаток дней + $price_old = $aPrice[$server['tickrate'].'_'.$server['fps']]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + $sql->query('UPDATE `servers` set `time`="'.$time.'", `fps`="'.$fps.'", `tickrate`="'.$tickrate.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/cssold/tarif/slots.php b/system/sections/megp/servers/cssold/tarif/slots.php new file mode 100644 index 0000000..fae705c --- /dev/null +++ b/system/sections/megp/servers/cssold/tarif/slots.php @@ -0,0 +1,33 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = sys::b64djs($tarif['price']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[$server['tickrate'].'_'.$server['fps']]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[$server['tickrate'].'_'.$server['fps']]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/games/tarif.php b/system/sections/megp/servers/games/tarif.php new file mode 100644 index 0000000..9ecbcb9 --- /dev/null +++ b/system/sections/megp/servers/games/tarif.php @@ -0,0 +1,50 @@ +get('tarif', 'sections/servers/games'); + + $html->set('id', $id); + + $html->pack('main'); + + // Шаблон продления + if($cfg['settlement_period']) + tarif::extend_sp($server, $tarif, $id); + else{ + $options = games::parse_time(explode(':', $tarif['timext']), $tarif['discount'], $server['tarif'], 'extend'); + + tarif::extend($options, $server, $tarif['name'], $id); + } + + // Если не тестовый период + if(!$server['test']) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Шаблон смены тарифа (если аренда не менее 1 дня и цены планов различны) + if($server['time'] > $start_point+86400 AND tarif::price($tarif['price'])) + tarif::plan($server, $tarif['name'], $id); + + // Шаблон изменения кол-ва слот + if($tarif['slots_min'] != $tarif['slots_max']) + tarif::slots($server, array('min' => $tarif['slots_min'], 'max' => $tarif['slots_max']), $id); + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/games/tarif/extend.php b/system/sections/megp/servers/games/tarif/extend.php new file mode 100644 index 0000000..e63104f --- /dev/null +++ b/system/sections/megp/servers/games/tarif/extend.php @@ -0,0 +1,71 @@ + с учетом промо-кода) + if(isset($url['promo']) || $aData['promo'] != '') + $promo = games::define_promo( + $aData['promo'], + $aData, + $tarif['discount'], + $sum, + 'extend' + ); + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $aData['time'] += $promo['days']*86400; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Выполнение продления + if($go) + { + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $status = $server['status'] == 'overdue' ? '`status`="off",' : ''; + + // Время аренды + $time = $server['time'] < $start_point ? $start_point+$aData['time']*86400 : $server['time']+$aData['time']*86400; + + // Обновление информации + $sql->query('UPDATE `servers` set '.$status.' `time`="'.$time.'", `test`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Продление адреса на 30 дней + if($add_sum) + $sql->query('UPDATE `address_buy` set `time`=`time`+"2592000" WHERE `server`="'.$id.'" LIMIT 1'); + + // Запись логов + if(!is_array($promo)) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_server'), + array('days' => $days, + 'money' => $sum, + 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$sum.'"'); + else{ + $sql->query('INSERT INTO `promo_use` set `promo`="'.$promo['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_server_promo'), + array('days' => $days, + 'money' => $sum, + 'promo' => $promo['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$sum.'"'); + } + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп цены + sys::outjs(array('s' => $sum)); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/games/tarif/slots.php b/system/sections/megp/servers/games/tarif/slots.php new file mode 100644 index 0000000..dbfe315 --- /dev/null +++ b/system/sections/megp/servers/games/tarif/slots.php @@ -0,0 +1,124 @@ + '')); + + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `slots`="'.$slots.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // При возможности уменьшить + if($cfg['change_slots'][$server['game']]['down'] || $overdue) + { + // Проверка кол-ва слот + if($slots < $tarif['slots_min'] || $slots > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданые неверные данные.'), $nmch); + + if($server['slots'] == $slots) + { + if($go) + sys::outjs(array('s' => 'ok'), $nmch); + + sys::outjs(array('s' => 'Сервер будет арендован до: '.date('d.m.Y - H:i', $server['time']).' ('.sys::date('min', $server['time']).')'), $nmch); + } + }else{ + // Установлено макс. значение + if($server['slots'] == $tarif['slots_max'] AND !$overdue) + sys::outjs(array('e' => 'На игровом сервере установлено максимальное значение.'), $nmch); + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $slots += $server['slots']; + } + + $date = date('H.i.s.d.m.Y', round($start_point+$price_old/($price*$slots)*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + // При уменьшении кол-ва слот не добавлять дни + if($slots < $server['slots'] AND ($cfg['change_slots'][$server['game']]['days'] AND $cfg['change_slots'][$server['game']]['down'] AND !$cfg['change_slots'][$server['game']]['add'])) + $time = $server['time']; + + // Выполнение операции + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `slots`="'.$slots.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change')) AND $slots < $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Сервер будет арендован до: '.$arenda.' '.date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')')); + } + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданые неверные данные'), $nmch); + + // Выполнение операции + if($go) + { + $slots_new = $server['slots']+$slots; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $start = $server['slots_start'] == $server['slots'] ? ', `slots_start`="'.$slots_new.'"' : ''; + + // Обновление информации + $sql->query('UPDATE `servers` set `slots`="'.$slots_new.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change')) AND $slots_new != $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_slots'), + array('slots' => $slots, 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Цена за дополнительные слоты: '.$sum.' '.$cfg['currency'])); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/index.php b/system/sections/megp/servers/index.php new file mode 100644 index 0000000..0b71c47 --- /dev/null +++ b/system/sections/megp/servers/index.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'index'); + + include(SEC.'megp/servers/'.$server['game'].'/index.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/list.php b/system/sections/megp/servers/list.php new file mode 100644 index 0000000..58c7acf --- /dev/null +++ b/system/sections/megp/servers/list.php @@ -0,0 +1,90 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + $n = $sql->num($q_Servers); + + $aUnits = array(); + $aTarifs = array(); + + // Проверка массивов в кеше + if(is_array($mcache->get('aut_'.$user['id'])) AND $mcache->get('nser_'.$user['id']) == $n) + { + $aUT = $mcache->get('aut_'.$user['id']); + $aUnits = $aUT[0]; + $aTarifs = $aUT[1]; + }else{ + while($server = $sql->get($q_Servers)) + { + if(!array_key_exists($server['unit'], $aUnits)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $aUnits[$server['unit']] = array( + 'name' => $unit['name'] + ); + } + + if(!array_key_exists($server['tarif'], $aTarifs)) + { + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aTarifs[$server['tarif']] = array( + 'name' => $tarif['name'], + 'packs' => sys::b64djs($tarif['packs']) + ); + } + } + + // Запись массивов в кеш + $mcache->set('aut_'.$user['id'], array($aUnits, $aTarifs), false, 60); + + // Запись кол-во серверов в кеш + $mcache->set('nser_'.$user['id'], $n, false, 60); + } + + include(LIB.'games/games.php'); + + $sql->query('SELECT ' + .'`id`,' + .'`unit`,' + .'`tarif`,' + .'`address`,' + .'`game`,' + .'`slots_start`,' + .'`online`,' + .'`status`,' + .'`name`,' + .'`map`,' + .'`time`,' + .'`overdue`' + .' FROM `servers` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + $wait_servers = ''; + $updates_servers = ''; + + while($server = $sql->get()) + { + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('list', 'sections/servers'); + + $html->set('id', $server['id']); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + + $html->pack('list'); + + $wait_servers .= $server['id'].':false,'; + $updates_servers .= 'setTimeout(function() {update_info(\''.$server['id'].'\', true)}, 5000); setTimeout(function() {update_status(\''.$server['id'].'\', true)}, 10000);'; + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/console.php b/system/sections/megp/servers/mc/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/mc/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/index.php b/system/sections/megp/servers/mc/index.php new file mode 100644 index 0000000..8537694 --- /dev/null +++ b/system/sections/megp/servers/mc/index.php @@ -0,0 +1,40 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue`, `ram` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['ram'].' RAM'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/settings.php b/system/sections/megp/servers/mc/settings.php new file mode 100644 index 0000000..7d7260d --- /dev/null +++ b/system/sections/megp/servers/mc/settings.php @@ -0,0 +1,46 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/settings/start.php b/system/sections/megp/servers/mc/settings/start.php new file mode 100644 index 0000000..c64a63b --- /dev/null +++ b/system/sections/megp/servers/mc/settings/start.php @@ -0,0 +1,44 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/tarif.php b/system/sections/megp/servers/mc/tarif.php new file mode 100644 index 0000000..7d95fa2 --- /dev/null +++ b/system/sections/megp/servers/mc/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/tarif/extend.php b/system/sections/megp/servers/mc/tarif/extend.php new file mode 100644 index 0000000..1c37b4a --- /dev/null +++ b/system/sections/megp/servers/mc/tarif/extend.php @@ -0,0 +1,53 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $ram = $server['slots_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['ram'] = $ram; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($ram, explode(':', $tarif['ram']))]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/tarif/plan.php b/system/sections/megp/servers/mc/tarif/plan.php new file mode 100644 index 0000000..6f4e3e2 --- /dev/null +++ b/system/sections/megp/servers/mc/tarif/plan.php @@ -0,0 +1,68 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + // Проверка плана + if(array_search($plan, $aRAM) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $ram = $server['slots_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + if($plan == $ram) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aRAM)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($ram, $aRAM)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + $plan = $server['slots_fix'] ? $plan : $plan*$server['slots']; + + // Выполнение смена тарифного плана + if($go) + { + $sql->query('UPDATE `servers` set `time`="'.$time.'", `ram`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mc/tarif/slots.php b/system/sections/megp/servers/mc/tarif/slots.php new file mode 100644 index 0000000..5126e84 --- /dev/null +++ b/system/sections/megp/servers/mc/tarif/slots.php @@ -0,0 +1,158 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[array_search($ram, $aRAM)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($ram, $aRAM)]/30)*$slots, 2); + + // Изменение кол-ва слот за счет пересчета дней аренды или закончился срок аренды (иначе аренда дополнительных слот) + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']*$slots; + + // Если просрочен + if($overdue) + { + sys::outjs(array('i' => '')); + + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `slots`="'.$slots.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // При возможности уменьшить + if($cfg['change_slots'][$server['game']]['down'] || $overdue) + { + // Проверка кол-ва слот + if($slots < $tarif['slots_min'] || $slots > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданые неверные данные.'), $nmch); + + if($server['slots'] == $slots) + { + if($go) + sys::outjs(array('s' => 'ok'), $nmch); + + sys::outjs(array('s' => 'Сервер будет арендован до: '.date('d.m.Y - H:i', $server['time']).' ('.sys::date('min', $server['time']).')'), $nmch); + } + }else{ + // Установлено макс. значение + if($server['slots'] == $tarif['slots_max'] AND !$overdue) + sys::outjs(array('e' => 'На игровом сервере установлено максимальное значение.'), $nmch); + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $slots += $server['slots']; + } + + $date = date('H.i.s.d.m.Y', round($start_point+$price_old/($price*$slots)*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + // При уменьшении кол-ва слот не добавлять дни + if($slots < $server['slots'] AND ($cfg['change_slots'][$server['game']]['days'] AND $cfg['change_slots'][$server['game']]['down'] AND !$cfg['change_slots'][$server['game']]['add'])) + $time = $server['time']; + + // Выполнение операции + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `slots`="'.$slots.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change')) AND $slots < $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Сервер будет арендован до: '.$arenda.' '.date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')')); + } + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданые неверные данные'), $nmch); + + // Выполнение операции + if($go) + { + $slots_new = $server['slots']+$slots; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $start = $server['slots_start'] == $server['slots'] ? ', `slots_start`="'.$slots_new.'"' : ''; + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']*$slots_new; + + // Обновление информации + $sql->query('UPDATE `servers` set `slots`="'.$slots_new.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart')) AND $slots_new != $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_slots'), + array('slots' => $slots, 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Цена за дополнительные слоты: '.$sum.' '.$cfg['currency'])); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/console.php b/system/sections/megp/servers/mta/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/mta/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/index.php b/system/sections/megp/servers/mta/index.php new file mode 100644 index 0000000..2025c89 --- /dev/null +++ b/system/sections/megp/servers/mta/index.php @@ -0,0 +1,35 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + $tarif['packs'] = sys::b64djs($tarif['packs']); + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + $html->set('btn', $btn); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/settings.php b/system/sections/megp/servers/mta/settings.php new file mode 100644 index 0000000..7d7260d --- /dev/null +++ b/system/sections/megp/servers/mta/settings.php @@ -0,0 +1,46 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/settings/start.php b/system/sections/megp/servers/mta/settings/start.php new file mode 100644 index 0000000..7721155 --- /dev/null +++ b/system/sections/megp/servers/mta/settings/start.php @@ -0,0 +1,50 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/tarif.php b/system/sections/megp/servers/mta/tarif.php new file mode 100644 index 0000000..7d95fa2 --- /dev/null +++ b/system/sections/megp/servers/mta/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/tarif/extend.php b/system/sections/megp/servers/mta/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/megp/servers/mta/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/mta/tarif/slots.php b/system/sections/megp/servers/mta/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/megp/servers/mta/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/noaccess.php b/system/sections/megp/servers/noaccess.php new file mode 100644 index 0000000..eb3d106 --- /dev/null +++ b/system/sections/megp/servers/noaccess.php @@ -0,0 +1,22 @@ +get('overdue'); + else{ + $status = array( + 'install' => 'установки', + 'reinstall' => 'переустановки', + 'update' => 'обновления', + 'recovery' => 'восстановления', + 'blocked' => 'блокировки' + ); + + $html->get('noaccess'); + + $html->set('status', $status[$server['status']]); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/owners_list.php b/system/sections/megp/servers/owners_list.php new file mode 100644 index 0000000..b08c2b4 --- /dev/null +++ b/system/sections/megp/servers/owners_list.php @@ -0,0 +1,102 @@ +query('SELECT `server` FROM `owners` WHERE `user`="'.$user['id'].'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC'); + + $n = $sql->num($owners); + + $aUnits = array(); + $aTarifs = array(); + + // Проверка массивов в кеше + if(is_array($mcache->get('owners_aut_'.$user['id'])) AND $mcache->get('owners_nser_'.$user['id']) == $n) + { + $aUT = $mcache->get('owners_aut_'.$user['id']); + $aUnits = $aUT[0]; + $aTarifs = $aUT[1]; + }else{ + while($owner = $sql->get($owners)) + { + $server_sql = $sql->query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$owner['server'].'"'); + + while($server = $sql->get($server_sql)) + { + if(!array_key_exists($server['unit'], $aUnits)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $aUnits[$server['unit']] = array( + 'name' => $unit['name'] + ); + } + + if(!array_key_exists($server['tarif'], $aTarifs)) + { + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aTarifs[$server['tarif']] = array( + 'name' => $tarif['name'], + 'packs' => sys::b64djs($tarif['packs']) + ); + } + } + } + + // Запись массивов в кеш + $mcache->set('owners_aut_'.$user['id'], array($aUnits, $aTarifs), false, 60); + + // Запись кол-во серверов в кеш + $mcache->set('owners_nser_'.$user['id'], $n, false, 60); + } + + $owners = $sql->query('SELECT `id`, `server`, `time` FROM `owners` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + while($owner = $sql->get($owners)) + { + if($owner['time'] < $start_point) + { + $sql->query('DELETE FROM `owners` WHERE `id`="'.$owner['id'].'" LIMIT 1'); + + continue; + } + + $sql->query('SELECT ' + .'`id`,' + .'`unit`,' + .'`tarif`,' + .'`address`,' + .'`game`,' + .'`slots_start`,' + .'`online`,' + .'`status`,' + .'`name`,' + .'`map`,' + .'`time`,' + .'`overdue`' + .' FROM `servers` WHERE `id`="'.$owner['server'].'" LIMIT 1'); + + while($server = $sql->get()) + { + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('list', 'sections/servers'); + + $html->set('id', $server['id']); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + + $html->pack('list'); + + $wait_servers .= $server['id'].':false,'; + $updates_servers .= 'setTimeout(function() {update_info(\''.$server['id'].'\', true)}, 5000); setTimeout(function() {update_status(\''.$server['id'].'\', true)}, 10000);'; + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/console.php b/system/sections/megp/servers/samp/console.php new file mode 100644 index 0000000..78da5ef --- /dev/null +++ b/system/sections/megp/servers/samp/console.php @@ -0,0 +1,14 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/index.php b/system/sections/megp/servers/samp/index.php new file mode 100644 index 0000000..2025c89 --- /dev/null +++ b/system/sections/megp/servers/samp/index.php @@ -0,0 +1,35 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + $tarif['packs'] = sys::b64djs($tarif['packs']); + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + $html->set('btn', $btn); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/settings.php b/system/sections/megp/servers/samp/settings.php new file mode 100644 index 0000000..7d7260d --- /dev/null +++ b/system/sections/megp/servers/samp/settings.php @@ -0,0 +1,46 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $aSub = array('start', 'pack'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + $dir = $url['subsection'] == 'start' ? 'megp/' : ''; + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.$dir.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/settings/start.php b/system/sections/megp/servers/samp/settings/start.php new file mode 100644 index 0000000..c64a63b --- /dev/null +++ b/system/sections/megp/servers/samp/settings/start.php @@ -0,0 +1,44 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/tarif.php b/system/sections/megp/servers/samp/tarif.php new file mode 100644 index 0000000..7d95fa2 --- /dev/null +++ b/system/sections/megp/servers/samp/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'slots'); + + include(SEC.'megp/servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/tarif/extend.php b/system/sections/megp/servers/samp/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/megp/servers/samp/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/samp/tarif/slots.php b/system/sections/megp/servers/samp/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/megp/servers/samp/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/scan.php b/system/sections/megp/servers/scan.php new file mode 100644 index 0000000..f2e2f23 --- /dev/null +++ b/system/sections/megp/servers/scan.php @@ -0,0 +1,27 @@ +query('SELECT `game` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'games/'.$server['game'].'/scan.php'); + + // Запрошена информация (статус, онлайн, название) + if(isset($url['mon'])) + sys::outjs(scan::mon($id)); + + // Запрошена информация (статус, онлайн, название, игроки) + if(isset($url['fmon'])) + sys::outjs(scan::mon($id, true)); + + // Запрошена информация (cpu, ram, hdd) + if(isset($url['resources'])) + sys::outjs(scan::resources($id)); + + // Запрошена информация (работает, меняется карта, переустанавливается) + if(isset($url['status'])) + sys::outjs(scan::status($id)); + + exit; +?> \ No newline at end of file diff --git a/system/sections/megp/servers/settings.php b/system/sections/megp/servers/settings.php new file mode 100644 index 0000000..d8dd817 --- /dev/null +++ b/system/sections/megp/servers/settings.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'settings'); + + include(sys::route($server, 'settings', $go)); +?> \ No newline at end of file diff --git a/system/sections/megp/servers/tarif.php b/system/sections/megp/servers/tarif.php new file mode 100644 index 0000000..63c161a --- /dev/null +++ b/system/sections/megp/servers/tarif.php @@ -0,0 +1,18 @@ +query('SELECT `uid`, `unit`, `user`, `tarif`, `address`, `port`, `game`, `status`, `slots`, `slots_start`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time`, `test`, `fps`, `tickrate`, `ram`, `ram_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'tarif'); + + if($server['status'] == 'blocked') + { + if($go) + sys::out('Раздел недоступен'); + + include(SEC.'megp/servers/noaccess.php'); + }else + include(SEC.'megp/servers/'.$server['game'].'/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/monitoring/all.php b/system/sections/monitoring/all.php new file mode 100644 index 0000000..69d25be --- /dev/null +++ b/system/sections/monitoring/all.php @@ -0,0 +1,119 @@ +nav('Мониторинг'); + +// Дополнительная переменная +$type = false; +$i = 0; + +// Получаем значение пагинации +if(isset($url['page'])){ + $page = sys::clean($url['page'], "int"); +}else{ + $page = 1; +} + +// Проверяем задано ли у нас фильтрация по типу игры +if(isset($url['game']) AND in_array($url['game'], array('cs', 'css', 'cssold', 'csgo', 'samp', 'crmp', 'mta', 'mc'))){ + $type = $url['game']; +} + +// Если идет сортировка по игре +if($type){ + + // SQL запрос для выборки + $qSql = "game = '{$type}' AND status = 'working'"; + + // Задаем переменной колличество серверов всего, результат кэша + $all = $mcache->get('monitoring_list_count_'.$type); + + // Если кэш пуст + if(!$all){ + + // Получаем инфу из бд, кооличество серверов всего + $sql->query("SELECT id FROM servers WHERE {$qSql}"); + $all = $sql->num(); + + // Закидываем значеие в кэш на 2 минуты + $mcache->set('monitoring_list_count_'.$type, $all, false, 120); + } + + // Массив для построения страниц + $aPage = sys::page($page, $all, 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'monitoring/type/'.$type); +}else{ + + // SQL запрос для выборки + $qSql = "status = 'working'"; + + // Задаем переменной колличество серверов всего, результат кэша + $all = $mcache->get('monitoring_list_count'); + + // Если кэш пуст + if(!$all){ + + // Получаем инфу из бд, кооличество серверов всего + $sql->query("SELECT id FROM servers WHERE {$qSql}"); + $all = $sql->num(); + + // Закидываем значеие в кэш на 2 минуты + $mcache->set('monitoring_list_count', $all, false, 120); + } + + // Массив для построения страниц + $aPage = sys::page($page, $all, 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'monitoring'); +} + + +// Получаем список серверов +$sql->query("SELECT `id`, `address`, `name`, `map`, `slots_start`, `online` FROM servers WHERE {$qSql} ORDER BY `id` ASC LIMIT {$aPage['num']}, 30"); + +// Циклически собираем шаблон серверов +while($server = $sql->get()) { + + // Увеличиваем значение ID + $i+=1; + + // Собираем шаблон + $html->get('list', 'sections/monitoring'); + $html->set('id', $i); + $html->set('server', $server['id']); + $html->set('address', $server['address']); + $html->set('name', $server['name']); + $html->set('map', $server['map']); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->pack('monitoring_list'); +} + +$games = array('cs', 'cssold', 'css', 'csgo', 'samp', 'crmp', 'mta', 'mc'); + $online = array(); + foreach($games as $game) + { + $sql->query('SELECT SUM(`online`) AS `online` FROM `servers` WHERE (`status`="working" OR `status`="change") AND `game`="'.$game.'"'); + $online[$game] = $sql->get()['online']; + } + +// Подготовка страницы +$html->get('all', 'sections/monitoring'); +foreach($games as $game) + if(!empty($online[$game])) + $html->set('o_'.$game, $online[$game]); + else + $html->set('o_'.$game, '0'); + $html->set('list', isset($html->arr['monitoring_list']) ? $html->arr['monitoring_list'] : ''); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); +$html->pack('main'); \ No newline at end of file diff --git a/system/sections/monitoring/server.php b/system/sections/monitoring/server.php new file mode 100644 index 0000000..e79554b --- /dev/null +++ b/system/sections/monitoring/server.php @@ -0,0 +1,77 @@ +nav('Мониторинг', $cfg['http'].'monitoring'); +$html->nav('Сервер #'.$id); + +// Получаем информацию о сервере +$sql->query("SELECT `id`, `unit`, `tarif`, `address`, `name`, `map`, `slots_start`, `online`, `players`, `status`, `game`, `pack`, `date` FROM servers WHERE id = '{$id}' LIMIT 1"); +$server = $sql->get(); + +// Если результат пустой +if(empty($server)){ + header('Refresh: 0; URL='.$cfg['http'].'monitoring'); + exit(); +} + +// Получаем название локации +$sql->query("SELECT name FROM units WHERE id = '{$server['unit']}' LIMIT 1"); +$unit = $sql->get(); + +// Получаем название тарифа и доступные сборки +$sql->query("SELECT name, packs FROM tarifs WHERE id = '{$server['tarif']}' LIMIT 1"); +$tarif = $sql->get(); + +// Получаем массив сборок +$aPacks = json_decode(base64_decode($tarif['packs']), true); + +// Получаем ключ для графиков +$sql->query("SELECT `key` FROM graph WHERE server = '{$id}' LIMIT 1"); + +// Если ключ отсуствует, создаем +if(!$sql->num()){ + + // Генерируем ключ + $key = md5($id.sys::key('graph')); + + // Добавляем в DB + $sql->query("INSERT INTO graph SET `server` = '{id}', `key` = '{key}', `time` = '0'"); +}else{ + + // Получаем ключ из бд + $graph = $sql->get(); + $key = $graph['key']; +} + +// Подготовка страницы +$html->get('server', 'sections/monitoring'); + $html->set('id', $server['id']); + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('name', $server['name']); + $html->set('map', $server['map']); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('pack', $aPacks[$server['pack']]); + $html->set('create', date("d.m.Y H:m", $server['date'])); +$html->pack('main'); \ No newline at end of file diff --git a/system/sections/news/index.php b/system/sections/news/index.php new file mode 100644 index 0000000..dd42140 --- /dev/null +++ b/system/sections/news/index.php @@ -0,0 +1,30 @@ +nav('Список новостей'); + + $sql->query('SELECT `id` FROM `news`'); + + $aPage = sys::page($page, $sql->num(), $cfg['news_page']); + + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'news'); + + $sql->query('SELECT `id`, `name`, `text`, `views`, `tags`, `date` FROM `news` ORDER BY `id` DESC LIMIT '.$aPage['num'].', '.$cfg['news_page']); + while($news = $sql->get()) + { + $html->get('list', 'sections/news'); + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', htmlspecialchars_decode($news['text'])); + $html->set('views', $news['views']); + $html->set('tags', sys::tags($news['tags'])); + $html->set('date', sys::today($news['date'])); + $html->pack('news'); + } + + $html->get('all', 'sections/news'); + $html->set('list', isset($html->arr['news']) ? $html->arr['news'] : ''); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/news/news.php b/system/sections/news/news.php new file mode 100644 index 0000000..d0b7738 --- /dev/null +++ b/system/sections/news/news.php @@ -0,0 +1,34 @@ +nav('Список новостей', $cfg['http'].'news'); + + $sql->query('SELECT `id`, `name`, `full_text`, `views`, `tags`, `date` FROM `news` WHERE `id`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + include(ENG.'404.php'); + + $news = $sql->get(); + + $sql->query('UPDATE `news` set `views`="'.($news['views']+1).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $text = htmlspecialchars_decode($news['full_text']); + + $title = $news['name']; + $description = $text; + $keywords = $news['tags']; + + $html->nav($news['name']); + + $html->get('news', 'sections/news'); + + $html->set('id', $news['id']); + $html->set('name', htmlspecialchars_decode($news['name'])); + $html->set('text', $text); + $html->set('views', $news['views']); + $html->set('tags', sys::tags($news['tags'])); + $html->set('date', sys::today($news['date'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/action.php b/system/sections/servers/action.php new file mode 100644 index 0000000..e8004d3 --- /dev/null +++ b/system/sections/servers/action.php @@ -0,0 +1,68 @@ +query('SELECT `game`, `status` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!isset($url['action'])) + sys::outjs(array('e' => 'Неверный запрос для выполнения операции')); + + $nmch = 'server_action_'.$id; + + if($mcache->get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache'))); + + $mcache->set($nmch, true, false, 10); + + include(LIB.'games/'.$server['game'].'/action.php'); + + switch($url['action']) + { + case 'stop': + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + sys::outjs(array('e' => sys::text('error', 'ser_stop')), $nmch); + + sys::outjs(action::stop($id), $nmch); + + case 'start': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_start')), $nmch); + + sys::outjs(action::start($id), $nmch); + + case 'restart': + if(!in_array($server['status'], array('working', 'start', 'restart', 'change'))) + sys::outjs(array('e' => sys::text('error', 'ser_restart')), $nmch); + + sys::outjs(action::start($id, 'restart'), $nmch); + + case 'change': + if($server['status'] != 'working') + { + if($server['status'] == 'change') + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + sys::outjs(array('e' => sys::text('error', 'ser_change')), $nmch); + } + + if(isset($url['change'])) + sys::outjs(action::change($id, $url['change']), $nmch); + + sys::outjs(action::change($id), $nmch); + + case 'reinstall': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_reinstall')), $nmch); + + sys::outjs(action::reinstall($id), $nmch); + + case 'update': + if($server['status'] != 'off') + sys::outjs(array('e' => sys::text('error', 'ser_update')), $nmch); + + sys::outjs(action::update($id), $nmch); + } + + exit; +?> \ No newline at end of file diff --git a/system/sections/servers/boost.php b/system/sections/servers/boost.php new file mode 100644 index 0000000..3f9d4aa --- /dev/null +++ b/system/sections/servers/boost.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'boost'); + + include(sys::route($server, 'boost', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/console.php b/system/sections/servers/console.php new file mode 100644 index 0000000..f49ac21 --- /dev/null +++ b/system/sections/servers/console.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'console'); + + include(sys::route($server, 'console', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/copy.php b/system/sections/servers/copy.php new file mode 100644 index 0000000..f075051 --- /dev/null +++ b/system/sections/servers/copy.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `tarif`, `user`, `address`, `game`, `pack`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'copy'); + + include(sys::route($server, 'copy', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/console.php b/system/sections/servers/crmp/console.php new file mode 100644 index 0000000..3c42b22 --- /dev/null +++ b/system/sections/servers/crmp/console.php @@ -0,0 +1,44 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if($server['status'] == 'off') + sys::out(sys::text('servers', 'off')); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::out(sys::text('error', 'ssh')); + + $dir = $tarif['install'].$server['uid'].'/'; + + $filecmd = $dir.'server_log.txt'; + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/copy.php b/system/sections/servers/crmp/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/crmp/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/graph.php b/system/sections/servers/crmp/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/crmp/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/index.php b/system/sections/servers/crmp/index.php new file mode 100644 index 0000000..3f35c48 --- /dev/null +++ b/system/sections/servers/crmp/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], 'crmp', 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/plugins.php b/system/sections/servers/crmp/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/crmp/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/rcon.php b/system/sections/servers/crmp/rcon.php new file mode 100644 index 0000000..1a0de70 --- /dev/null +++ b/system/sections/servers/crmp/rcon.php @@ -0,0 +1,54 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/settings.php b/system/sections/servers/crmp/settings.php new file mode 100644 index 0000000..132d29b --- /dev/null +++ b/system/sections/servers/crmp/settings.php @@ -0,0 +1,72 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'firewall', 'crontab', 'startlogs', 'pack', 'file', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/settings/server.php b/system/sections/servers/crmp/settings/server.php new file mode 100644 index 0000000..c9b07a5 --- /dev/null +++ b/system/sections/servers/crmp/settings/server.php @@ -0,0 +1,119 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' '.$val."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/server.cfg'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $sql->query('UPDATE `servers` set `map_start`="'.htmlspecialchars($servercfg['rcon_password']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/settings/start.php b/system/sections/servers/crmp/settings/start.php new file mode 100644 index 0000000..862c835 --- /dev/null +++ b/system/sections/servers/crmp/settings/start.php @@ -0,0 +1,45 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/tarif.php b/system/sections/servers/crmp/tarif.php new file mode 100644 index 0000000..c321da7 --- /dev/null +++ b/system/sections/servers/crmp/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/tarif/extend.php b/system/sections/servers/crmp/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/servers/crmp/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/tarif/slots.php b/system/sections/servers/crmp/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/servers/crmp/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/tarif/unit.php b/system/sections/servers/crmp/tarif/unit.php new file mode 100644 index 0000000..b840bc7 --- /dev/null +++ b/system/sections/servers/crmp/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aTICKold = explode(':', $oldTarif['tickrate']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + if(!in_array($server['tickrate'], $aTICK)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['tickrate'], $aTICKold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/crmp/web.php b/system/sections/servers/crmp/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/crmp/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/boost.php b/system/sections/servers/cs/boost.php new file mode 100644 index 0000000..d539440 --- /dev/null +++ b/system/sections/servers/cs/boost.php @@ -0,0 +1,100 @@ + 'Необходимо указать сервис.')); + + // Проверка сервиса + if(!in_array($aData['site'], $aBoost[$server['game']]['boost'])) + sys::outjs(array('e' => 'Указанный сервис по раскрутке не найден.')); + + if(isset($url['rating'])) + { + $rating = $url['rating'] == 'up' ? '1' : '-1'; + + $sql->query('SELECT `id` FROM `boost_rating` WHERE `boost`="'.$aData['site'].'" AND `user`="'.$user['id'].'" AND `rating`="'.$rating.'" LIMIT 1'); + if($sql->num()) + sys::out('err'); + + $sql->query('DELETE FROM `boost_rating` WHERE `boost`="'.$aData['site'].'" AND `user`="'.$user['id'].'" LIMIT 1'); + $sql->query('INSERT INTO `boost_rating` set `boost`="'.$aData['site'].'", `rating`="'.$rating.'", `user`="'.$user['id'].'"'); + + $sql->query('SELECT SUM(`rating`) FROM `boost_rating` WHERE `boost`="'.$aData['site'].'"'); + $sum = $sql->get(); + + $rating = (int) $sum['SUM(`rating`)']; + + sys::out($rating, 'server_boost_'.$id); + } + + $aData['service'] = isset($url['service']) ? sys::int($url['service']) : sys::outjs(array('e' => 'Необходимо указать номер услуги.')); + + // Проверка номера услуги + if(!in_array($aData['service'], $aBoost[$server['game']][$aData['site']]['services'])) + sys::outjs(array('e' => 'Неправильно указан номер услуги.')); + + // Определение суммы + $sum = $aBoost[$server['game']][$aData['site']]['price'][$aData['service']]; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $name_mcache); + + include(LIB.'games/boost.php'); + + $boost = new boost($aBoost[$server['game']][$aData['site']]['key'], $aBoost[$server['game']][$aData['site']]['api']); + + $buy = $boost->$aBoost[$server['game']][$aData['site']]['type'](array('period' => $aData['service'], 'address' => $server['address'])); + + if(is_array($buy)) + sys::outjs(array('e' => $buy['error'])); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + include(LIB.'games/games.php'); + + // Реф. система + games::part($user['id'], $sum); + + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_boost'), + array('circles' => $aBoost[$server['game']][$aData['site']]['circles'][$aData['service']], + 'money' => $sum, 'site' => $aBoost[$server['game']][$aData['site']]['site'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="boost", `money`="'.$sum.'"'); + + $sql->query('INSERT INTO `boost` set `user`="'.$user['id'].'", `server`="'.$id.'", `site`="'.$aData['site'].'", `circles`="'.$aBoost[$server['game']][$aData['site']]['circles'][$aData['service']].'", `money`="'.$sum.'", `date`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Раскрутка'); + + if($mcache->get('server_boost_'.$id) != '') + $html->arr['main'] = $mcache->get('server_boost_'.$id); + else{ + $html->get('boost', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('address', $server['address']); + + foreach($aBoost[$server['game']]['boost'] as $boost) + { + $sql->query('SELECT SUM(`rating`) FROM `boost_rating` WHERE `boost`="'.$boost.'"'); + $sum = $sql->get(); + + $rating = (int) $sum['SUM(`rating`)']; + + $html->set($boost, $rating); + } + + $html->pack('main'); + + $mcache->set('server_boost_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/console.php b/system/sections/servers/cs/console.php new file mode 100644 index 0000000..fec0e74 --- /dev/null +++ b/system/sections/servers/cs/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + $filecmd = $dir.'qconsole.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/copy.php b/system/sections/servers/cs/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/cs/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/graph.php b/system/sections/servers/cs/graph.php new file mode 100644 index 0000000..c106d08 --- /dev/null +++ b/system/sections/servers/cs/graph.php @@ -0,0 +1,70 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/index.php b/system/sections/servers/cs/index.php new file mode 100644 index 0000000..affa171 --- /dev/null +++ b/system/sections/servers/cs/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `fps`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['fps'].' FPS'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/maps.php b/system/sections/servers/cs/maps.php new file mode 100644 index 0000000..de85c4d --- /dev/null +++ b/system/sections/servers/cs/maps.php @@ -0,0 +1,87 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'list', 'listing', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Карты', $cfg['http'].'servers/id/'.$id.'/section/maps'); + + if($go) + $nmch = sys::rep_act('server_maps_go_'.$id, 10); + + include(SEC.'servers/'.$server['game'].'/maps/'.$url['subsection'].'.php'); + }else{ + $html->nav('Карты'); + + // Построение списка установленных карт + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Сортировка карт + sort($aMaps); + reset($aMaps); + + $mapsjs = ''; + $i = 0; + + foreach($aMaps as $index => $map) + { + if(!isset($map{3})) + continue; + + $mapjs = str_replace('$', '-_-', $map); + + $i+=1; + $mapsjs .= $i.' : "'.$mapjs.'",'; + + $html->get('map_server', 'sections/servers/games/maps'); + $html->set('img', sys::img($map, $server['game'])); + $html->set('map', $mapjs); + $html->set('name', $map); + $html->pack('maps'); + } + + // Если есть кеш + if($mcache->get('server_maps_'.$id) != '') + $html->arr['main'] = $mcache->get('server_maps_'.$id); + else{ + $html->get('maps', 'sections/servers/games'); + $html->set('id', $id); + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : ''); + $html->set('mapsjs', $mapsjs); + $html->pack('main'); + + $mcache->set('server_maps_'.$id, $html->arr['main'], false, 3); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/maps/delete.php b/system/sections/servers/cs/maps/delete.php new file mode 100644 index 0000000..7b0173a --- /dev/null +++ b/system/sections/servers/cs/maps/delete.php @@ -0,0 +1,70 @@ +query('SELECT `unit`, `tarif`, `map_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка карт + $ssh->set('cd '.$dir.'maps/ && ls | grep -iE "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $name => $sel) + if($sel) + { + $map = str_replace(array("\\", "'", "'", '-_-'), array('', '', '', '$'), $name); + + // Проверка наличия карты + if(!in_array($map, $aMaps)) + continue; + + // Проверка: является ли карта стартовой + if($server['map_start'] == $map) + continue; + + $ssh->set('cd /path/maps/'.$server['game'].'/'.sys::map($map).' && du -a | grep -iE "\.[a-z]{1,3}$" | awk \'{print $2}\''); + + $aFiles = explode("\n", str_replace('./', '', $ssh->get())); + + if(isset($aFiles[count($aFiles)-1]) AND $aFiles[count($aFiles)-1] == '') + unset($aFiles[count($aFiles)-1]); + + $files = ''; + + foreach($aFiles as $file) + $files .= $dir.$file.' '; + + $rm = ''; + $aFlrm = explode(' ', $dir.'maps/'.$map.'.* '.trim($files)); + + foreach($aFlrm as $flrm) + $rm .= sys::map($flrm).' '; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS md'.$start_point.$id.' sh -c \'rm '.trim($rm).'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/cs/maps/install.php b/system/sections/servers/cs/maps/install.php new file mode 100644 index 0000000..b54e0fd --- /dev/null +++ b/system/sections/servers/cs/maps/install.php @@ -0,0 +1,56 @@ +query('SELECT `unit`, `tarif`, `hdd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Проверить наличие свободного места + $ssh->set('cd '.$dir.' && du -ms'); + $hdd = ceil(sys::int($ssh->get())/($server['hdd']/100)); + $hdd = $hdd > 100 ? 100 : $hdd; + + if($hdd == 100) + sys::outjs(array('e' => 'Невозможно выполнить установку, нет свободного места'), $nmch); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $mid => $sel) + if($sel) + { + $map = sys::int($mid); + + // Проверка наличия карты + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `id`="'.$map.'" AND `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $map = $sql->get(); + + $cp = 'cp /path/maps/'.$server['game'].'/'.sys::map($map['name']).'.* '.$dir.'maps/;' + .'cd /path/maps/'.$server['game'].'/'.sys::map($map['name']).'/ && cp -r * '.$dir; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS mc'.$start_point.$id.' sh -c \''.$cp.'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/cs/maps/list.php b/system/sections/servers/cs/maps/list.php new file mode 100644 index 0000000..f3c28dc --- /dev/null +++ b/system/sections/servers/cs/maps/list.php @@ -0,0 +1,85 @@ +nav('Установка карт'); + + // Категории для быстрой сортировки + $html->get('types', 'sections/servers/'.$server['game'].'/maps'); + $html->set('id', $id); + $html->pack('types'); + + $type = false; + + include(DATA.'maps.php'); + include(LIB.'games/games.php'); + + if(isset($url['type']) AND array_key_exists($url['type'], $aFindMap[$server['game']])) + $type = $url['type']; + + if($type) + { + $qsql = games::mapsql($aFindMap[$server['game']][$type]); + + $all = $mcache->get('maps_'.$server['game'].'_'.$type); + + if(!$all) + { + $sql->query('SELECT `id` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" '.$qsql); + $all = $sql->num(); + + $mcache->set('maps_'.$server['game'].'_'.$type, $all, false, 120); + } + + // Массив для построения страниц + $aPage = sys::page($page, $all, 60); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'servers/id/'.$id.'/section/maps/subsection/list/type/'.$type); + + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" '.$qsql.' ORDER BY `name` ASC LIMIT '.$aPage['num'].', 30'); + }else{ + $all = $mcache->get('maps_'.$server['game']); + + if(!$all) + { + $sql->query('SELECT `id` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'"'); + $all = $sql->num(); + + $mcache->set('maps_'.$server['game'], $all, false, 120); + } + + // Массив для построения страниц + $aPage = sys::page($page, $all, 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'servers/id/'.$id.'/section/maps/subsection/list'); + + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `name` ASC LIMIT '.$aPage['num'].', 30'); + } + + $mapsjs = ''; + $i = 0; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs .= $i.' : "'.$map['id'].'",'; + + $html->get('map_install', 'sections/servers/games/maps'); + $html->set('id', $map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', $map['name']); + $html->pack('maps'); + } + + $html->get('install', 'sections/servers/games/maps'); + $html->set('id', $id); + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : 'К сожалению карты не найдены в базе'); + $html->set('amaps', $mapsjs); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->set('cdn', $cfg['cdn']); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/maps/listing.php b/system/sections/servers/cs/maps/listing.php new file mode 100644 index 0000000..93dec91 --- /dev/null +++ b/system/sections/servers/cs/maps/listing.php @@ -0,0 +1,94 @@ +nav('Списки карт'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/maps'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория сервера + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка + if($go AND isset($url['gen'])) + { + $ssh->set('cd '.$dir.'maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace(array('./', '.bsp'), '', $maps)); + + sort($aMaps); + reset($aMaps); + + $list = ''; + + foreach($aMaps as $index => $map) + { + $aMap = explode('/', $map); + $name = end($aMap); + if(strlen($name) < 4) + continue; + + $list .= $map."\n"; + } + + sys::outjs(array('s' => $list), $nmch); + } + + $aFiles = array( + 'mapcycle' => 'mapcycle.txt', + 'maps' => 'addons/amxmodx/configs/maps.ini' + ); + + // Сохранение + if($go AND isset($url['file'])) + { + if(!array_key_exists($url['file'], $aFiles)) + exit; + + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $dir.$aFiles[$url['file']], 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$dir.$aFiles[$url['file']]); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['mapcycle'].'; cat '.$dir.$aFiles['mapcycle'].'"'); + $mapcycle = $ssh->get(); + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['maps'].'; cat '.$dir.$aFiles['maps'].'"'); + $maps = $ssh->get(); + + $html->get('listing', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->set('mapcycle', $mapcycle); + $html->set('maps', $maps); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/maps/search.php b/system/sections/servers/cs/maps/search.php new file mode 100644 index 0000000..866ca47 --- /dev/null +++ b/system/sections/servers/cs/maps/search.php @@ -0,0 +1,64 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + // Поиск по картам + if($text{0} == '^') + { + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode(str_replace('_', '\_', $text).'').'\') ORDER BY `name` ASC LIMIT 12'); + $text = substr($text, 1); + }else + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') ORDER BY `name` ASC LIMIT 12'); + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $i = 0; + $mapsjs = ''; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs[$i] = 's'.$map['id']; + + $html->get('map_search', 'sections/servers/games/maps'); + + $html->set('id', 's'.$map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', sys::find($map['name'], $text)); + + $html->pack('maps'); + } + + $mcache->set($mkey, array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs), false, 15); + + sys::outjs(array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs)); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/plugins.php b/system/sections/servers/cs/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/cs/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/rcon.php b/system/sections/servers/cs/rcon.php new file mode 100644 index 0000000..9c2389c --- /dev/null +++ b/system/sections/servers/cs/rcon.php @@ -0,0 +1,53 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'amx_kick "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'amx_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings.php b/system/sections/servers/cs/settings.php new file mode 100644 index 0000000..c5f3a92 --- /dev/null +++ b/system/sections/servers/cs/settings.php @@ -0,0 +1,77 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'amxlogs', 'pack', 'file', 'antiddos', 'privileges', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/admins.php b/system/sections/servers/cs/settings/admins.php new file mode 100644 index 0000000..83edc7d --- /dev/null +++ b/system/sections/servers/cs/settings/admins.php @@ -0,0 +1,151 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['type'] = isset($_POST['type']) ? $_POST['type'] : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $type = isset($aData['type'][$index]) ? $aData['type'][$index] : 'a'; + if(!in_array($type, array('c', 'ce', 'de', 'a'))) + $type = 'a'; + + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['passwd'][$index].'" "'.$aData['flags'][$index].'" "'.$type.'"'; + + $sql->query('INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$id.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`type`="'.$type.'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/addons/amxmodx/configs/users.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/addons/amxmodx/configs/users.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `type`, `time`, `info` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + switch($admin['type']) + { + case 'c': + $type = ''; + break; + + case 'ce': + $type = ''; + break; + + case 'de': + $type = ''; + break; + + default: + $type = ''; + } + + $html->get('list', 'sections/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('type', $type); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + list($ip, $port) = explode(':', $server['address']); + + $html->get('admins', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + $html->set('address', 'ip/'.$ip.'/port/'.$port); + + $sql->query('SELECT `active` FROM `privileges` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $privilege = $sql->get(); + + if($privilege['active']) + $html->unit('privileges', 1); + else + $html->unit('privileges'); + }else + $html->unit('privileges'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/amxlogs.php b/system/sections/servers/cs/settings/amxlogs.php new file mode 100644 index 0000000..e02ee9a --- /dev/null +++ b/system/sections/servers/cs/settings/amxlogs.php @@ -0,0 +1,89 @@ +nav('Логи AMX'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/addons/amxmodx/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csamxlogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/amxlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'amxlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/amxlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'amxlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', 'amx'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/antiddos.php b/system/sections/servers/cs/settings/antiddos.php new file mode 100644 index 0000000..6451e5d --- /dev/null +++ b/system/sections/servers/cs/settings/antiddos.php @@ -0,0 +1,73 @@ +query('SELECT `id` FROM `units` WHERE `id`="'.$server['unit'].'" AND `ddos`="1" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'В данный момент нельзя изменить параметр, т.к. включена защита на всю локацию.'), $name_mcache); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($url['type']) || !in_array($url['type'], array('0', '1', '2'))) + sys::outjs(array('e' => 'Неправильно передан параметр.'), $name_mcache); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh', $user['group'])), $name_mcache); + + list($ip, $port) = explode(':', $server['address']); + + $geo = $cfg['iptables'].'_geo'; + + if($url['type'] == 2) + { + if($server['ddos'] == 2) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="2" WHERE `id`="'.$id.'" LIMIT 1'); + }elseif($url['type'] == 1){ + if($server['ddos'] == 1) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="1" WHERE `id`="'.$id.'" LIMIT 1'); + }else{ + if(!$server['ddos']) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $country = $server['ddos'] == 2 ? 'AM,BY,UA,RU,KZ' : 'UA,RU'; + + $ssh->set('iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country '.$country.' -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'); + + $sql->query('UPDATE `servers` set `ddos`="0" WHERE `id`="'.$id.'" LIMIT 1'); + } + + $mcache->delete('server_settings_'.$id); + + sys::outjs(array('s' => 'ok'), $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/bans.php b/system/sections/servers/cs/settings/bans.php new file mode 100644 index 0000000..ee82294 --- /dev/null +++ b/system/sections/servers/cs/settings/bans.php @@ -0,0 +1,167 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к файлам (banned.cfg / listip.cfg) + $folder = $tarif['install'].$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_ban 0 ".$aData['value']." EGP\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_ban 0 ".$aData['value']." EGP\"\015'"); + }else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned.cfg; rm temp_banned.cfg"'); + + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_unban ".$aData['value']."\"\015'"); + }else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_ban 0 ".$aData['value']." EGP\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_ban 0 ".$aData['value']." EGP\"\015'"); + }else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' listip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/listip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из listip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat listip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > listip.cfg; rm temp_listip.cfg"'); + + // Если включен amxbans/csbans + if($aData['amxbans']) + { + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"fb_unban ".$aData['value']."\"\015'"); + }else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' listip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле listip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле listip.cfg'), $nmch); + } + } + } + + // Содержимое banned.cfg + $ssh->set('cd '.$folder.' && cat banned.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое listip.cfg + $ssh->set('cd '.$folder.' && cat listip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/debug.php b/system/sections/servers/cs/settings/debug.php new file mode 100644 index 0000000..180f9d0 --- /dev/null +++ b/system/sections/servers/cs/settings/debug.php @@ -0,0 +1,28 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Чтение файла - oldstart.log + $file = $tarif['install'].$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/logs.php b/system/sections/servers/cs/settings/logs.php new file mode 100644 index 0000000..94ba493 --- /dev/null +++ b/system/sections/servers/cs/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/privileges.php b/system/sections/servers/cs/settings/privileges.php new file mode 100644 index 0000000..de8716a --- /dev/null +++ b/system/sections/servers/cs/settings/privileges.php @@ -0,0 +1,138 @@ +query('SELECT `active` FROM `privileges` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $privilege = $sql->get(); + + if(!$privilege['active']) + { + $sql->query('SELECT `id` FROM `privileges_list` WHERE `server`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо настроить привилегии')); + + $sql->query('UPDATE `privileges` set `active`="1" WHERE `server`="'.$id.'" LIMIT 1'); + }else + $sql->query('UPDATE `privileges` set `active`="0" WHERE `server`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + + sys::outjs(array('e' => 'Необходимо настроить привилегии')); + } + + if(isset($url['delete'])) + { + $sql->query('DELETE FROM `privileges_list` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + $sql->query('SELECT `id` FROM `privileges_list` WHERE `server`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + $sql->query('UPDATE `privileges` set `active`="0" WHERE `server`="'.$id.'" LIMIT 1'); + + sys::out(); + } + + if($go) + { + $sql->query('SELECT `id` FROM `privileges_list` WHERE `server`="'.$id.'" LIMIT 10'); + if($sql->num() > 9) + sys::outjs(array('e' => 'Нельзя добавить больше 10-и привилегий'), $name_mcache); + + $aData = array(); + + $aData['name'] = isset($_POST['name']) ? trim($_POST['name']) : sys::outjs(array('e' => 'Необходимо заполнить все поля'), $name_mcache); + $aData['flags'] = isset($_POST['flags']) ? trim($_POST['flags']) : sys::outjs(array('e' => 'Необходимо заполнить все поля'), $name_mcache); + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : sys::outjs(array('e' => 'Необходимо заполнить все поля'), $name_mcache); + $aData['price'] = isset($_POST['price']) ? $_POST['price'] : sys::outjs(array('e' => 'Необходимо заполнить все поля'), $name_mcache); + + if(sys::strlen($aData['name']) < 3 || sys::strlen($aData['name']) > 30) + sys::outjs(array('e' => 'Длина названия должна быть от 3-х до 30-и символов'), $name_mcache); + + if(sys::valid($aData['name'], 'other', '/[А-яA-z0-9]+$/u')) + sys::outjs(array('e' => 'Неверное указано название, доступны латинские, русские буквы и цифры.'), $name_mcache); + + if(sys::valid($aData['flags'], 'other', '/^[a-z]+$/') || (sys::strlen($aData['flags']) < 1 || sys::strlen($aData['flags']) > 22)) + sys::outjs(array('e' => 'Неверное указаны флаги AmxModX.'), $name_mcache); + + foreach(count_chars($aData['flags'], 1) as $val) + if($val > 1) + sys::outjs(array('e' => 'Неверное указаны флаги AmxModX, флаг не должен повторяться дважды.'), $name_mcache); + + if((!is_array($aData['time']) || !is_array($aData['price'])) || (count($aData['time']) < 1|| count($aData['time']) > 5) || (count($aData['time']) != count($aData['price']))) + sys::outjs(array('e' => 'Неверное переданы данные.'), $name_mcache); + + $keys = array(); + $data = array(); + + foreach($aData['time'] as $key => $val) + { + $val = intval($val); + + if($val > 1000) + $val = 1000; + + if(in_array($val, $keys)) + continue; + + $aData['price'][$key] = intval($aData['price'][$key]); + + if($aData['price'][$key] < 1) + continue; + + $data[$val] = $aData['price'][$key]; + $keys[] = $val; + } + + if(!count($data)) + sys::outjs(array('e' => 'Неверное переданы данные.'), $name_mcache); + + $sql->query('SELECT `id` FROM `privileges` WHERE `server`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + $sql->query('INSERT INTO `privileges` set `server`="'.$id.'", `active`="0"'); + + $sql->query('INSERT INTO `privileges_list` set `server`="'.$id.'", `name`="'.$aData['name'].'", `flags`="'.$aData['flags'].'", `data`="'.sys::b64js($data).'"'); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + $html->nav('Управление администраторами', $cfg['http'].'servers/id/'.$id.'/section/settings/subsection/admins'); + $html->nav('Настройка платных привилегий'); + + $sql->query('SELECT `id`, `name`, `flags`, `data` FROM `privileges_list` WHERE `server`="'.$id.'" ORDER BY `id` ASC LIMIT 10'); + while($privilege = $sql->get()) + { + $data = sys::b64djs($privilege['data']); + + $time = ''; + + if(isset($data[0])) + { + $time = 'Навсегда / '.$data[0].' '.$cfg['currency'].'; '; + + unset($data[0]); + } + + foreach($data as $days => $price) + $time .= $days.' '.sys::day($time).' / '.$price.' '.$cfg['currency'].'; '; + + $html->get('list', 'sections/servers/'.$server['game'].'/settings/privileges'); + + $html->set('id', $privilege['id']); + $html->set('name', $privilege['name']); + $html->set('flags', $privilege['flags']); + $html->set('time', $time); + + $html->pack('list'); + } + + $html->get('privileges', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('list', $html->arr['list']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/server.php b/system/sections/servers/cs/settings/server.php new file mode 100644 index 0000000..158ec18 --- /dev/null +++ b/system/sections/servers/cs/settings/server.php @@ -0,0 +1,119 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/server.cfg'); + + unlink($temp); + + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "exec server.cfg"\015\';'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/cstrike/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/start.php b/system/sections/servers/cs/settings/start.php new file mode 100644 index 0000000..25d83e2 --- /dev/null +++ b/system/sections/servers/cs/settings/start.php @@ -0,0 +1,166 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fps`, `fastdl`, `autorestart`, `pingboost` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `fps`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $map, true, $nmch); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['fps']))) + $sql->query('UPDATE `servers` set `fps`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'pingboost': + if($cfg['change_pingboost'] AND in_array($value, array(1, 2, 3))) + $sql->query('UPDATE `servers` set `pingboost`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/cstrike/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/cstrike/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + + if(!tarif::price($tarif['price'])) + { + $aFps = explode(':', $tarif['fps']); + + unset($aFps[array_search($server['fps'], $aFps)]); + + if(count($aFps)) + foreach($aFps as $value) + $fps .= ''; + } + + if($cfg['change_pingboost']) + $pingboost = str_replace($server['pingboost'].'"', $server['pingboost'].'" selected="select"', ''); + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if($cfg['change_pingboost']) + { + $html->unit('pingboost', true); + $html->set('pingboost', $pingboost); + }else + $html->unit('pingboost'); + + if(!tarif::price($tarif['price'])) + { + $html->unit('fps', true); + $html->set('fps', $fps); + }else + $html->unit('fps'); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/settings/top.php b/system/sections/servers/cs/settings/top.php new file mode 100644 index 0000000..e0e1d61 --- /dev/null +++ b/system/sections/servers/cs/settings/top.php @@ -0,0 +1,25 @@ +query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Удаление файла csstats.dat + $ssh->set('rm '.$tarif['install'].$server['uid'].'/cstrike/addons/amxmodx/data/csstats.dat'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + shell_exec('php cron.php '.$cfg['cron_key'].' server_action restart cs '.$id); + + sys::outjs(array('s' => 'ok')); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cs/tarif.php b/system/sections/servers/cs/tarif.php new file mode 100644 index 0000000..bff952e --- /dev/null +++ b/system/sections/servers/cs/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/tarif/extend.php b/system/sections/servers/cs/tarif/extend.php new file mode 100644 index 0000000..0e66ff6 --- /dev/null +++ b/system/sections/servers/cs/tarif/extend.php @@ -0,0 +1,52 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['fps'] = $server['fps']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($server['fps'], $aFPS)]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/tarif/plan.php b/system/sections/servers/cs/tarif/plan.php new file mode 100644 index 0000000..d847cdc --- /dev/null +++ b/system/sections/servers/cs/tarif/plan.php @@ -0,0 +1,66 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + // Проверка плана + if(array_search($plan, $aFPS) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + if($plan == $server['fps']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aFPS)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($server['fps'], $aFPS)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + sys::benefitblock($id, $nmch); + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `fps`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/tarif/slots.php b/system/sections/servers/cs/tarif/slots.php new file mode 100644 index 0000000..b32de8a --- /dev/null +++ b/system/sections/servers/cs/tarif/slots.php @@ -0,0 +1,34 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день 1 слота + $price = $aPrice[array_search($server['fps'], $aFPS)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($server['fps'], $aFPS)]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/tarif/unit.php b/system/sections/servers/cs/tarif/unit.php new file mode 100644 index 0000000..1ea53a9 --- /dev/null +++ b/system/sections/servers/cs/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `fps`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aFPSold = explode(':', $oldTarif['fps']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aFPS = explode(':', $tarif['fps']); + + if(!in_array($server['fps'], $aFPS)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['fps'], $aFPS)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['fps'], $aFPSold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cs/web.php b/system/sections/servers/cs/web.php new file mode 100644 index 0000000..d987a62 --- /dev/null +++ b/system/sections/servers/cs/web.php @@ -0,0 +1,86 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/console.php b/system/sections/servers/csgo/console.php new file mode 100644 index 0000000..6f548f0 --- /dev/null +++ b/system/sections/servers/csgo/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/csgo/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/copy.php b/system/sections/servers/csgo/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/csgo/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/graph.php b/system/sections/servers/csgo/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/csgo/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/index.php b/system/sections/servers/csgo/index.php new file mode 100644 index 0000000..e16beb5 --- /dev/null +++ b/system/sections/servers/csgo/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `tickrate`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['tickrate'].' TickRate'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/maps.php b/system/sections/servers/csgo/maps.php new file mode 100644 index 0000000..9fc1ba3 --- /dev/null +++ b/system/sections/servers/csgo/maps.php @@ -0,0 +1,97 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'list', 'listing', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Карты', $cfg['http'].'servers/id/'.$id.'/section/maps'); + + $nmch = sys::rep_act('server_maps_go_'.$id, 10); + + include(SEC.'servers/'.$server['game'].'/maps/'.$url['subsection'].'.php'); + }else{ + $html->nav('Карты'); + + // Построение списка установленных карт + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cd '.$tarif['install'].$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\''); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Сортировка карт + sort($aMaps); + reset($aMaps); + + $mapsjs = ''; + $i = 0; + + foreach($aMaps as $index => $map) + { + if(!isset($map{3})) + continue; + + $map = str_replace('./', '', $map); + + $mapjs = str_replace('$', '-_-', $map); + + $aName = explode('/', $map); + $name = end($aName); + + $html->get('map_server', 'sections/servers/csgo/maps'); + $html->set('img', sys::img($name, $server['game'])); + $html->set('map', $mapjs); + $html->set('name', $name); + + if(count($aName) > 1) + $html->unit('workshop', true, true); + else{ + $i+=1; + $mapsjs .= $i.' : "'.$mapjs.'",'; + + $html->unit('workshop', false, true); + } + $html->pack('maps'); + } + + // Если есть кеш + if($mcache->get('server_maps_'.$id) != '') + $html->arr['main'] = $mcache->get('server_maps_'.$id); + else{ + $html->get('maps', 'sections/servers/games'); + $html->set('id', $id); + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : ''); + $html->set('mapsjs', $mapsjs); + $html->pack('main'); + + $mcache->set('server_maps_'.$id, $html->arr['main'], false, 3); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/maps/delete.php b/system/sections/servers/csgo/maps/delete.php new file mode 100644 index 0000000..0cbf4ec --- /dev/null +++ b/system/sections/servers/csgo/maps/delete.php @@ -0,0 +1,70 @@ +query('SELECT `unit`, `tarif`, `map_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/csgo/'; + + // Генерация списка карт + $ssh->set('cd '.$dir.'maps/ && ls | grep -iE "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $name => $sel) + if($sel) + { + $map = str_replace(array("\\", "'", "'", '-_-'), array('', '', '', '$'), $name); + + // Проверка наличия карты + if(!in_array($map, $aMaps)) + continue; + + // Проверка: является ли карта стартовой + if($server['map_start'] == $map) + continue; + + $ssh->set('cd /path/maps/'.$server['game'].'/'.sys::map($map).' && du -a | grep -iE "\.[a-z]{1,3}$" | awk \'{print $2}\''); + + $aFiles = explode("\n", str_replace('./', '', $ssh->get())); + + if(isset($aFiles[count($aFiles)-1]) AND $aFiles[count($aFiles)-1] == '') + unset($aFiles[count($aFiles)-1]); + + $files = ''; + + foreach($aFiles as $file) + $files .= $dir.$file.' '; + + $rm = ''; + $aFlrm = explode(' ', $dir.'maps/'.$map.'.* '.trim($files)); + + foreach($aFlrm as $flrm) + $rm .= sys::map($flrm).' '; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS md'.$start_point.$id.' sh -c \'rm '.trim($rm).'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/csgo/maps/install.php b/system/sections/servers/csgo/maps/install.php new file mode 100644 index 0000000..7aae0c8 --- /dev/null +++ b/system/sections/servers/csgo/maps/install.php @@ -0,0 +1,56 @@ +query('SELECT `unit`, `tarif`, `hdd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/csgo/'; + + // Проверить наличие свободного места + $ssh->set('cd '.$dir.' && du -ms'); + $hdd = ceil(sys::int($ssh->get())/($server['hdd']/100)); + $hdd = $hdd > 100 ? 100 : $hdd; + + if($hdd == 100) + sys::outjs(array('e' => 'Невозможно выполнить установку, нет свободного места'), $nmch); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $mid => $sel) + if($sel) + { + $map = sys::int($mid); + + // Проверка наличия карты + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `id`="'.$map.'" AND `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $map = $sql->get(); + + $cp = 'cp /path/maps/'.$server['game'].'/'.sys::map($map['name']).'.* '.$dir.'maps/;' + .'cd /path/maps/'.$server['game'].'/'.sys::map($map['name']).'/ && cp -r * '.$dir; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS mc'.$start_point.$id.' sh -c \''.$cp.'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/csgo/maps/list.php b/system/sections/servers/csgo/maps/list.php new file mode 100644 index 0000000..abb251a --- /dev/null +++ b/system/sections/servers/csgo/maps/list.php @@ -0,0 +1,62 @@ +nav('Установка карт'); + + // Категории для быстрой сортировки + $html->get('types', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->pack('types'); + + $type = false; + + if(isset($url['type']) AND in_array($url['type'], array('de', 'cs', 'aim', 'awp', 'bhop', 'csde', 'deathrun', 'jail'))) + $type = '^'.$url['type'].'\_'; + + if($type) + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode($type).'\') ORDER BY `name` ASC LIMIT 72'); + else{ + $sql->query('SELECT `id` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'"'); + + // Массив для построения страниц + $aPage = sys::page($page, $sql->num(), 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'servers/id/'.$id.'/section/maps/subsection/list'); + + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `name` ASC LIMIT '.$aPage['num'].', 30'); + } + + $mapsjs = ''; + $i = 0; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs .= $i.' : "'.$map['id'].'",'; + + $html->get('map_install', 'sections/servers/games/maps'); + + $html->set('id', $map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', $map['name']); + + $html->pack('maps'); + } + + $html->get('install', 'sections/servers/games/maps'); + + $html->set('id', $id); + + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : 'К сожалению карты не найдены в базе'); + $html->set('amaps', $mapsjs); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->set('cdn', $cfg['cdn']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/maps/listing.php b/system/sections/servers/csgo/maps/listing.php new file mode 100644 index 0000000..664ea1e --- /dev/null +++ b/system/sections/servers/csgo/maps/listing.php @@ -0,0 +1,94 @@ +nav('Списки карт'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/maps'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория сервера + $dir = $tarif['install'].$server['uid'].'/csgo/'; + + // Генерация списка + if($go AND isset($url['gen'])) + { + $ssh->set('cd '.$dir.'maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\''); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace(array('./', '.bsp'), '', $maps)); + + sort($aMaps); + reset($aMaps); + + $list = ''; + + foreach($aMaps as $index => $map) + { + $aMap = explode('/', $map); + $name = end($aMap); + if(strlen($name) < 4) + continue; + + $list .= $map."\n"; + } + + sys::outjs(array('s' => $list), $nmch); + } + + $aFiles = array( + 'mapcycle' => 'mapcycle.txt', + 'maps' => 'maplist.txt' + ); + + // Сохранение + if($go AND isset($url['file'])) + { + if(!array_key_exists($url['file'], $aFiles)) + exit; + + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $dir.$aFiles[$url['file']], 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$dir.$aFiles[$url['file']]); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['mapcycle'].'; cat '.$dir.$aFiles['mapcycle'].'"'); + $mapcycle = $ssh->get(); + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['maps'].'; cat '.$dir.$aFiles['maps'].'"'); + $maps = $ssh->get(); + + $html->get('listing', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->set('mapcycle', $mapcycle); + $html->set('maps', $maps); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/maps/search.php b/system/sections/servers/csgo/maps/search.php new file mode 100644 index 0000000..866ca47 --- /dev/null +++ b/system/sections/servers/csgo/maps/search.php @@ -0,0 +1,64 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + // Поиск по картам + if($text{0} == '^') + { + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode(str_replace('_', '\_', $text).'').'\') ORDER BY `name` ASC LIMIT 12'); + $text = substr($text, 1); + }else + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') ORDER BY `name` ASC LIMIT 12'); + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $i = 0; + $mapsjs = ''; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs[$i] = 's'.$map['id']; + + $html->get('map_search', 'sections/servers/games/maps'); + + $html->set('id', 's'.$map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', sys::find($map['name'], $text)); + + $html->pack('maps'); + } + + $mcache->set($mkey, array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs), false, 15); + + sys::outjs(array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs)); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/owners.php b/system/sections/servers/csgo/owners.php new file mode 100644 index 0000000..71a5157 --- /dev/null +++ b/system/sections/servers/csgo/owners.php @@ -0,0 +1,172 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'change' => 'Смена карты', + 'reinstall' => 'Переустановка', + 'update' => 'Обновление', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"', + 'maps' => 'Раздел "Карты"' + ); + + $aAccess = array('start', 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/plugins.php b/system/sections/servers/csgo/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/csgo/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/rcon.php b/system/sections/servers/csgo/rcon.php new file mode 100644 index 0000000..1a0de70 --- /dev/null +++ b/system/sections/servers/csgo/rcon.php @@ -0,0 +1,54 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings.php b/system/sections/servers/csgo/settings.php new file mode 100644 index 0000000..b775147 --- /dev/null +++ b/system/sections/servers/csgo/settings.php @@ -0,0 +1,77 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file', 'antiddos', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/admins.php b/system/sections/servers/csgo/settings/admins.php new file mode 100644 index 0000000..a60bca1 --- /dev/null +++ b/system/sections/servers/csgo/settings/admins.php @@ -0,0 +1,114 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$id.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/csgo/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/csgo/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/bans.php b/system/sections/servers/csgo/settings/bans.php new file mode 100644 index 0000000..e715728 --- /dev/null +++ b/system/sections/servers/csgo/settings/bans.php @@ -0,0 +1,160 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = $tarif['install'].$server['uid'].'/csgo'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'steamid3') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | egrep "^\[U:[01]:[0-9]{3,12}\]$"'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/debug.php b/system/sections/servers/csgo/settings/debug.php new file mode 100644 index 0000000..180f9d0 --- /dev/null +++ b/system/sections/servers/csgo/settings/debug.php @@ -0,0 +1,28 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Чтение файла - oldstart.log + $file = $tarif['install'].$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/logs.php b/system/sections/servers/csgo/settings/logs.php new file mode 100644 index 0000000..6f3acd2 --- /dev/null +++ b/system/sections/servers/csgo/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/csgo/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/server.php b/system/sections/servers/csgo/settings/server.php new file mode 100644 index 0000000..62faef8 --- /dev/null +++ b/system/sections/servers/csgo/settings/server.php @@ -0,0 +1,117 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/csgo/cfg/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/csgo/cfg/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/smlogs.php b/system/sections/servers/csgo/settings/smlogs.php new file mode 100644 index 0000000..784e3a8 --- /dev/null +++ b/system/sections/servers/csgo/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/csgo/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/settings/start.php b/system/sections/servers/csgo/settings/start.php new file mode 100644 index 0000000..ea9406b --- /dev/null +++ b/system/sections/servers/csgo/settings/start.php @@ -0,0 +1,169 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate`, `pingboost` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/csgo/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/csgo/maps', $map, true, $nmch); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'mod': + if(in_array($value, array(1, 2, 3, 4, 5))) + $sql->query('UPDATE `servers` set `pingboost`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['tickrate']))) + $sql->query('UPDATE `servers` set `tickrate`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/csgo /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/csgo/cfg/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/csgo/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + if(!tarif::price($tarif['price'])) + { + $aTick = explode(':', $tarif['tickrate']); + + unset($aTick[array_search($server['tickrate'], $aTick)]); + + if(count($aTick)) + foreach($aTick as $value) + $tickrate .= ''; + } + + // Игровой режим + $mods = '' + .'' + .'' + .'' + .''; + + if(!$server['pingboost']) + $server['pingboost'] = 2; + + $mod = str_replace('value="'.$server['pingboost'], 'value="'.$server['pingboost'].'" selected="select', $mods); + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('mod', $mod); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if(!tarif::price($tarif['price'])) + { + $html->unit('tickrate', true); + $html->set('tickrate', $tickrate); + }else + $html->unit('tickrate'); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/tarif.php b/system/sections/servers/csgo/tarif.php new file mode 100644 index 0000000..30cc896 --- /dev/null +++ b/system/sections/servers/csgo/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `tickrate`, `ram`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/tarif/extend.php b/system/sections/servers/csgo/tarif/extend.php new file mode 100644 index 0000000..9d060bc --- /dev/null +++ b/system/sections/servers/csgo/tarif/extend.php @@ -0,0 +1,51 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['tickrate'] = $server['tickrate']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($server['tickrate'], explode(':', $tarif['tickrate']))]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/tarif/plan.php b/system/sections/servers/csgo/tarif/plan.php new file mode 100644 index 0000000..3eed81c --- /dev/null +++ b/system/sections/servers/csgo/tarif/plan.php @@ -0,0 +1,66 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + // Проверка плана + if(array_search($plan, $aTICK) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + if($plan == $server['tickrate']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aTICK)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + sys::benefitblock($id, $nmch); + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `tickrate`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/tarif/slots.php b/system/sections/servers/csgo/tarif/slots.php new file mode 100644 index 0000000..e457286 --- /dev/null +++ b/system/sections/servers/csgo/tarif/slots.php @@ -0,0 +1,34 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($server['tickrate'], $aTICK)]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/tarif/unit.php b/system/sections/servers/csgo/tarif/unit.php new file mode 100644 index 0000000..b840bc7 --- /dev/null +++ b/system/sections/servers/csgo/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aTICKold = explode(':', $oldTarif['tickrate']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + if(!in_array($server['tickrate'], $aTICK)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['tickrate'], $aTICKold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/csgo/web.php b/system/sections/servers/csgo/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/csgo/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/console.php b/system/sections/servers/css/console.php new file mode 100644 index 0000000..f31d841 --- /dev/null +++ b/system/sections/servers/css/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/copy.php b/system/sections/servers/css/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/css/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/graph.php b/system/sections/servers/css/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/css/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/index.php b/system/sections/servers/css/index.php new file mode 100644 index 0000000..098c6c5 --- /dev/null +++ b/system/sections/servers/css/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `tickrate`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['tickrate'].' TickRate'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/maps.php b/system/sections/servers/css/maps.php new file mode 100644 index 0000000..6e04160 --- /dev/null +++ b/system/sections/servers/css/maps.php @@ -0,0 +1,86 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'list', 'listing', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Карты', $cfg['http'].'servers/id/'.$id.'/section/maps'); + + $nmch = sys::rep_act('server_maps_go_'.$id, 10); + + include(SEC.'servers/'.$server['game'].'/maps/'.$url['subsection'].'.php'); + }else{ + $html->nav('Карты'); + + // Построение списка установленных карт + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Сортировка карт + sort($aMaps); + reset($aMaps); + + $mapsjs = ''; + $i = 0; + + foreach($aMaps as $index => $map) + { + if(!isset($map{3})) + continue; + + $mapjs = str_replace('$', '-_-', $map); + + $i+=1; + $mapsjs .= $i.' : "'.$mapjs.'",'; + + $html->get('map_server', 'sections/servers/games/maps'); + $html->set('img', sys::img($map, $server['game'])); + $html->set('map', $mapjs); + $html->set('name', $map); + $html->pack('maps'); + } + + // Если есть кеш + if($mcache->get('server_maps_'.$id) != '') + $html->arr['main'] = $mcache->get('server_maps_'.$id); + else{ + $html->get('maps', 'sections/servers/games'); + $html->set('id', $id); + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : ''); + $html->set('mapsjs', $mapsjs); + $html->pack('main'); + + $mcache->set('server_maps_'.$id, $html->arr['main'], false, 3); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/maps/delete.php b/system/sections/servers/css/maps/delete.php new file mode 100644 index 0000000..7b0173a --- /dev/null +++ b/system/sections/servers/css/maps/delete.php @@ -0,0 +1,70 @@ +query('SELECT `unit`, `tarif`, `map_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка карт + $ssh->set('cd '.$dir.'maps/ && ls | grep -iE "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $name => $sel) + if($sel) + { + $map = str_replace(array("\\", "'", "'", '-_-'), array('', '', '', '$'), $name); + + // Проверка наличия карты + if(!in_array($map, $aMaps)) + continue; + + // Проверка: является ли карта стартовой + if($server['map_start'] == $map) + continue; + + $ssh->set('cd /path/maps/'.$server['game'].'/'.sys::map($map).' && du -a | grep -iE "\.[a-z]{1,3}$" | awk \'{print $2}\''); + + $aFiles = explode("\n", str_replace('./', '', $ssh->get())); + + if(isset($aFiles[count($aFiles)-1]) AND $aFiles[count($aFiles)-1] == '') + unset($aFiles[count($aFiles)-1]); + + $files = ''; + + foreach($aFiles as $file) + $files .= $dir.$file.' '; + + $rm = ''; + $aFlrm = explode(' ', $dir.'maps/'.$map.'.* '.trim($files)); + + foreach($aFlrm as $flrm) + $rm .= sys::map($flrm).' '; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS md'.$start_point.$id.' sh -c \'rm '.trim($rm).'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/css/maps/install.php b/system/sections/servers/css/maps/install.php new file mode 100644 index 0000000..b54e0fd --- /dev/null +++ b/system/sections/servers/css/maps/install.php @@ -0,0 +1,56 @@ +query('SELECT `unit`, `tarif`, `hdd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Проверить наличие свободного места + $ssh->set('cd '.$dir.' && du -ms'); + $hdd = ceil(sys::int($ssh->get())/($server['hdd']/100)); + $hdd = $hdd > 100 ? 100 : $hdd; + + if($hdd == 100) + sys::outjs(array('e' => 'Невозможно выполнить установку, нет свободного места'), $nmch); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $mid => $sel) + if($sel) + { + $map = sys::int($mid); + + // Проверка наличия карты + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `id`="'.$map.'" AND `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $map = $sql->get(); + + $cp = 'cp /path/maps/'.$server['game'].'/'.sys::map($map['name']).'.* '.$dir.'maps/;' + .'cd /path/maps/'.$server['game'].'/'.sys::map($map['name']).'/ && cp -r * '.$dir; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS mc'.$start_point.$id.' sh -c \''.$cp.'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/css/maps/list.php b/system/sections/servers/css/maps/list.php new file mode 100644 index 0000000..abb251a --- /dev/null +++ b/system/sections/servers/css/maps/list.php @@ -0,0 +1,62 @@ +nav('Установка карт'); + + // Категории для быстрой сортировки + $html->get('types', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->pack('types'); + + $type = false; + + if(isset($url['type']) AND in_array($url['type'], array('de', 'cs', 'aim', 'awp', 'bhop', 'csde', 'deathrun', 'jail'))) + $type = '^'.$url['type'].'\_'; + + if($type) + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode($type).'\') ORDER BY `name` ASC LIMIT 72'); + else{ + $sql->query('SELECT `id` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'"'); + + // Массив для построения страниц + $aPage = sys::page($page, $sql->num(), 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'servers/id/'.$id.'/section/maps/subsection/list'); + + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `name` ASC LIMIT '.$aPage['num'].', 30'); + } + + $mapsjs = ''; + $i = 0; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs .= $i.' : "'.$map['id'].'",'; + + $html->get('map_install', 'sections/servers/games/maps'); + + $html->set('id', $map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', $map['name']); + + $html->pack('maps'); + } + + $html->get('install', 'sections/servers/games/maps'); + + $html->set('id', $id); + + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : 'К сожалению карты не найдены в базе'); + $html->set('amaps', $mapsjs); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->set('cdn', $cfg['cdn']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/maps/listing.php b/system/sections/servers/css/maps/listing.php new file mode 100644 index 0000000..f47dcc0 --- /dev/null +++ b/system/sections/servers/css/maps/listing.php @@ -0,0 +1,94 @@ +nav('Списки карт'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/maps'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория сервера + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка + if($go AND isset($url['gen'])) + { + $ssh->set('cd '.$dir.'maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace(array('./', '.bsp'), '', $maps)); + + sort($aMaps); + reset($aMaps); + + $list = ''; + + foreach($aMaps as $index => $map) + { + $aMap = explode('/', $map); + $name = end($aMap); + if(strlen($name) < 4) + continue; + + $list .= $map."\n"; + } + + sys::outjs(array('s' => $list), $nmch); + } + + $aFiles = array( + 'mapcycle' => 'mapcycle.txt', + 'maps' => 'maplist.txt' + ); + + // Сохранение + if($go AND isset($url['file'])) + { + if(!array_key_exists($url['file'], $aFiles)) + exit; + + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $dir.$aFiles[$url['file']], 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$dir.$aFiles[$url['file']]); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['mapcycle'].'; cat '.$dir.$aFiles['mapcycle'].'"'); + $mapcycle = $ssh->get(); + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['maps'].'; cat '.$dir.$aFiles['maps'].'"'); + $maps = $ssh->get(); + + $html->get('listing', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->set('mapcycle', $mapcycle); + $html->set('maps', $maps); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/maps/search.php b/system/sections/servers/css/maps/search.php new file mode 100644 index 0000000..866ca47 --- /dev/null +++ b/system/sections/servers/css/maps/search.php @@ -0,0 +1,64 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + // Поиск по картам + if($text{0} == '^') + { + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode(str_replace('_', '\_', $text).'').'\') ORDER BY `name` ASC LIMIT 12'); + $text = substr($text, 1); + }else + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') ORDER BY `name` ASC LIMIT 12'); + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $i = 0; + $mapsjs = ''; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs[$i] = 's'.$map['id']; + + $html->get('map_search', 'sections/servers/games/maps'); + + $html->set('id', 's'.$map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', sys::find($map['name'], $text)); + + $html->pack('maps'); + } + + $mcache->set($mkey, array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs), false, 15); + + sys::outjs(array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs)); +?> \ No newline at end of file diff --git a/system/sections/servers/css/owners.php b/system/sections/servers/css/owners.php new file mode 100644 index 0000000..71a5157 --- /dev/null +++ b/system/sections/servers/css/owners.php @@ -0,0 +1,172 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'change' => 'Смена карты', + 'reinstall' => 'Переустановка', + 'update' => 'Обновление', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"', + 'maps' => 'Раздел "Карты"' + ); + + $aAccess = array('start', 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/plugins.php b/system/sections/servers/css/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/css/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/rcon.php b/system/sections/servers/css/rcon.php new file mode 100644 index 0000000..1a0de70 --- /dev/null +++ b/system/sections/servers/css/rcon.php @@ -0,0 +1,54 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings.php b/system/sections/servers/css/settings.php new file mode 100644 index 0000000..b775147 --- /dev/null +++ b/system/sections/servers/css/settings.php @@ -0,0 +1,77 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file', 'antiddos', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/admins.php b/system/sections/servers/css/settings/admins.php new file mode 100644 index 0000000..f8ad37e --- /dev/null +++ b/system/sections/servers/css/settings/admins.php @@ -0,0 +1,114 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$id.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/antiddos.php b/system/sections/servers/css/settings/antiddos.php new file mode 100644 index 0000000..6451e5d --- /dev/null +++ b/system/sections/servers/css/settings/antiddos.php @@ -0,0 +1,73 @@ +query('SELECT `id` FROM `units` WHERE `id`="'.$server['unit'].'" AND `ddos`="1" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'В данный момент нельзя изменить параметр, т.к. включена защита на всю локацию.'), $name_mcache); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($url['type']) || !in_array($url['type'], array('0', '1', '2'))) + sys::outjs(array('e' => 'Неправильно передан параметр.'), $name_mcache); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh', $user['group'])), $name_mcache); + + list($ip, $port) = explode(':', $server['address']); + + $geo = $cfg['iptables'].'_geo'; + + if($url['type'] == 2) + { + if($server['ddos'] == 2) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="2" WHERE `id`="'.$id.'" LIMIT 1'); + }elseif($url['type'] == 1){ + if($server['ddos'] == 1) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="1" WHERE `id`="'.$id.'" LIMIT 1'); + }else{ + if(!$server['ddos']) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $country = $server['ddos'] == 2 ? 'AM,BY,UA,RU,KZ' : 'UA,RU'; + + $ssh->set('iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country '.$country.' -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'); + + $sql->query('UPDATE `servers` set `ddos`="0" WHERE `id`="'.$id.'" LIMIT 1'); + } + + $mcache->delete('server_settings_'.$id); + + sys::outjs(array('s' => 'ok'), $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/bans.php b/system/sections/servers/css/settings/bans.php new file mode 100644 index 0000000..eeef061 --- /dev/null +++ b/system/sections/servers/css/settings/bans.php @@ -0,0 +1,160 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = $tarif['install'].$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'steamid3') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | egrep "^\[U:[01]:[0-9]{3,12}\]$"'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/debug.php b/system/sections/servers/css/settings/debug.php new file mode 100644 index 0000000..180f9d0 --- /dev/null +++ b/system/sections/servers/css/settings/debug.php @@ -0,0 +1,28 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Чтение файла - oldstart.log + $file = $tarif['install'].$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/logs.php b/system/sections/servers/css/settings/logs.php new file mode 100644 index 0000000..1aa0914 --- /dev/null +++ b/system/sections/servers/css/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/server.php b/system/sections/servers/css/settings/server.php new file mode 100644 index 0000000..b6a4696 --- /dev/null +++ b/system/sections/servers/css/settings/server.php @@ -0,0 +1,117 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/smlogs.php b/system/sections/servers/css/settings/smlogs.php new file mode 100644 index 0000000..b39aa81 --- /dev/null +++ b/system/sections/servers/css/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/css/settings/start.php b/system/sections/servers/css/settings/start.php new file mode 100644 index 0000000..dc83025 --- /dev/null +++ b/system/sections/servers/css/settings/start.php @@ -0,0 +1,149 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $map, true, $nmch); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['tickrate']))) + $sql->query('UPDATE `servers` set `tickrate`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $tickrate = ''; + + if(!tarif::price($tarif['price'])) + { + $aTick = explode(':', $tarif['tickrate']); + + unset($aTick[array_search($server['tickrate'], $aTick)]); + + if(count($aTick)) + foreach($aTick as $value) + $tickrate .= ''; + } + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if(!tarif::price($tarif['price'])) + { + $html->unit('tickrate', true); + $html->set('tickrate', $tickrate); + }else + $html->unit('tickrate'); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/tarif.php b/system/sections/servers/css/tarif.php new file mode 100644 index 0000000..30cc896 --- /dev/null +++ b/system/sections/servers/css/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `tickrate`, `ram`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/tarif/extend.php b/system/sections/servers/css/tarif/extend.php new file mode 100644 index 0000000..9d060bc --- /dev/null +++ b/system/sections/servers/css/tarif/extend.php @@ -0,0 +1,51 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['tickrate'] = $server['tickrate']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($server['tickrate'], explode(':', $tarif['tickrate']))]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/tarif/plan.php b/system/sections/servers/css/tarif/plan.php new file mode 100644 index 0000000..3eed81c --- /dev/null +++ b/system/sections/servers/css/tarif/plan.php @@ -0,0 +1,66 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + // Проверка плана + if(array_search($plan, $aTICK) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + if($plan == $server['tickrate']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aTICK)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + sys::benefitblock($id, $nmch); + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `tickrate`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/css/tarif/slots.php b/system/sections/servers/css/tarif/slots.php new file mode 100644 index 0000000..e457286 --- /dev/null +++ b/system/sections/servers/css/tarif/slots.php @@ -0,0 +1,34 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($server['tickrate'], $aTICK)]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/tarif/unit.php b/system/sections/servers/css/tarif/unit.php new file mode 100644 index 0000000..b840bc7 --- /dev/null +++ b/system/sections/servers/css/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aTICKold = explode(':', $oldTarif['tickrate']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + if(!in_array($server['tickrate'], $aTICK)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['tickrate'], $aTICKold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/css/web.php b/system/sections/servers/css/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/css/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/console.php b/system/sections/servers/cssold/console.php new file mode 100644 index 0000000..f31d841 --- /dev/null +++ b/system/sections/servers/cssold/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/copy.php b/system/sections/servers/cssold/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/cssold/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/graph.php b/system/sections/servers/cssold/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/cssold/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/index.php b/system/sections/servers/cssold/index.php new file mode 100644 index 0000000..89f90ad --- /dev/null +++ b/system/sections/servers/cssold/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `fps`, `tickrate`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['fps'].' FPS / '.$server['tickrate'].' TickRate'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/maps.php b/system/sections/servers/cssold/maps.php new file mode 100644 index 0000000..6e04160 --- /dev/null +++ b/system/sections/servers/cssold/maps.php @@ -0,0 +1,86 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'list', 'listing', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Карты', $cfg['http'].'servers/id/'.$id.'/section/maps'); + + $nmch = sys::rep_act('server_maps_go_'.$id, 10); + + include(SEC.'servers/'.$server['game'].'/maps/'.$url['subsection'].'.php'); + }else{ + $html->nav('Карты'); + + // Построение списка установленных карт + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $ssh->set('cd '.$tarif['install'].$server['uid'].'/cstrike/maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Сортировка карт + sort($aMaps); + reset($aMaps); + + $mapsjs = ''; + $i = 0; + + foreach($aMaps as $index => $map) + { + if(!isset($map{3})) + continue; + + $mapjs = str_replace('$', '-_-', $map); + + $i+=1; + $mapsjs .= $i.' : "'.$mapjs.'",'; + + $html->get('map_server', 'sections/servers/games/maps'); + $html->set('img', sys::img($map, $server['game'])); + $html->set('map', $mapjs); + $html->set('name', $map); + $html->pack('maps'); + } + + // Если есть кеш + if($mcache->get('server_maps_'.$id) != '') + $html->arr['main'] = $mcache->get('server_maps_'.$id); + else{ + $html->get('maps', 'sections/servers/games'); + $html->set('id', $id); + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : ''); + $html->set('mapsjs', $mapsjs); + $html->pack('main'); + + $mcache->set('server_maps_'.$id, $html->arr['main'], false, 3); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/maps/delete.php b/system/sections/servers/cssold/maps/delete.php new file mode 100644 index 0000000..7b0173a --- /dev/null +++ b/system/sections/servers/cssold/maps/delete.php @@ -0,0 +1,70 @@ +query('SELECT `unit`, `tarif`, `map_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка карт + $ssh->set('cd '.$dir.'maps/ && ls | grep -iE "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace('.bsp', '', $maps)); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $name => $sel) + if($sel) + { + $map = str_replace(array("\\", "'", "'", '-_-'), array('', '', '', '$'), $name); + + // Проверка наличия карты + if(!in_array($map, $aMaps)) + continue; + + // Проверка: является ли карта стартовой + if($server['map_start'] == $map) + continue; + + $ssh->set('cd /path/maps/'.$server['game'].'/'.sys::map($map).' && du -a | grep -iE "\.[a-z]{1,3}$" | awk \'{print $2}\''); + + $aFiles = explode("\n", str_replace('./', '', $ssh->get())); + + if(isset($aFiles[count($aFiles)-1]) AND $aFiles[count($aFiles)-1] == '') + unset($aFiles[count($aFiles)-1]); + + $files = ''; + + foreach($aFiles as $file) + $files .= $dir.$file.' '; + + $rm = ''; + $aFlrm = explode(' ', $dir.'maps/'.$map.'.* '.trim($files)); + + foreach($aFlrm as $flrm) + $rm .= sys::map($flrm).' '; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS md'.$start_point.$id.' sh -c \'rm '.trim($rm).'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/cssold/maps/install.php b/system/sections/servers/cssold/maps/install.php new file mode 100644 index 0000000..b54e0fd --- /dev/null +++ b/system/sections/servers/cssold/maps/install.php @@ -0,0 +1,56 @@ +query('SELECT `unit`, `tarif`, `hdd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Проверить наличие свободного места + $ssh->set('cd '.$dir.' && du -ms'); + $hdd = ceil(sys::int($ssh->get())/($server['hdd']/100)); + $hdd = $hdd > 100 ? 100 : $hdd; + + if($hdd == 100) + sys::outjs(array('e' => 'Невозможно выполнить установку, нет свободного места'), $nmch); + + // Массив переданных карт + $in_aMaps = isset($_POST['maps']) ? $_POST['maps'] : array(); + + // Обработка выборки + foreach($in_aMaps as $mid => $sel) + if($sel) + { + $map = sys::int($mid); + + // Проверка наличия карты + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `id`="'.$map.'" AND `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $map = $sql->get(); + + $cp = 'cp /path/maps/'.$server['game'].'/'.sys::map($map['name']).'.* '.$dir.'maps/;' + .'cd /path/maps/'.$server['game'].'/'.sys::map($map['name']).'/ && cp -r * '.$dir; + + $ssh->set('sudo -u server'.$server['uid'].' screen -dmS mc'.$start_point.$id.' sh -c \''.$cp.'\''); + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> diff --git a/system/sections/servers/cssold/maps/list.php b/system/sections/servers/cssold/maps/list.php new file mode 100644 index 0000000..abb251a --- /dev/null +++ b/system/sections/servers/cssold/maps/list.php @@ -0,0 +1,62 @@ +nav('Установка карт'); + + // Категории для быстрой сортировки + $html->get('types', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->pack('types'); + + $type = false; + + if(isset($url['type']) AND in_array($url['type'], array('de', 'cs', 'aim', 'awp', 'bhop', 'csde', 'deathrun', 'jail'))) + $type = '^'.$url['type'].'\_'; + + if($type) + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode($type).'\') ORDER BY `name` ASC LIMIT 72'); + else{ + $sql->query('SELECT `id` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'"'); + + // Массив для построения страниц + $aPage = sys::page($page, $sql->num(), 30); + + // Генерация массива ($html->arr['pages']) страниц + sys::page_gen($aPage['ceil'], $page, $aPage['page'], 'servers/id/'.$id.'/section/maps/subsection/list'); + + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `name` ASC LIMIT '.$aPage['num'].', 30'); + } + + $mapsjs = ''; + $i = 0; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs .= $i.' : "'.$map['id'].'",'; + + $html->get('map_install', 'sections/servers/games/maps'); + + $html->set('id', $map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', $map['name']); + + $html->pack('maps'); + } + + $html->get('install', 'sections/servers/games/maps'); + + $html->set('id', $id); + + $html->set('types', isset($html->arr['types']) ? $html->arr['types'] : ''); + $html->set('maps', isset($html->arr['maps']) ? $html->arr['maps'] : 'К сожалению карты не найдены в базе'); + $html->set('amaps', $mapsjs); + $html->set('pages', isset($html->arr['pages']) ? $html->arr['pages'] : ''); + $html->set('cdn', $cfg['cdn']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/maps/listing.php b/system/sections/servers/cssold/maps/listing.php new file mode 100644 index 0000000..f47dcc0 --- /dev/null +++ b/system/sections/servers/cssold/maps/listing.php @@ -0,0 +1,94 @@ +nav('Списки карт'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/maps'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория сервера + $dir = $tarif['install'].$server['uid'].'/cstrike/'; + + // Генерация списка + if($go AND isset($url['gen'])) + { + $ssh->set('cd '.$dir.'maps/ && ls | grep -e "\.bsp$"'); + + $maps = $ssh->get(); + + $aMaps = explode("\n", str_ireplace(array('./', '.bsp'), '', $maps)); + + sort($aMaps); + reset($aMaps); + + $list = ''; + + foreach($aMaps as $index => $map) + { + $aMap = explode('/', $map); + $name = end($aMap); + if(strlen($name) < 4) + continue; + + $list .= $map."\n"; + } + + sys::outjs(array('s' => $list), $nmch); + } + + $aFiles = array( + 'mapcycle' => 'mapcycle.txt', + 'maps' => 'maplist.txt' + ); + + // Сохранение + if($go AND isset($url['file'])) + { + if(!array_key_exists($url['file'], $aFiles)) + exit; + + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $dir.$aFiles[$url['file']], 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$dir.$aFiles[$url['file']]); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['mapcycle'].'; cat '.$dir.$aFiles['mapcycle'].'"'); + $mapcycle = $ssh->get(); + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$dir.$aFiles['maps'].'; cat '.$dir.$aFiles['maps'].'"'); + $maps = $ssh->get(); + + $html->get('listing', 'sections/servers/'.$server['game'].'/maps'); + + $html->set('id', $id); + + $html->set('mapcycle', $mapcycle); + $html->set('maps', $maps); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/maps/search.php b/system/sections/servers/cssold/maps/search.php new file mode 100644 index 0000000..866ca47 --- /dev/null +++ b/system/sections/servers/cssold/maps/search.php @@ -0,0 +1,64 @@ +get($mkey); + + if(is_array($cache)) + { + if($go) + sys::outjs($cache, $nmch); + + sys::outjs($cache); + } + + if(!isset($text{2})) + { + if($go) + sys::outjs(array('e' => 'Для выполнения поиска, необходимо больше данных'), $nmch); + + sys::outjs(array('e' => '')); + } + + // Поиск по картам + if($text{0} == '^') + { + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` REGEXP FROM_BASE64(\''.base64_encode(str_replace('_', '\_', $text).'').'\') ORDER BY `name` ASC LIMIT 12'); + $text = substr($text, 1); + }else + $sql->query('SELECT `id`, `name` FROM `maps` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.str_replace('_', '\_', $text).'%').'\') ORDER BY `name` ASC LIMIT 12'); + + if(!$sql->num()) + { + if($go) + sys::outjs(array('e' => 'По вашему запросу ничего не найдено'), $nmch); + + sys::outjs(array('e' => 'По вашему запросу ничего не найдено')); + } + + $i = 0; + $mapsjs = ''; + + while($map = $sql->get()) + { + $i+=1; + + $mapsjs[$i] = 's'.$map['id']; + + $html->get('map_search', 'sections/servers/games/maps'); + + $html->set('id', 's'.$map['id']); + $html->set('img', sys::img($map['name'], $server['game'])); + $html->set('name', sys::find($map['name'], $text)); + + $html->pack('maps'); + } + + $mcache->set($mkey, array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs), false, 15); + + sys::outjs(array('maps' => $html->arr['maps'], 'mapsjs' => $mapsjs)); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/owners.php b/system/sections/servers/cssold/owners.php new file mode 100644 index 0000000..71a5157 --- /dev/null +++ b/system/sections/servers/cssold/owners.php @@ -0,0 +1,172 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'change' => 'Смена карты', + 'reinstall' => 'Переустановка', + 'update' => 'Обновление', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"', + 'maps' => 'Раздел "Карты"' + ); + + $aAccess = array('start', 'stop', 'restart', 'change', 'reinstall', 'update', 'console', 'settings', 'plugins', 'maps'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/plugins.php b/system/sections/servers/cssold/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/cssold/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/rcon.php b/system/sections/servers/cssold/rcon.php new file mode 100644 index 0000000..1a0de70 --- /dev/null +++ b/system/sections/servers/cssold/rcon.php @@ -0,0 +1,54 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings.php b/system/sections/servers/cssold/settings.php new file mode 100644 index 0000000..6ffcbee --- /dev/null +++ b/system/sections/servers/cssold/settings.php @@ -0,0 +1,77 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack`, `ddos` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'admins', 'bans', 'firewall', 'crontab', 'startlogs', 'debug', 'logs', 'smlogs', 'pack', 'file', 'antiddos', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + $antiddos = '' + .'' + .''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('antiddos', str_replace($server['ddos'], $server['ddos'].'" selected="select', $antiddos)); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/admins.php b/system/sections/servers/cssold/settings/admins.php new file mode 100644 index 0000000..f8ad37e --- /dev/null +++ b/system/sections/servers/cssold/settings/admins.php @@ -0,0 +1,114 @@ +nav('Управление администраторами'); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $aData = array(); + + $aData['active'] = isset($_POST['active']) ? $_POST['active'] : ''; + $aData['value'] = isset($_POST['value']) ? $_POST['value'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['flags'] = isset($_POST['flags']) ? $_POST['flags'] : ''; + $aData['immunity'] = isset($_POST['immunity']) ? sys::int($_POST['immunity']) : ''; + $aData['time'] = isset($_POST['time']) ? $_POST['time'] : ''; + $aData['info'] = isset($_POST['info']) ? $_POST['info'] : ''; + + // Удаление текущих записей + $sql->query('DELETE FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'"'); + + $usini = ''; + + foreach($aData['value'] as $index => $val) + { + if($val != '') + { + $aDate = isset($aData['time'][$index]) ? explode('.', $aData['time'][$index]) : explode('.', date('d.m.Y', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + $aDate = explode('.', date('d.m.Y', $start_point)); + + $time = mktime(0, 0, 0, $aDate[1], $aDate[0], $aDate[2]); + + $aData['active'][$index] = isset($aData['active'][$index]) ? 1 : 0; + $aData['passwd'][$index] = isset($aData['passwd'][$index]) ? $aData['passwd'][$index] : ''; + $aData['flags'][$index] = isset($aData['flags'][$index]) ? $aData['flags'][$index] : ''; + $aData['info'][$index] = isset($aData['info'][$index]) ? $aData['info'][$index] : ''; + + $text = '"'.$val.'" "'.$aData['immunity'][$index].':'.$aData['flags'][$index].'" "'.$aData['passwd'][$index].'"'; + + $sql->query('INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$id.'",' + .'`value`="'.htmlspecialchars($val).'",' + .'`active`="'.$aData['active'][$index].'",' + .'`passwd`="'.htmlspecialchars($aData['passwd'][$index]).'",' + .'`flags`="'.htmlspecialchars($aData['flags'][$index]).'",' + .'`immunity`="'.$aData['immunity'][$index].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="'.htmlspecialchars($aData['info'][$index]).'"'); + + if($aData['active'][$index]) + $usini .= $text.PHP_EOL; + } + } + + $temp = sys::temp($usini); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini', 0644); + + unlink($temp); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/configs/admins_simple.ini'); + + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \" sm_reloadadmins\"\015'"); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Построение списка добавленных админов + $sql->query('SELECT `id`, `value`, `active`, `passwd`, `flags`, `immunity`, `time`, `info` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + while($admin = $sql->get()) + { + $html->get('list', 'sections/servers/'.$server['game'].'/settings/admins'); + + if($admin['active']) + $html->unit('active', 1); + else + $html->unit('active'); + + $html->set('id', $admin['id']); + $html->set('value', $admin['value']); + $html->set('passwd', $admin['passwd']); + $html->set('flags', $admin['flags']); + $html->set('immunity', $admin['immunity']); + $html->set('time', date('d.m.y', $admin['time'])); + $html->set('info', $admin['info']); + + $html->pack('admins'); + } + + $sql->query('SELECT `id` FROM `admins_'.$server['game'].'` WHERE `server`="'.$id.'" ORDER BY `id` DESC LIMIT 1'); + $max = $sql->get(); + + $html->get('admins', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('admins', isset($html->arr['admins']) ? $html->arr['admins'] : ''); + $html->set('index', $max['id'] < 1 ? 0 : $max['id']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/antiddos.php b/system/sections/servers/cssold/settings/antiddos.php new file mode 100644 index 0000000..6451e5d --- /dev/null +++ b/system/sections/servers/cssold/settings/antiddos.php @@ -0,0 +1,73 @@ +query('SELECT `id` FROM `units` WHERE `id`="'.$server['unit'].'" AND `ddos`="1" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'В данный момент нельзя изменить параметр, т.к. включена защита на всю локацию.'), $name_mcache); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($url['type']) || !in_array($url['type'], array('0', '1', '2'))) + sys::outjs(array('e' => 'Неправильно передан параметр.'), $name_mcache); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh', $user['group'])), $name_mcache); + + list($ip, $port) = explode(':', $server['address']); + + $geo = $cfg['iptables'].'_geo'; + + if($url['type'] == 2) + { + if($server['ddos'] == 2) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="2" WHERE `id`="'.$id.'" LIMIT 1'); + }elseif($url['type'] == 1){ + if($server['ddos'] == 1) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $cmd = ''; + + if($server['ddos']) + $cmd = 'iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country AM,BY,UA,RU,KZ -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'; + + $rule = 'iptables -I INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country UA,RU -j DROP;'; + + $ssh->set($cmd.$rule.' echo -e "#'.$id.';\n'.$rule.'" >> '.$geo); + + $sql->query('UPDATE `servers` set `ddos`="1" WHERE `id`="'.$id.'" LIMIT 1'); + }else{ + if(!$server['ddos']) + sys::outjs(array('s' => 'ok'), $name_mcache); + + $country = $server['ddos'] == 2 ? 'AM,BY,UA,RU,KZ' : 'UA,RU'; + + $ssh->set('iptables -D INPUT -p udp -d '.$ip.' --dport '.$port.' -m geoip ! --source-country '.$country.' -j DROP;' + .'sed "`nl '.$geo.' | grep \"#'.$id.'\" | awk \'{print $1","$1+1}\'`d" '.$geo.' > '.$geo.'_temp; cat '.$geo.'_temp > '.$geo.'; rm '.$geo.'_temp;'); + + $sql->query('UPDATE `servers` set `ddos`="0" WHERE `id`="'.$id.'" LIMIT 1'); + } + + $mcache->delete('server_settings_'.$id); + + sys::outjs(array('s' => 'ok'), $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/bans.php b/system/sections/servers/cssold/settings/bans.php new file mode 100644 index 0000000..71a11ca --- /dev/null +++ b/system/sections/servers/cssold/settings/bans.php @@ -0,0 +1,160 @@ +nav('Бан листы'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к файлам (banned_user.cfg / banned_ip.cfg) + $folder = $tarif['install'].$server['uid'].'/cstrike'; + + // Если бан/разбан/проверка + if($go) + { + $aData = array(); + + $aData['value'] = isset($_POST['value']) ? trim($_POST['value']) : sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + $aData['userid'] = isset($_POST['userid']) ? sys::int($_POST['userid']) : false; + $aData['amxbans'] = isset($_POST['amxbans']) ? true : false; + + // Проверка входных данных + if(sys::valid($aData['value'], 'steamid') AND sys::valid($aData['value'], 'ip')) + sys::outjs(array('e' => sys::text('servers', 'bans')), $nmch); + + // Если указан steamid + if(sys::valid($aData['value'], 'ip')) + { + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans'] AND $aData['userid']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['userid']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"banid 0.0 ".$aData['value']." kick\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"banid 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_user.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_user.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_user.cfg | grep -v '.$aData['value'].' > temp_banned.cfg; echo "" >> temp_banned.cfg && cat temp_banned.cfg > banned_user.cfg; rm temp_banned.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeid ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeid\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_user.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный SteamID найден в файле banned_user.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный SteamID не найден в файле banned_user.cfg'), $nmch); + } + }else{ + // бан + if(isset($url['action']) AND $url['action'] == 'ban') + { + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"sm_ban 0 ".$aData['value']." EGP\"\015'"); + else + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"addip 0.0 ".$aData['value']." EGP\"\015'"); + + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] != trim($ssh->get())) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"addip 0.0 '.$aData['value'].'\" >> '.$folder.'/banned_ip.cfg"'); + + sys::outjs(array('s' => 'ok'), $nmch); + + // разбан + }elseif(isset($url['action']) AND $url['action'] == 'unban'){ + // Убираем запись из banned_ip.cfg + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' sh -c "cat banned_ip.cfg | grep -v '.$aData['value'].' > temp_listip.cfg; echo "" >> temp_listip.cfg && cat temp_listip.cfg > banned_ip.cfg; rm temp_listip.cfg"'); + + // Если включен sourcebans + if($aData['amxbans']) + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"amx_unban ".$aData['value']."\"\015'"); + else{ + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"removeip ".$aData['value']."\"\015'"); + $ssh->set("sudo -u server".$server['uid']." screen -p 0 -S s_".$server['uid']." -X eval 'stuff \"writeip\"\015'"); + } + + sys::outjs(array('s' => 'ok'), $nmch); + // проверка + }else{ + $ssh->set('cd '.$folder.' && sudo -u server'.$server['uid'].' fgrep '.$aData['value'].' banned_ip.cfg | awk \'{print $3}\''); + + if($aData['value'] == trim($ssh->get())) + sys::outjs(array('ban' => 'Данный IP найден в файле banned_ip.cfg'), $nmch); + + sys::outjs(array('unban' => 'Данный IP не найден в файле banned_ip.cfg'), $nmch); + } + } + } + + // Содержимое banned_user.cfg + $ssh->set('cd '.$folder.' && cat banned_user.cfg | awk \'{print $3}\' | grep STEAM_'); + $aBanned = explode("\n", $ssh->get()); + + // Содержимое banned_ip.cfg + $ssh->set('cd '.$folder.' && cat banned_ip.cfg | awk \'{print $3}\' | egrep "(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[0-9]{2}|[0-9])){3}"'); + $aListip = explode("\n", $ssh->get()); + + if(isset($aBanned[count($aBanned)-1]) AND $aBanned[count($aBanned)-1] == '') + unset($aBanned[count($aBanned)-1]); + + if(isset($aListip[count($aListip)-1]) AND $aListip[count($aListip)-1] == '') + unset($aListip[count($aListip)-1]); + + // Построение списка забаненых по steamid + foreach($aBanned as $line => $steam) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($steam)); + + $html->pack('banned'); + } + + // Построение списка забаненых по ip + foreach($aListip as $line => $ip) + { + $html->get('bans_list', 'sections/servers/games/settings'); + + $html->set('value', trim($ip)); + + $html->pack('listip'); + } + + $html->get('bans', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('banned', isset($html->arr['banned']) ? $html->arr['banned'] : ''); + $html->set('listip', isset($html->arr['listip']) ? $html->arr['listip'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/debug.php b/system/sections/servers/cssold/settings/debug.php new file mode 100644 index 0000000..180f9d0 --- /dev/null +++ b/system/sections/servers/cssold/settings/debug.php @@ -0,0 +1,28 @@ +nav('Отладочный лог'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Чтение файла - oldstart.log + $file = $tarif['install'].$server['uid'].'/debug.log'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep "CRASH: " | grep -ve "^#\|^[[:space:]]*$"'); + + $html->get('debug', 'sections/servers/games/settings'); + + $html->set('log', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/logs.php b/system/sections/servers/cssold/settings/logs.php new file mode 100644 index 0000000..1aa0914 --- /dev/null +++ b/system/sections/servers/cssold/settings/logs.php @@ -0,0 +1,89 @@ +nav('Логи'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['cslogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'logs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/logs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'logs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', ''); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/server.php b/system/sections/servers/cssold/settings/server.php new file mode 100644 index 0000000..b6a4696 --- /dev/null +++ b/system/sections/servers/cssold/settings/server.php @@ -0,0 +1,117 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' "'.$val.'"'."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/smlogs.php b/system/sections/servers/cssold/settings/smlogs.php new file mode 100644 index 0000000..b39aa81 --- /dev/null +++ b/system/sections/servers/cssold/settings/smlogs.php @@ -0,0 +1,89 @@ +nav('Логи SourceMod'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/cstrike/addons/sourcemod/logs'; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['csssmlogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get())); + $html->set('uri', 'smlogs'); + + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/smlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"\/"$1"\/"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('\/', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/logs'); + + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('uri', 'smlogs/log/'.end($name)); + $html->set('date', $date); + $html->set('size', $size); + + $html->pack('logs'); + } + + $html->get('logs', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('uri', 'sm'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/settings/start.php b/system/sections/servers/cssold/settings/start.php new file mode 100644 index 0000000..3715413 --- /dev/null +++ b/system/sections/servers/cssold/settings/start.php @@ -0,0 +1,170 @@ +query('SELECT `uid`, `slots`, `slots_start`, `map_start`, `vac`, `fastdl`, `autorestart`, `fps`, `tickrate` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install`, `fps`, `tickrate`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'games/games.php'); + include(LIB.'games/tarifs.php'); + include(LIB.'games/'.$server['game'].'/tarif.php'); + + // Вывод списка карт + if(isset($url['maps'])) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $server['map_start'], false); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'map': + $map = isset($url['value']) ? trim($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + if($map != $server['map_start']) + games::maplist($id, $unit, $tarif['install'].$server['uid'].'/cstrike/maps', $map, true, $nmch); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'vac': + if($value != $server['vac']) + $sql->query('UPDATE `servers` set `vac`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fps': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['fps']))) + $sql->query('UPDATE `servers` set `fps`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'tickrate': + if(!tarif::price($tarif['price']) AND in_array($value, explode(':', $tarif['tickrate']))) + $sql->query('UPDATE `servers` set `tickrate`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'fastdl': + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + if($value) + { + $fastdl = 'sv_downloadurl "http://'.sys::first(explode(':', $unit['address'])).':8080/fast_'.$server['uid'].'"'.PHP_EOL + .'sv_consistency 1'.PHP_EOL + .'sv_allowupload 1'.PHP_EOL + .'sv_allowdownload 1'; + + // Временый файл + $temp = sys::temp($fastdl); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg;' + .'ln -s '.$tarif['install'].$server['uid'].'/cstrike /var/nginx/fast_'.$server['uid'].';' + .'sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'echo "exec fastdl.cfg" >> '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg'); + + unlink($temp); + }else + $ssh->set('sed -i '."'s/exec fastdl.cfg//g'".' '.$tarif['install'].$server['uid'].'/cstrike/cfg/server.cfg;' + .'rm '.$tarif['install'].$server['uid'].'/cstrike/cfg/fastdl.cfg; rm /var/nginx/fast_'.$server['uid']); + + $sql->query('UPDATE `servers` set `fastdl`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Античит VAC + $vac = $server['vac'] ? '' : ''; + + // Быстрая скачака + $fastdl = $server['fastdl'] ? '' : ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $fps = ''; + $tickrate = ''; + + if(!tarif::price($tarif['price'])) + { + $aFps = explode(':', $tarif['fps']); + + unset($aFps[array_search($server['fps'], $aFps)]); + + if(count($aFps)) + foreach($aFps as $value) + $fps .= ''; + + $aTick = explode(':', $tarif['tickrate']); + + unset($aTick[array_search($server['tickrate'], $aTick)]); + + if(count($aTick)) + foreach($aTick as $value) + $tickrate .= ''; + } + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('map', $server['map_start']); + $html->set('vac', $vac); + $html->set('fastdl', $fastdl); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + if(!tarif::price($tarif['price'])) + { + $html->unit('fps', true); + $html->set('fps', $fps); + + $html->unit('tickrate', true); + $html->set('tickrate', $tickrate); + }else{ + $html->unit('fps'); + $html->unit('tickrate'); + } + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/tarif.php b/system/sections/servers/cssold/tarif.php new file mode 100644 index 0000000..30cc896 --- /dev/null +++ b/system/sections/servers/cssold/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `fps`, `tickrate`, `ram`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/tarif/extend.php b/system/sections/servers/cssold/tarif/extend.php new file mode 100644 index 0000000..5125e5f --- /dev/null +++ b/system/sections/servers/cssold/tarif/extend.php @@ -0,0 +1,52 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['fps'] = $server['fps']; + $aData['tickrate'] = $server['tickrate']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = sys::b64djs($tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[$server['tickrate'].'_'.$server['fps']]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/tarif/plan.php b/system/sections/servers/cssold/tarif/plan.php new file mode 100644 index 0000000..a5173f7 --- /dev/null +++ b/system/sections/servers/cssold/tarif/plan.php @@ -0,0 +1,67 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = sys::b64djs($tarif['price']); + + // Проверка плана + if(!array_key_exists($plan, $aPrice)) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + list($tickrate, $fps) = explode('_', $plan); + + if($tickrate == $server['tickrate'] AND $fps == $server['fps']) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день (по новому тарифному плану) + $price = $aPrice[$plan]/30*$server['slots']; + + // Цена аренды за остаток дней + $price_old = $aPrice[$server['tickrate'].'_'.$server['fps']]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + // Выполнение смена тарифного плана + if($go) + { + sys::benefitblock($id, $nmch); + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `fps`="'.$fps.'", `tickrate`="'.$tickrate.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/tarif/slots.php b/system/sections/servers/cssold/tarif/slots.php new file mode 100644 index 0000000..fae705c --- /dev/null +++ b/system/sections/servers/cssold/tarif/slots.php @@ -0,0 +1,33 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = sys::b64djs($tarif['price']); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[$server['tickrate'].'_'.$server['fps']]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[$server['tickrate'].'_'.$server['fps']]/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/tarif/unit.php b/system/sections/servers/cssold/tarif/unit.php new file mode 100644 index 0000000..bc023d1 --- /dev/null +++ b/system/sections/servers/cssold/tarif/unit.php @@ -0,0 +1,48 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `fps`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = sys::b64djs($oldTarif['price']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = sys::b64djs($tarif['price']); + + if(!array_key_exists($server['tickrate'].'_'.$server['fps'], $aPrice)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[$server['tickrate'].'_'.$server['fps']]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[$server['tickrate'].'_'.$server['fps']]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/cssold/web.php b/system/sections/servers/cssold/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/cssold/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/filetp.php b/system/sections/servers/filetp.php new file mode 100644 index 0000000..feb39c9 --- /dev/null +++ b/system/sections/servers/filetp.php @@ -0,0 +1,223 @@ +query('SELECT `uid`, `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + if(!$server['ftp_use']) + sys::back($cfg['http'].'servers/id/'.$id); + + sys::nav($server, $id, 'filetp'); + + $frouter = explode('/', sys::route($server, 'filetp', $go)); + + if(end($frouter) == 'noaccess.php') + include(SEC.'servers/noaccess.php'); + else{ + $sql->query('SELECT `uid`, `unit`, `tarif`, `ftp`, `ftp_root`, `ftp_passwd`, `ftp_on`, `hdd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + $ip = sys::first(explode(':', $unit['address'])); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('FileTP'); + + // Корневой каталог сервера + if($cfg['ftp']['root'][$server['game']] || $server['ftp_root']) + { + // Путь для Proftpd + $homedir = $tarif['install'].$server['uid']; + + // Путь для файлового менеджера + $dir = $cfg['ftp']['dir'][$server['game']]; + }else{ + // Путь для Proftpd + $homedir = $tarif['install'].$server['uid'].$cfg['ftp']['home'][$server['game']]; + + // Путь для файлового менеджера + $dir = '/'; + } + + $aData = array( + 'root' => $dir, + 'host' => $ip, + 'login' => $server['uid'], + 'passwd' => $server['ftp_passwd'] + ); + + if($go) + { + if(isset($url['action']) AND in_array($url['action'], array('on', 'off', 'change', 'logs'))) + { + $sql->query('SELECT `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = array_merge($unit, $sql->get()); + + include(LIB.'ssh.php'); + + // Проверка соединения с ssh сервером + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + }else{ + include(LIB.'ftp.php'); + + $ftp = new ftp; + + // Проверка соединения с ftp сервером + if(!$ftp->auth($aData['host'], $aData['login'], $aData['passwd'])) + { + if(isset($url['action'])) + { + if($url['action'] == 'search') + sys::out('Не удалось соединиться с ftp-сервером.'); + + sys::outjs(array('e' => 'Не удалось соединиться с ftp-сервером.')); + } + + sys::out(); + } + } + + // Выполнение операций + if(isset($url['action'])) + switch($url['action']) + { + case 'on': + if($server['ftp']) + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + $used = sys::int($ssh->get('cd '.$tarif['install'].$server['uid'].' && du -b | tail -1')); + + if($used < 1) + sys::back($cfg['http'].'help/action/create'); + + $bytes = $server['hdd']*1048576; + + $server['ftp_passwd'] = isset($server['ftp_passwd']{1}) ? $server['ftp_passwd'] : sys::passwd(8); + + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';' + .'DELETE FROM quotalimits WHERE name=\''.$server['uid'].'\';' + .'DELETE FROM quotatallies WHERE name=\''.$server['uid'].'\';' + .'INSERT INTO users set username=\''.$server['uid'].'\', password=\''.$server['ftp_passwd'].'\', uid=\''.$server['uid'].'\', gid=\'1000\', homedir=\''.$homedir.'\', shell=\'/bin/false\';' + .'INSERT INTO quotalimits set name=\''.$server['uid'].'\', quota_type=\'user\', per_session=\'false\', limit_type=\'hard\', bytes_in_avail=\''.$bytes.'\';' + .'INSERT INTO quotatallies set name=\''.$server['uid'].'\', quota_type=\'user\', bytes_in_used=\''.$used.'\''; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + $sql->query('UPDATE `servers` SET `ftp`="1", `ftp_on`="1", `ftp_passwd`="'.$server['ftp_passwd'].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_filetp_'.$id); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + case 'change': + if(!$server['ftp']) + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + $passwd = sys::passwd(8); + + $qSql = "UPDATE users set password='".$passwd."' WHERE username='".$server['uid']."' LIMIT 1"; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e '.'"'.$qSql.'"'); + + $sql->query('UPDATE `servers` SET `ftp_passwd`="'.$passwd.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_filetp_'.$id); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + case 'off': + if(!$server['ftp']) + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + $qSql = 'DELETE FROM users WHERE username=\''.$server['uid'].'\';' + .'DELETE FROM quotalimits WHERE name=\''.$server['uid'].'\';' + .'DELETE FROM quotatallies WHERE name=\''.$server['uid'].'\''; + + $ssh->set('screen -dmS ftp'.$server['uid'].' mysql -P '.$unit['sql_port'].' -u'.$unit['sql_login'].' -p'.$unit['sql_passwd'].' --database '.$unit['sql_ftp'].' -e "'.$qSql.'"'); + + $sql->query('UPDATE `servers` SET `ftp`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_filetp_'.$id); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/filetp'); + + case 'rename': + $ftp->rename(json_decode($_POST['path']), json_decode($_POST['name']), json_decode($_POST['newname'])); + + case 'edit': + $ftp->edit_file(json_decode($_POST['path']), json_decode($_POST['name'])); + + case 'create': + if(isset($url['folder'])) + $ftp->mkdir(json_decode($_POST['path']), json_decode($_POST['name'])); + + $ftp->touch(json_decode($_POST['path']), json_decode($_POST['name']), json_decode($_POST['text'])); + + case 'delete': + if(isset($url['folder'])) + $ftp->rmdir(json_decode($_POST['path']), json_decode($_POST['name'])); + + $ftp->rmfile(json_decode($_POST['path']).'/'.json_decode($_POST['name'])); + + case 'chmod': + $ftp->chmod(json_decode($_POST['path']), json_decode($_POST['name']), sys::int($_POST['chmod'])); + + case 'search': + $text = isset($_POST['find']) ? sys::first(explode('.', json_decode($_POST['find']))) : sys::out(); + + if(!isset($text{2})) + sys::out('Для выполнения поиска, необходимо больше данных'); + + $ftp->search($text, $id); + + case 'logs': + $logs = $mcache->get('filetp_logs_'.$id); + + if(!$logs) + { + include(LIB.'ftp.php'); + + $ftp = new ftp; + + $logs = $ftp->logs($ssh->get('cat /var/log/proftpd/xferlog | grep "/'.$server['uid'].'/" | awk \'{print $2"\\\"$3"\\\"$4"\\\"$5"\\\"$7"\\\"$8"\\\"$9"\\\"$12}\' | tail -50'), $server['uid']); + + $mcache->set('filetp_logs_'.$id, $logs, false, 300); + } + + sys::out($logs); + } + + if(!isset($_POST['path'])) $_POST['path'] = json_encode($aData['root']); + + sys::out($ftp->view($ftp->read(json_decode($_POST['path'])), $id)); + } + + if($mcache->get('server_filetp_'.$id) != '') + $html->arr['main'] = $mcache->get('server_filetp_'.$id); + else{ + if($server['ftp']) + { + $html->get('filetp_on', 'sections/servers/games/filetp'); + + $html->set('address', 'ftp://'.$aData['login'].':'.$aData['passwd'].'@'.$aData['host']); + $html->set('server', $aData['host']); + $html->set('login', $aData['login']); + $html->set('passwd', $aData['passwd']); + $html->set('path', $aData['root']); + }else + $html->get('filetp_off', 'sections/servers/games/filetp'); + + $html->set('id', $id); + + $html->pack('main'); + + $mcache->set('server_filetp_'.$id, $html->arr['main'], false, 10); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/check.php b/system/sections/servers/games/copy/check.php new file mode 100644 index 0000000..c50e8c4 --- /dev/null +++ b/system/sections/servers/games/copy/check.php @@ -0,0 +1,26 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache'))); + + $mcache->set($nmch, true, false, 10); + + $copys = $sql->query('SELECT `id` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `status`="0"'); + if(!$sql->num($copys)) + sys::outjs(array('e' => 'no find'), $nmch); + + while($copy = $sql->get($copys)) + { + if(!sys::int($ssh->get('ps aux | grep copy_'.$server['uid'].' | grep -v grep | awk \'{print $2}\''))) + $sql->query('UPDATE `copy` set `status`="1" WHERE `id`="'.$copy['id'].'" LIMIT 1'); + } + + // Очистка кеша + $mcache->delete('server_copy_'.$id); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/create.php b/system/sections/servers/games/copy/create.php new file mode 100644 index 0000000..e27d8b7 --- /dev/null +++ b/system/sections/servers/games/copy/create.php @@ -0,0 +1,54 @@ +query('SELECT `id` FROM `copy` WHERE `server`="'.$id.'" ORDER BY `id` DESC LIMIT 3'); + if($sql->num() > 2) + sys::outjs(array('e' => 'Для создания новой копии необходимо удалить старые.'), $nmch); + + $sql->query('SELECT `id` FROM `copy` WHERE `server`="'.$id.'" AND `status`="0" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Для создания новой копии дождитесь создания предыдущей.'), $nmch); + + $aSel = array(); + + $aData = isset($_POST['copy']) ? $_POST['copy'] : sys::outjs(array('e' => 'Для создания копии необходимо выбрать директории/файлы.'), $nmch); + + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + if(!isset($aData['\''.$name.'\''])) + continue; + + $aSel[] = $name; + } + + if(!count($aSel)) + sys::outjs(array('e' => 'Для создания копии необходимо выбрать директории/файлы.'), $nmch); + + $copy = ''; + $info = ''; + $plugins = ''; + + foreach($aSel as $name) + { + $copy .= isset(params::$section_copy[$server['game']]['aCopyDir'][$name]) ? params::$section_copy[$server['game']]['aCopyDir'][$name].' ' : ''; + $copy .= isset(params::$section_copy[$server['game']]['aCopyFile'][$name]) ? params::$section_copy[$server['game']]['aCopyFile'][$name].' ' : ''; + + $info .= $name.', '; + } + + $name_copy = md5($start_point.$id.$server['game']); + + $ssh->set('cd '.$tarif['install'].$server['uid'].' && screen -dmS copy_'.$server['uid'].' sh -c "tar -cf '.$name_copy.'.tar '.$copy.'; mv '.$name_copy.'.tar /copy"'); + + $sql->query('SELECT `plugin`, `upd` FROM `plugins_install` WHERE `server`="'.$id.'"'); + while($plugin = $sql->get()) + $plugins .= $plugin['plugin'].'.'.$plugin['upd'].','; + + $sql->query('INSERT INTO `copy` set `user`="'.$server['user'].'_'.$server['unit'].'", `game`="'.$server['game'].'", `server`="'.$id.'", `pack`="'.$server['pack'].'", `name`="'.$name_copy.'", `info`="'.substr($info, 0, -2).'", `plugins`="'.substr($plugins, 0, -1).'", `date`="'.$start_point.'", `status`="0"'); + + // Очистка кеша + $mcache->delete('server_copy_'.$id); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/fullcopy.php b/system/sections/servers/games/copy/fullcopy.php new file mode 100644 index 0000000..23bc872 --- /dev/null +++ b/system/sections/servers/games/copy/fullcopy.php @@ -0,0 +1,25 @@ +query('SELECT `id` FROM `copy` WHERE `server`="'.$id.'" AND `info`="'.params::$section_copy[$server['game']]['CopyFull'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Для создания новой копии необходимо удалить старую.'), $nmch); + + $name_copy = md5($start_point.$id.$server['game']); + + $ssh->set('cd '.$tarif['install'].$server['uid'].' && screen -dmS copy_'.$server['uid'].' sh -c "tar -cf '.$name_copy.'.tar '.params::$section_copy[$server['game']]['CopyFull'].'; mv '.$name_copy.'.tar /copy"'); + + $plugins = ''; + + $sql->query('SELECT `plugin`, `upd` FROM `plugins_install` WHERE `server`="'.$id.'"'); + while($plugin = $sql->get()) + $plugins .= $plugin['plugin'].'.'.$plugin['upd'].','; + + $sql->query('INSERT INTO `copy` set `user`="'.$server['user'].'_'.$server['unit'].'", `game`="'.$server['game'].'", `server`="'.$id.'", `pack`="'.$server['pack'].'", `name`="'.$name_copy.'", `info`="'.params::$section_copy[$server['game']]['CopyFull'].'", `plugins`="'.substr($plugins, 0, -1).'", `date`="'.$start_point.'", `status`="0"'); + + // Очистка кеша + $mcache->delete('server_copy_'.$id); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/recfull.php b/system/sections/servers/games/copy/recfull.php new file mode 100644 index 0000000..76b0f26 --- /dev/null +++ b/system/sections/servers/games/copy/recfull.php @@ -0,0 +1,79 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `id`, `pack`, `name`, `info`, `plugins`, `date`, `status` FROM `copy` WHERE `id`="'.$cid.'" AND `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + if($copy['pack'] != $server['pack']) + { + $sql->query('SELECT `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = array_merge($tarif, $sql->get()); + + $aPack = sys::b64djs($tarif['packs'], true); + + sys::outjs(array('e' => 'Для восстановления необходимо установить сборку: '.$aPack[$copy['pack']].'.'), $nmch); + } + + if(params::$section_copy[$server['game']]['CopyFull'] == $copy['info']) + $rm = 'rm -r '.$copy['info']; + else{ + $rm = ''; + + $aInfo = explode(', ', $copy['info']); + + foreach($aInfo as $name) + { + $rm .= isset(params::$section_copy[$server['game']]['aCopyDir'][$name]) ? 'rm -r '.params::$section_copy[$server['game']]['aCopyDir'][$name].' ' : ''; + $rm .= isset(params::$section_copy[$server['game']]['aCopyFile'][$name]) ? 'rm '.params::$section_copy[$server['game']]['aCopyFile'][$name].' ' : ''; + } + + } + + $ssh->set('cd '.$tarif['install'].$server['uid'].' && screen -dmS rec_'.$server['uid'].' sh -c "' + .$rm.'; cp /copy/'.$copy['name'].'.tar . && tar -xf '.$copy['name'].'.tar; rm '.$copy['name'].'.tar;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].';' + .'chown -R servers'.$server['uid'].':servers ."'); + + // Удаление плагинов + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$id.'"'); + + // Установка плагинов (имитирование) + $aPlugins = explode(',', $copy['plugins']); + + foreach($aPlugins as $plugin) + { + $aPlugin = explode('.', $plugin); + + if(!count($aPlugin != 2)) + continue; + + if(!$aPlugin[0]) + continue; + + $sql->query('SELECT `id` FROM `plugins_install` WHERE `plugin`="'.$aPlugin[0].'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$aPlugin[1]) + $aPlugin[1] = 0; + + if(!$sql->num()) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$aPlugin[0].'", `upd`="'.$aPlugin[1].'", `time`="'.$copy['date'].'"'); + } + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + $sql->query('UPDATE `servers` set `status`="recovery" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/recpart.php b/system/sections/servers/games/copy/recpart.php new file mode 100644 index 0000000..da74d73 --- /dev/null +++ b/system/sections/servers/games/copy/recpart.php @@ -0,0 +1,53 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `id`, `pack`, `name`, `plugins`, `date`, `status` FROM `copy` WHERE `id`="'.$cid.'" AND `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + if($copy['pack'] != $server['pack']) + { + $sql->query('SELECT `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = array_merge($tarif, $sql->get()); + + $aPack = sys::b64djs($tarif['packs'], true); + + sys::outjs(array('e' => 'Для восстановления необходимо установить сборку: '.$aPack[$copy['pack']].'.'), $nmch); + } + + $ssh->set('cd '.$tarif['install'].$server['uid'].' && screen -dmS rec_'.$server['uid'].' sh -c "' + .'cp /copy/'.$copy['name'].'.tar . && tar -xf '.$copy['name'].'.tar; rm '.$copy['name'].'.tar;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].';' + .'chown -R servers'.$server['uid'].':servers ."'); + + // Установка плагинов (имитирование) + $aPlugin = explode(',', $copy['plugins']); + + foreach($aPlugin as $plugin) + { + if(!$plugin) + continue; + + $sql->query('SELECT `id` FROM `plugins_install` WHERE `plugin`="'.$plugin.'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$plugin.'", `time`="'.$copy['date'].'"'); + } + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + $sql->query('UPDATE `servers` set `status`="recovery" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/copy/remove.php b/system/sections/servers/games/copy/remove.php new file mode 100644 index 0000000..67eff02 --- /dev/null +++ b/system/sections/servers/games/copy/remove.php @@ -0,0 +1,24 @@ + 'Выбранная копия не найдена.'), $nmch); + + $sql->query('SELECT `name`, `status` FROM `copy` WHERE `id`="'.$cid.'" AND `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная копия не найдена.'), $nmch); + + $copy = $sql->get(); + + if(!$copy['status']) + sys::outjs(array('e' => 'Дождитесь создания резервной копии.'), $nmch); + + $ssh->set('screen -dmS rem_copy_'.$cid.' rm /copy/'.$copy['name'].'.tar'); + + $sql->query('DELETE FROM `copy` WHERE `id`="'.$cid.'" LIMIT 1'); + + // Очистка кеша + $mcache->delete('server_copy_'.$id); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/owners.php b/system/sections/servers/games/owners.php new file mode 100644 index 0000000..ed9e83d --- /dev/null +++ b/system/sections/servers/games/owners.php @@ -0,0 +1,153 @@ +query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aOwnersI as $access => $info) + if($aRights[$access]) $rights .= $info.', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) && $url['delete']) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) && is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + if($server['user'] == $uowner['id']) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + $upd = $sql->num($owner); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$upd) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально кол-во совладельцев.'), $nmch); + } + + $aRights = array(); + + $check = 0; + + foreach($aOwners[$server['game']] as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + if($upd) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + $sql->query('DELETE FROM `owners` WHERE `server`="'.$id.'" AND `time`<"'.$start_point.'" LIMIT 5'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Друзья'); + + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners', 'sections/servers/games/owners'); + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + $html->pack('owners'); + } + + foreach($aOwnersI as $access => $info) + { + $html->get('access', 'sections/servers/games/owners'); + $html->set('access', $access); + $html->set('info', $info); + $html->pack('access'); + } + + $html->get('index', 'sections/servers/games/owners'); + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + $html->set('access', $html->arr['access']); + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/config.php b/system/sections/servers/games/plugins/config.php new file mode 100644 index 0000000..cc8971e --- /dev/null +++ b/system/sections/servers/games/plugins/config.php @@ -0,0 +1,83 @@ +query('SELECT `plugin`, `update`, `file` FROM `plugins_config` WHERE `id`="'.$fid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $config = $sql->get(); + + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$config['plugin'].'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + // Если обновленный плагин + if($config['update']) + $sql->query('SELECT `name` FROM `plugins_update` WHERE `id`="'.$config['update'].'" LIMIT 1'); + else + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$config['plugin'].'" LIMIT 1'); + + $plugin = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Данные файла + $file = explode('/', $config['file']); + + // Полный путь файла + $path = $tarif['install'].$server['uid'].'/'.$config['file']; + + // Сохранение + if($go) + { + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $path, 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$path); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$path.'; cat '.$path.'"'); + + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + $html->nav($plugin['name'], $cfg['http'].'servers/id/'.$id.'/section/plugins/subsection/plugin/plugin/'.$config['plugin']); + + $html->get('config', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('file', $fid); + $html->set('plugin', $config['plugin']); + $html->set('name', end($file)); + $html->set('data', htmlspecialchars($ssh->get())); + + $html->pack('main'); + +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/delete.php b/system/sections/servers/games/plugins/delete.php new file mode 100644 index 0000000..d97111b --- /dev/null +++ b/system/sections/servers/games/plugins/delete.php @@ -0,0 +1,87 @@ +query('SELECT `id`, `upd` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Данный плагин не установлен')); + + $plugin = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория игр. сервера + $dir = $tarif['install'].$server['uid'].'/'; + + // Имя исполняемого файла + if($plugin['upd']) + { + $qsql = 'WHERE `update`="'.$plugin['upd'].'" ORDER BY `id` ASC'; + $frm = 'u'.$plugin['upd']; + }else{ + $qsql = 'WHERE `plugin`="'.$pid.'" AND `update`="0" ORDER BY `id` ASC'; + $frm = $pid; + } + + // Удаление и установка файлов + $ssh->set('cd '.$dir.' && screen -dmS delete_upd_'.$start_point.' ' + .'sudo -u server'.$server['uid'].' sh -c "' + .'wget --no-check-certificate '.$cfg['plugins'].'delete/'.$frm.'.rm && ' + .'chmod 755 '.$frm.'.rm; ./'.$frm.'.rm; rm '.$frm.'.rm"'); + + include(LIB.'games/plugins.php'); + + // Удаление добавленного при установке текста в файлах + $sql->query('SELECT `text`, `file` FROM `plugins_write` '.$qsql); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + unset($clear); + + // Добавление текста при удалении в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write_del` '.$qsql); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Удаление записи установленного плагина в базе + $sql->query('DELETE FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'"'); + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + if($plugin['upd']) + $sql->query('SELECT `install` FROM `plugins_delete_ins` WHERE `update`="'.$plugin['upd'].'" LIMIT 1'); + else + $sql->query('SELECT `install` FROM `plugins_delete_ins` WHERE `plugin`="'.$pid.'" AND `update`="0" LIMIT 1'); + + if($sql->num()) + { + $ins = $sql->get(); + + $sql->query('SELECT `name` FROM `plugins` WHERE `id`="'.$ins['install'].'" LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + sys::outjs(array('i' => $ins['install'], 'pname' => $plugin['name']), $nmch); + } + } + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/install.php b/system/sections/servers/games/plugins/install.php new file mode 100644 index 0000000..e52dbb1 --- /dev/null +++ b/system/sections/servers/games/plugins/install.php @@ -0,0 +1,136 @@ +query('SELECT `name`, `cfg`, `upd`, `incompatible`, `choice`, `required`, `packs`, `price` FROM `plugins` WHERE `id`="'.$pid.'" AND `game`="'.$server['game'].'" LIMIT 1'); + + if(!$sql->num()) + exit; + + $plugin = $sql->get(); + + // Проверка установки плагина + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный плагин уже установлен')); + + $upd = false; + + // Если есть более поздняя версия плагина + if($plugin['upd']) + { + $sql->query('SELECT `name`, `id`, `cfg`, `incompatible`, `choice`, `required`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$pid.'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = array_merge($plugin, $sql->get()); + + $upd = true; + } + } + + $buy = false; + + // Если платный плагин + if($plugin['price']) + { + // Проверка покупки + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$pid.'" AND `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + $buy = true; + else{ + // Проверка баланса + if($user['balance'] < $plugin['price']) + sys::outjs(array('e' => 'У вас не хватает '.(round($plugin['price']-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + } + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + exit; + + include(LIB.'games/plugins.php'); + + // Проверка на наличие несовместимости с уже установленными плагинами + plugins::incompatible($id, $plugin['incompatible'], $nmch); + + // Проверка на наличие необходимых установленых плагинов для устанавливаемого дополнения + plugins::required($id, $plugin['required'], $plugin['choice'], $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + if($upd) + { + $qsql = 'WHERE `update`="'.$plugin['id'].'" ORDER BY `id` ASC'; + $fzip = 'u'.$plugin['id']; + $upd = $plugin['id']; + }else{ + $qsql = 'WHERE `plugin`="'.$pid.'" AND `update`="0" ORDER BY `id` ASC'; + $fzip = $pid; + $upd = 0; + } + + // Директория игр. сервера + $dir = $tarif['install'].$server['uid'].'/'; + + // Установка файлов на сервер + $ssh->set('cd '.$dir.' && screen -dmS install_'.$start_point.' sudo -u server'.$server['uid'].' sh -c "' + .'wget --no-check-certificate '.$cfg['plugins'].'install/'.$fzip.'.zip && unzip -o '.$fzip.'.zip; rm '.$fzip.'.zip;' + .'find . -type d -exec chmod 700 {} \;;' + .'find . -type f -exec chmod 600 {} \;;' + .'chmod 500 '.params::$aFileGame[$server['game']].'"'); + + // Удаление файлов + $sql->query('SELECT `file` FROM `plugins_delete` '.$qsql); + while($delete = $sql->get()) + $ssh->set('sudo -u server'.$server['uid'].' rm '.$dir.$delete['file']); + + // Удаление текста из файлов + $sql->query('SELECT `text`, `file`, `regex` FROM `plugins_clear` '.$qsql); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + // Добавление текста в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write` '.$qsql); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Если платный плагин + if(!$buy AND $plugin['price']) + { + $sql->query('UPDATE `users` set `balance`=`balance`-"'.$plugin['price'].'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + $sql->query('INSERT INTO `plugins_buy` set `plugin`="'.$pid.'", `key`="'.md5(strip_tags($plugin['name'])).'", `server`="'.$id.'", `price`="'.$plugin['price'].'", `time`="'.$start_point.'"'); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_plugin'), + array('plugin' => strip_tags($plugin['name']), 'money' => $plugin['price'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$plugin['price'].'"'); + } + + // Запись данных в базу + $sql->query('INSERT INTO `plugins_install` set `server`="'.$id.'", `plugin`="'.$pid.'", `upd`="'.$upd.'", `time`="'.$start_point.'"'); + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + if($plugin['cfg']) + sys::outjs(array('s' => 'cfg'), $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/plugin.php b/system/sections/servers/games/plugins/plugin.php new file mode 100644 index 0000000..1655e23 --- /dev/null +++ b/system/sections/servers/games/plugins/plugin.php @@ -0,0 +1,87 @@ +query('SELECT `id`, `upd` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $install = $sql->get(); + + // Если установленно обновление + if($install['upd']) + $sql->query('SELECT `name`, `info`, `images`, `upd` FROM `plugins_update` WHERE `id`="'.$install['upd'].'" LIMIT 1'); + else + $sql->query('SELECT `name`, `info`, `images`, `upd` FROM `plugins` WHERE `id`="'.$pid.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $plugin = $sql->get(); + + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + $html->nav($plugin['name']); + + // Если есть кеш + if($mcache->get('server_plugin_'.$pid.$id) != '') + $html->arr['main'] = $mcache->get('server_plugin_'.$pid.$id); + else{ + include(LIB.'games/plugins.php'); + + // Построение списка редактируемых файлов + $aConf = array(); + + $sql->query('SELECT `id`, `file` FROM `plugins_config` WHERE (`plugin`="'.$pid.'" AND `update`="0") OR (`plugin`="'.$pid.'" AND `update`="'.$install['upd'].'") ORDER BY `sort`, `id` ASC'); + while($config = $sql->get()) + { + // Исключить дублирование, путем проверки массива файлов + if(in_array($config['file'], $aConf)) + continue; + + $aConf[] = $config['file']; + + // Данные файла + $file = explode('/', $config['file']); + + $html->get('config_list', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('fid', $config['id']); + $html->set('name', end($file)); + $html->set('file', $config['file']); + + $html->pack('configs'); + } + + $images = plugins::images($plugin['images'], $pid); + + $html->get('configs', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('name', $plugin['name']); + $html->set('info', htmlspecialchars_decode($plugin['info'])); + + // Картинки + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + // Редактируемые файлы + if(isset($html->arr['configs'])) + { + $html->set('configs', $html->arr['configs']); + $html->unit('configs', 1); + }else + $html->unit('configs'); + + $html->pack('main'); + + $mcache->set('server_plugin_'.$pid.$id, $html->arr['main'], false, 60); + } +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/search.php b/system/sections/servers/games/plugins/search.php new file mode 100644 index 0000000..3572d2b --- /dev/null +++ b/system/sections/servers/games/plugins/search.php @@ -0,0 +1,200 @@ + '')); + + $mkey = md5($text.$id); + + if($mcache->get($mkey) != '') + sys::outjs(array('s' => $mcache->get($mkey))); + + if(!isset($text{2})) + sys::outjs(array('s' => 'Для выполнения поиска, необходимо больше данных', $nmch)); + + $sPlugins = array(); + $sUpdate = array(); + + // Поиск по плагинам + $plugins = $sql->query('SELECT `id`, `packs` FROM `plugins` WHERE `game`="'.$server['game'].'" AND `name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 5'); + + // Поиск по обновлениям + $update = false; + + if(!$sql->num($plugins)) + { + $plugins = $sql->query('SELECT `id`, `plugin`, `packs` FROM `plugins_update` WHERE `game`="'.$server['game'].'" AND (`name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\')) AND `upd`="0" LIMIT 5'); + $update = true; + } + + // Если нет ниодного совпадения по вводимому тексту + if(!$sql->num($plugins)) + { + // Поиск по словам + if(strpos($text, ' ')) + { + // Массив слов + $aText = explode(' ', $text); + + // Метка, которая изменится в процессе, если будет найдено хоть одно совпадение + $sWord = false; + + foreach($aText as $word) + { + if($word == '' || !isset($word{2})) + continue; + + // Поиск по плагинам + $plugins = $sql->query('SELECT `id`, `packs` FROM `plugins` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 5'); + + // Поиск по обновлениям + $update = false; + + if(!$sql->num($plugins)) + { + $plugins = $sql->query('SELECT `id`, `plugin`, `packs` FROM `plugins_update` WHERE (`name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `desc` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\')) AND `upd`="0" LIMIT 5'); + $update = true; + } + + if($sql->num($plugins)) + { + if(!$sWord) $sWord = true; + + $sPlugins[] = $plugins; + $sUpdate[] = $update; + } + } + + // Если нет ниодного совпадения + if(!$sWord) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + }else{ + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + }else{ + $sPlugins[] = $plugins; + $sUpdate[] = $update; + } + + // Массив для исклуючения дублирования + $aPlugins = array(); + + foreach($sPlugins as $index => $plugins) + { + while($plugin = $sql->get($plugins)) + { + // Проверка дублирования + if(($sUpdate[$index] AND in_array($plugin['plugin'], $aPlugins)) || !$sUpdate[$index] AND in_array($plugin['id'], $aPlugins)) + continue; + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':', $plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $install = false; // не установлен плагин + $upd = false; // не обновлен плагин + + if($sUpdate[$index]) + { + $sql->query('SELECT `id`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['plugin'].'" LIMIT 1'); + + $aPlugins[] = $plugin['plugin']; + }else{ + $sql->query('SELECT `id`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + + $aPlugins[] = $plugin['id']; + } + + // Проверка на установку + if($sql->num()) + { + $install = $sql->get(); + + $upd = $install['upd']; + $time = sys::today($install['time']); + + $install = true; + } + + // Если установлен обновленный плагин + if($upd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$upd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['id'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + $html->get('search', 'sections/servers/games/plugins'); + + // Если установлен + if($install) + { + // Если есть обновление + if($plugin['upd'] > $upd) $html->unit('update', 1); else $html->unit('update'); + + // Если есть редактируемые файлы + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + $html->unit('install', 1); + $html->unit('!install'); + }else{ + // Обновление данных на более позднею версию плагина + $sql->query('SELECT `name`, `desc`, `status`, `cfg` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" AND `upd`="0" LIMIT 1'); + if($sql->num()) + { + $upd = $sql->get(); + + $plugin['name'] = $upd['name']; + $plugin['desc'] = $upd['desc']; + $plugin['status'] = $upd['status']; + $plugin['cfg'] = $upd['cfg']; + } + + $html->unit('install'); + $html->unit('!install', 1); + } + + if(!$plugin['status']) + { + $html->unit('unstable'); + $html->unit('stable', 1); + $html->unit('testing'); + }elseif($plugin['status'] == 2){ + $html->unit('unstable'); + $html->unit('stable'); + $html->unit('testing', 1); + }else{ + $html->unit('unstable', 1); + $html->unit('stable'); + $html->unit('testing'); + } + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + if($install) + $html->set('time', $time); + + $html->set('name', sys::find(htmlspecialchars_decode($plugin['name']), $text)); + $html->set('desc', sys::find(htmlspecialchars_decode($plugin['desc']), $text)); + + $html->pack('plugins'); + } + } + + $html->arr['plugins'] = isset($html->arr['plugins']) ? $html->arr['plugins'] : ''; + + $mcache->set($mkey, $html->arr['plugins'], false, 15); + + sys::outjs(array('s' => $html->arr['plugins']), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/games/plugins/update.php b/system/sections/servers/games/plugins/update.php new file mode 100644 index 0000000..ddecd7c --- /dev/null +++ b/system/sections/servers/games/plugins/update.php @@ -0,0 +1,88 @@ +query('SELECT `id` FROM `plugins_update` WHERE `plugin`="'.$pid.'" ORDER BY `id` DESC LIMIT 1'); + + if(!$sql->num()) + exit(); + + $plugin = $sql->get(); + + // Проверка установки плагина + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" LIMIT 1'); + if(!$sql->num()) + exit(); + + // Проверка установки обновления плагина + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" AND `upd`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный плагин уже обновлен')); + + // Данные обновления + $sql->query('SELECT `id`, `cfg`, `incompatible`, `required` FROM `plugins_update` WHERE `id`="'.$plugin['id'].'" LIMIT 1'); + + $plugin = $sql->get(); + + include(LIB.'games/plugins.php'); + + // Проверка на наличие несовместимости с уже установленными плагинами + plugins::incompatible($id, $plugin['incompatible'], $nmch); + + // Проверка на наличие необходимых установленых плагинов для устанавливаемого плагина + plugins::required($id, $plugin['required'], $nmch); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + if(!isset($ssh)) + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Директория игр. сервера + $dir = $tarif['install'].$server['uid'].'/'; + + // Установка файлов на сервер + $ssh->set('cd '.$dir.' && screen -dmS update_'.$start_point.' sudo -u server'.$server['uid'].' sh -c "wget --no-check-certificate '.$cfg['plugins'].'update/'.$plugin['id'].'.zip && unzip -o '.$plugin['id'].'.zip; rm '.$plugin['id'].'.zip"'); + + // Удаление файлов + $sql->query('SELECT `file` FROM `plugins_delete` WHERE `update`="'.$plugin['id'].'"'); + while($delete = $sql->get()) + $ssh->set('sudo -u server'.$server['uid'].' rm '.$dir.$delete['file']); + + unset($delete); + + // Удаление текста из файлов + $sql->query('SELECT `text`, `file`, `regex` FROM `plugins_clear` WHERE `update`="'.$plugin['id'].'"'); + while($clear = $sql->get()) + plugins::clear($clear, $server['uid'], $dir); + + unset($clear); + + // Добавление текста в файлы + $sql->query('SELECT `text`, `file`, `top` FROM `plugins_write` WHERE `update`="'.$plugin['id'].'" ORDER BY `id` ASC'); + while($write = $sql->get()) + plugins::write($write, $server['uid'], $dir); + + // Обновление данных в базе + $sql->query('UPDATE `plugins_install` set `upd`="'.$plugin['id'].'", `time`="'.$start_point.'" WHERE `server`="'.$id.'" AND `plugin`="'.$pid.'" LIMIT 1'); + + // Очистка кеша + $mcache->delete('server_plugins_'.$id); + + if($plugin['cfg']) + sys::outjs(array('s' => 'cfg'), $nmch); + + sys::outjs(array('s' => 'ok'), $nmch); + +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/api.php b/system/sections/servers/games/settings/api.php new file mode 100644 index 0000000..fa951bd --- /dev/null +++ b/system/sections/servers/games/settings/api.php @@ -0,0 +1,14 @@ +query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + $sql->query('DELETE FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + else + $sql->query('INSERT INTO `api` set `server`="'.$id.'", `key`="'.md5(sys::passwd(10)).'"'); + + $mcache->delete('server_settings_'.$id); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/crontab.php b/system/sections/servers/games/settings/crontab.php new file mode 100644 index 0000000..928c2cf --- /dev/null +++ b/system/sections/servers/games/settings/crontab.php @@ -0,0 +1,117 @@ +nav('Планировщик задач'); + + $sql->query('SELECT `autostop` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `panel` LIMIT 1'); + $panel = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($panel['passwd'], $panel['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + // Удаление задания + if(isset($url['action']) AND $url['action'] == 'delete') + { + $task = isset($_POST['task']) ? sys::int($_POST['task']) : sys::outjs(array('s' => 'ok'), $nmch); + + $sql->query('SELECT `cron` FROM `crontab` WHERE `id`="'.$task.'" AND `server`="'.$id.'" LIMIT 1'); + if(!$sql->num()) + $sys->outjs(array('s' => 'ok'), $nmch); + + $cron = $sql->get(); + + $ssh->set('touch /etc/crontab; cat /etc/crontab'); + $crontab = str_replace($cron['cron'], '', $ssh->get()); + + // Временный файл + $temp = sys::temp($crontab); + + $ssh->setfile($temp, '/etc/crontab', 0644); + + $ssh->set("sed -i '/^$/d' /etc/crontab;" + .'crontab -u root /etc/crontab'); + + unlink($temp); + + $sql->query('DELETE FROM `crontab` WHERE `id`="'.$task.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Добавление задания + $sql->query('SELECT `id` FROM `crontab` WHERE `server`="'.$id.'" LIMIT 5'); + if($sql->num() == $cfg['crontabs']) + sys::outjs(array('e' => sys::text('servers', 'crontab')), $nmch); + + $data = array(); + + $data['task'] = isset($_POST['task']) ? $_POST['task'] : 'start'; + + $task = in_array($server['game'], array('samp', 'crmp')) ? array('start', 'restart', 'stop') : array('start', 'restart', 'stop', 'console'); + + if(!in_array($data['task'], $task)) + $data['task'] = 'start'; + + $data['commands'] = isset($_POST['commands']) ? base64_encode(htmlspecialchars($_POST['commands'])) : ''; + $data['allhour'] = isset($_POST['allhour']) ? true : false; + $data['hour'] = isset($_POST['hour']) ? $_POST['hour'] : '00'; + $data['minute'] = isset($_POST['minute']) ? $_POST['minute'] : '00'; + $data['week'] = (isset($_POST['week']) AND is_array($_POST['week'])) ? $_POST['week'] : array(); + + $sql->query('INSERT INTO `crontab` set `server`="'.$id.'"'); + $cid = $sql->id(); + + include(LIB.'games/games.php'); + + $cron_rule = games::crontab($data, $id, $cid); + + $ssh->set('echo "'.$cron_rule.'" >> /etc/crontab;' + ."sed -i '/^$/d' /etc/crontab;" + .'crontab -u root /etc/crontab'); + + $time = games::crontab_time($data['allhour'], $data['hour'], $data['minute']); + $week = games::crontab_week($data['week']); + + $sql->query('UPDATE `crontab` set `server`="'.$id.'", `task`="'.$data['task'].'", `cron`="'.$cron_rule.'", `week`="'.$week.'", `time`="'.$time.'", `commands`="'.$data['commands'].'" WHERE `id`="'.$cid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $aTask = array( + 'start' => 'Включение сервера', + 'stop' => 'Выключение сервера', + 'restart' => 'Перезагрузка сервера', + 'console' => 'Отправка команд на сервер' + ); + + $sql->query('SELECT `id`, `task`, `week`, `time` FROM `crontab` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + while($crontab = $sql->get()) + { + $html->get('crontab_list', 'sections/servers/games/settings'); + $html->set('id', $crontab['id']); + $html->set('task', $aTask[$crontab['task']]); + $html->set('week', $crontab['week']); + $html->set('time', $crontab['time']); + $html->pack('crontab'); + } + + $html->get('crontab', 'sections/servers/'.$server['game'].'/settings'); + $html->set('id', $id); + $html->set('time', date('H:i:s', $start_point)); + + if($server['autostop']) + $html->unit('!autostop'); + else + $html->unit('!autostop', 1); + + $html->set('crontab', isset($html->arr['crontab']) ? $html->arr['crontab'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/file.php b/system/sections/servers/games/settings/file.php new file mode 100644 index 0000000..db980a1 --- /dev/null +++ b/system/sections/servers/games/settings/file.php @@ -0,0 +1,60 @@ +nav('Редактирование файла: '.$file); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + // Полный путь файла + $path = $tarif['install'].$server['uid'].'/'.$aEdits[$server['game']]['all']['path'][$file].$file; + if($go) + { + $data = isset($_POST['data']) ? $_POST['data'] : ''; + + $temp = sys::temp($data); + + // Отправление файла на сервер + $ssh->setfile($temp, $path, 0644); + + // Смена владельца/группы файла + $ssh->set('chown server'.$server['uid'].':servers '.$path); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $ssh->set('sudo -u server'.$server['uid'].' sh -c "touch '.$path.'; cat '.$path.'"'); + + $html->get('file', 'sections/servers/games/settings'); + + $html->set('id', $id); + $html->set('file', $file); + $html->set('data', htmlspecialchars($ssh->get())); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/firewall.php b/system/sections/servers/games/settings/firewall.php new file mode 100644 index 0000000..ae2c194 --- /dev/null +++ b/system/sections/servers/games/settings/firewall.php @@ -0,0 +1,39 @@ +nav('Блокировка на оборудовании'); + + if(isset($url['action'])) + { + include(LIB.'games/games.php'); + + // Получение информации адреса + if($url['action'] == 'info') + games::iptables_whois($nmch); + + // Добавление / удаление правил + if($go && in_array($url['action'], array('block', 'unblock'))) + { + $address = isset($_POST['address']) ? trim($_POST['address']) : sys::outjs(array('e' => sys::text('servers', 'firewall')), $nmch); + $snw = isset($_POST['subnetwork']) ? true : false; + + sys::outjs(games::iptables($id, $url['action'], $address, explode(':', $server['address']), $server['unit'], $snw), $nmch); + } + } + + $sql->query('SELECT `id`, `sip` FROM `firewall` WHERE `server`="'.$id.'" ORDER BY `id` ASC'); + + while($firewall = $sql->get()) + { + $html->get('list', 'sections/servers/games/settings/firewall'); + $html->set('id', $firewall['id']); + $html->set('address', $firewall['sip']); + $html->pack('firewall'); + } + + $html->get('firewall', 'sections/servers/games/settings'); + $html->set('id', $id); + $html->set('firewall', isset($html->arr['firewall']) ? $html->arr['firewall'] : ''); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/pack.php b/system/sections/servers/games/settings/pack.php new file mode 100644 index 0000000..93955f9 --- /dev/null +++ b/system/sections/servers/games/settings/pack.php @@ -0,0 +1,22 @@ +query('SELECT `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPacks = sys::b64djs($tarif['packs'], true); + + $pack = isset($url['pack']) ? $url['pack'] : exit; + + if($pack == $server['pack']) + sys::outjs(array('s' => 'ok')); + + // Проверка сборки + if(!array_key_exists($pack, $aPacks)) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $sql->query('UPDATE `servers` set `pack`="'.$pack.'" WHERE `id`="'.$id.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), 'server_settings_'.$id); +?> \ No newline at end of file diff --git a/system/sections/servers/games/settings/startlogs.php b/system/sections/servers/games/settings/startlogs.php new file mode 100644 index 0000000..b23c6ce --- /dev/null +++ b/system/sections/servers/games/settings/startlogs.php @@ -0,0 +1,98 @@ +nav('Снимки консоли'); + + $sql->query('SELECT `ftp`, `ftp_root`, `ftp_passwd` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + + // Путь к логам + $folder = $tarif['install'].$server['uid'].'/'.$aSLdir[$server['game']]; + + // Если выбран лог + if(isset($url['log'])) + { + if(sys::valid($url['log'], 'other', $aValid['startlogs'])) + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/startlogs'); + + $ssh->set('sudo -u server'.$server['uid'].' cat '.$folder.'/'.$url['log']); + + $html->get('view', 'sections/servers/games/settings/logs'); + $html->set('id', $id); + $html->set('name', $url['log']); + $html->set('log', htmlspecialchars($ssh->get(), NULL, '')); + $html->set('uri', 'startlogs'); + $html->pack('main'); + }else{ + if(isset($url['delall'])) + { + $ssh->set('cd '.$folder.' && rm *.log'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings/subsection/startlogs'); + } + + $ssh->set('cd '.$folder.' && du -ab --time | grep -e .log$ | awk \'{print $2" "$3"@"$1"@"$4}\' | sort -Mr'); + + // Массив данных + $aData = explode("\n", $ssh->get()); + + if(isset($aData[count($aData)-1])) + unset($aData[count($aData)-1]); + + $olds = $aSLdirFtp[$server['game']]; + + if($server['ftp_root'] || $cfg['ftp']['root'][$server['game']]) + $olds = $aSLdir[$server['game']]; + + // Построение списка + foreach($aData as $line => $log) + { + $aLog = explode('@', $log); + + // Название + $name = explode('/', $aLog[2]); + + if(count($name) > 2) + continue; + + // Дата + $date = sys::unidate($aLog[0]); + + // Вес + $size = sys::size($aLog[1]); + + $html->get('list', 'sections/servers/games/settings/startlogs'); + $html->set('id', $id); + $html->set('name', end($name)); + $html->set('date', $date); + $html->set('size', $size); + + if($server['ftp']) + { + $html->unit('download', true, true); + + $html->set('url', 'ftp://'.$server['uid'].':'.$server['ftp_passwd'].'@'.sys::first(explode(':', $unit['address'])).'/'.$olds.'/'.end($name)); + }else + $html->unit('download', false, true); + $html->pack('logs'); + } + + $html->get('startlogs', 'sections/servers/games/settings'); + $html->set('id', $id); + $html->set('uri', 'start'); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : ''); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif.php b/system/sections/servers/games/tarif.php new file mode 100644 index 0000000..3c5de6e --- /dev/null +++ b/system/sections/servers/games/tarif.php @@ -0,0 +1,61 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Тариф'); + + // Общий шаблон раздела + $html->get('tarif', 'sections/servers/games'); + + $html->set('id', $id); + + $html->pack('main'); + + // Шаблон продления + if($cfg['settlement_period']) + tarif::extend_sp($server, $tarif, $id); + else{ + $options = games::parse_time(explode(':', $tarif['timext']), $tarif['discount'], $server['tarif'], 'extend'); + + tarif::extend($options, $server, $tarif['name'], $id); + } + + // Если не тестовый период + if(!$server['test']) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Шаблон смены тарифа (если аренда не менее 1 дня и цены планов различны) + if($server['time'] > $start_point+86400 AND tarif::price($tarif['price'])) + tarif::plan($server, $tarif['name'], $id); + + // Шаблон изменения кол-ва слот + if($tarif['slots_min'] != $tarif['slots_max']) + tarif::slots($server, array('min' => $tarif['slots_min'], 'max' => $tarif['slots_max']), $id); + + // Шаблон изменения локации (если аренда не менее 1 дня) + if($server['time'] > $start_point+86400) + tarif::unit($server, $unit['name'], $tarif['name'], $id); + + // Шаблон покупки/аренды выделенного адреса + if($server['port'] != 27015) + tarif::address($server, $id); + } +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif/addextend.php b/system/sections/servers/games/tarif/addextend.php new file mode 100644 index 0000000..5daa0e4 --- /dev/null +++ b/system/sections/servers/games/tarif/addextend.php @@ -0,0 +1,39 @@ + +query('SELECT `id`, `aid`, `time` FROM `address_buy` WHERE `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('s' => 'ok'), $nmch); + + $add = $sql->get(); + + $sql->query('SELECT `price` FROM `address` WHERE `id`="'.$add['aid'].'" LIMIT 1'); + + $add = array_merge($add, $sql->get()); + + // Проверка баланса + if($user['balance'] < $add['price']) + sys::outjs(array('e' => 'У вас не хватает '.(round($add['price']-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$add['price']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $add['price']); + + // Обновление информации + $sql->query('UPDATE `address_buy` set `time`="'.($add['time']+2592000).'" WHERE `id`="'.$add['id'].'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_address'), + array('money' => $add['price'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$add['price'].'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif/address.php b/system/sections/servers/games/tarif/address.php new file mode 100644 index 0000000..0b4eeea --- /dev/null +++ b/system/sections/servers/games/tarif/address.php @@ -0,0 +1,64 @@ +query('SELECT `id` FROM `address_buy` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num() AND $go) + sys::outjs(array('s' => 'ok'), $nmch); + + $aid = isset($url['aid']) ? sys::int($url['aid']) : sys::outjs(array('e' => 'Переданы не все данные'), $nmch); + + $sql->query('SELECT `ip`, `price` FROM `address` WHERE `id`="'.$aid.'" AND `unit`="'.$server['unit'].'" AND `buy`="0" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Выделенный адрес не найден.'), $nmch); + + $add = $sql->get(); + + // Выполнение операции + if($go) + { + // Проверка баланса + if($user['balance'] < $add['price']) + sys::outjs(array('e' => 'У вас не хватает '.(round($add['price']-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + include(LIB.'ssh.php'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Проверка ssh соединения с локацией + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$add['price']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $add['price']); + + // Обновление информации + $sql->query('UPDATE `address` set `buy`="1" WHERE `id`="'.$aid.'" LIMIT 1'); + $sql->query('UPDATE `servers` set `address`="'.$add['ip'].':'.params::$aDefPort[$server['game']].'" WHERE `id`="'.$id.'" LIMIT 1'); + + $sql->query('INSERT INTO `address_buy` set `aid`="'.$aid.'", `server`="'.$id.'", `time`="'.($start_point+2592000).'"'); + + // Порт игрового сервера + $port = explode(':', $server['address']); + + // Очистка правил FireWall + games::iptables($server['id'], 'remove', NULL, NULL, NULL, false, $ssh); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_address'), + array('money' => $add['price'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$add['price'].'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + sys::outjs(array('s' => $add['price'])); +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif/extend.php b/system/sections/servers/games/tarif/extend.php new file mode 100644 index 0000000..8c17ebe --- /dev/null +++ b/system/sections/servers/games/tarif/extend.php @@ -0,0 +1,71 @@ + с учетом промо-кода) + if(isset($url['promo']) || $aData['promo'] != '') + $promo = games::define_promo( + $aData['promo'], + $aData, + $tarif['discount'], + $sum, + 'extend' + ); + + // Использование промо-кода + if(is_array($promo)) + { + if(array_key_exists('sum', $promo)) + $sum = $promo['sum']; + else + $aData['time'] += $promo['days']*86400; // Кол-во дней аренды с учетом подарочных (промо-код) + } + + // Выполнение продления + if($go) + { + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $status = $server['status'] == 'overdue' ? '`status`="off",' : ''; + + // Время аренды + $time = $server['time'] < $start_point ? $start_point+$aData['time']*86400 : $server['time']+$aData['time']*86400; + + // Обновление информации + $sql->query('UPDATE `servers` set '.$status.' `time`="'.$time.'", `test`="0" WHERE `id`="'.$id.'" LIMIT 1'); + + // Продление адреса на 30 дней + if($add_sum) + $sql->query('UPDATE `address_buy` set `time`=`time`+"2592000" WHERE `server`="'.$id.'" LIMIT 1'); + + // Запись логов + if(!is_array($promo)) + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_server'), + array('days' => $days, + 'money' => $sum, + 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$sum.'"'); + else{ + $sql->query('UPDATE `servers` set `benefit`="'.$time.'" WHERE `id`="'.$id.'" LIMIT 1'); + $sql->query('INSERT INTO `promo_use` set `promo`="'.$promo['id'].'", `user`="'.$user['id'].'", `time`="'.$start_point.'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'extend_server_promo'), + array('days' => $days, + 'money' => $sum, + 'promo' => $promo['cod'], 'id' => $id)).'", `date`="'.$start_point.'", `type`="extend", `money`="'.$sum.'"'); + } + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп цены + sys::outjs(array('s' => $sum)); +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif/slots.php b/system/sections/servers/games/tarif/slots.php new file mode 100644 index 0000000..b298439 --- /dev/null +++ b/system/sections/servers/games/tarif/slots.php @@ -0,0 +1,128 @@ + '')); + + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `slots`="'.$slots.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // При возможности уменьшить + if($cfg['change_slots'][$server['game']]['down'] || $overdue) + { + // Проверка кол-ва слот + if($slots < $tarif['slots_min'] || $slots > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданые неверные данные.'), $nmch); + + if($server['slots'] == $slots) + { + if($go) + sys::outjs(array('s' => 'ok'), $nmch); + + sys::outjs(array('s' => 'Сервер будет арендован до: '.date('d.m.Y - H:i', $server['time']).' ('.sys::date('min', $server['time']).')'), $nmch); + } + }else{ + // Установлено макс. значение + if($server['slots'] == $tarif['slots_max'] AND !$overdue) + sys::outjs(array('e' => 'На игровом сервере установлено максимальное значение.'), $nmch); + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $slots += $server['slots']; + } + + $date = date('H.i.s.d.m.Y', round($start_point+$price_old/($price*$slots)*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + // При уменьшении кол-ва слот не добавлять дни + if($slots < $server['slots'] AND ($cfg['change_slots'][$server['game']]['days'] AND $cfg['change_slots'][$server['game']]['down'] AND !$cfg['change_slots'][$server['game']]['add'])) + $time = $server['time']; + + // Выполнение операции + if($go) + { + sys::benefitblock($id, $nmch); + + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `slots`="'.$slots.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change')) AND $slots < $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Сервер будет арендован до: '.$arenda.' '.date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')')); + } + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданые неверные данные'), $nmch); + + // Выполнение операции + if($go) + { + sys::benefitblock($id, $nmch); + + $slots_new = $server['slots']+$slots; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $start = $server['slots_start'] == $server['slots'] ? ', `slots_start`="'.$slots_new.'"' : ''; + + // Обновление информации + $sql->query('UPDATE `servers` set `slots`="'.$slots_new.'" '.$start.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart', 'change')) AND $slots_new != $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_slots'), + array('slots' => $slots, 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Цена за дополнительные слоты: '.$sum.' '.$cfg['currency'])); +?> \ No newline at end of file diff --git a/system/sections/servers/games/tarif/unit.php b/system/sections/servers/games/tarif/unit.php new file mode 100644 index 0000000..c5e4e81 --- /dev/null +++ b/system/sections/servers/games/tarif/unit.php @@ -0,0 +1,119 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $pack = isset($url['pack']) ? $url['pack'] : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + // Проверка сборки + if(!array_key_exists($pack, sys::b64djs($tarif['packs'], true))) + sys::outjs(array('e' => 'Сборка не найдена.')); + + $sql->query('SELECT `id`, `unit`, `port_min`, `port_max`, `hostname`, `path`, `install`, `map`, `plugins_install`, `hdd`, `autostop`, `core_fix`, `ip` FROM `tarifs` WHERE `id`="'.$tarif['id'].'" LIMIT 1'); + $tarif = array_merge(array('pack' => $pack), $sql->get()); + + $sql->query('SELECT `name`, `address`, `passwd` FROM `units` WHERE `id`="'.$tarif['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + // Выделенный адрес игрового сервера + if(!empty($tarif['ip'])) + { + $aIp = explode(':', $tarif['ip']); + + $ip = false; + $port = params::$aDefPort[$server['game']]; + + // Проверка наличия свободного адреса + foreach($aIp as $adr) + { + $adr = trim($adr); + + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$tarif['unit'].'" AND `address` LIKE "'.$adr.':%" LIMIT 1'); + if(!$sql->num()) + { + $ip = $adr; + + break; + } + } + }else{ + $ip = sys::first(explode(':', $unit['address'])); + $port = false; + + // Проверка наличия свободного порта + for($tarif['port_min']; $tarif['port_min'] <= $tarif['port_max']; $tarif['port_min']+=1) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$tarif['unit'].'" AND `port`="'.$tarif['port_min'].'" LIMIT 1'); + if(!$sql->num()) + { + $port = $tarif['port_min']; + + break; + } + } + } + + $core = 0; + + if($tarif['core_fix'] != '') + { + $aCore = explode(',', $tarif['core_fix']); + + foreach($aCore as $cpu) + { + $sql->query('SELECT `id` FROM `servers` WHERE `unit`="'.$tarif['unit'].'" AND `tarif`="'.$tarif['id'].'" AND `core_fix`="'.$cpu.'" AND `core_fix_one`="1" LIMIT 1'); + + if($sql->num()) + continue; + + $core = $cpu; + $tarif['core_fix'] = $cpu; + + break; + } + } + + if(!$ip || !$port || !$core) + sys::outjs(array('e' => 'К сожалению нет доступных мест, обратитесь в тех.поддержку.')); + + $server['id'] = $id; + + // Време аренды + $tarif['time'] = $time; + + include(LIB.'ssh.php'); + + // Удаление данных с текущей локации + tarif::unit_old($oldTarif, $oldUnit, $server, $nmch); + + $mcache->delete('server_filetp_'.$id); + + $adUnit = explode(':', $unit['address']); + + $server['address'] = $ip.':'.$port; + + // Создание сервера на новой локации + tarif::unit_new($tarif, $unit, $server, $nmch); + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_unit').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Генерация списка сборок + $packs = ''; + $aPack = sys::b64djs($tarif['packs'], true); + + if(is_array($aPack)) + foreach($aPack as $index => $name) + $packs .= ''; + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')', 'p' => $packs)); +?> \ No newline at end of file diff --git a/system/sections/servers/graph.php b/system/sections/servers/graph.php new file mode 100644 index 0000000..2ca88cb --- /dev/null +++ b/system/sections/servers/graph.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `user`, `address`, `game`, `status`, `slots_start`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'graph'); + + include(sys::route($server, 'graph', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/index.php b/system/sections/servers/index.php new file mode 100644 index 0000000..497a567 --- /dev/null +++ b/system/sections/servers/index.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'index'); + + include(SEC.'servers/'.$server['game'].'/index.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/list.php b/system/sections/servers/list.php new file mode 100644 index 0000000..c145ee1 --- /dev/null +++ b/system/sections/servers/list.php @@ -0,0 +1,113 @@ +query('SELECT `unit`, `tarif` FROM `servers` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + $n = $sql->num($q_Servers); + + $aUnits = array(); + $aTarifs = array(); + + // Проверка массивов в кеше + if(is_array($mcache->get('aut_'.$user['id'])) AND $mcache->get('nser_'.$user['id']) == $n) + { + $aUT = $mcache->get('aut_'.$user['id']); + $aUnits = $aUT[0]; + $aTarifs = $aUT[1]; + }else{ + while($server = $sql->get($q_Servers)) + { + if(!array_key_exists($server['unit'], $aUnits)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $aUnits[$server['unit']] = array( + 'name' => $unit['name'] + ); + } + + if(!array_key_exists($server['tarif'], $aTarifs)) + { + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aTarifs[$server['tarif']] = array( + 'name' => $tarif['name'], + 'packs' => sys::b64djs($tarif['packs']) + ); + } + } + + // Запись массивов в кеш + $mcache->set('aut_'.$user['id'], array($aUnits, $aTarifs), false, 60); + + // Запись кол-во серверов в кеш + $mcache->set('nser_'.$user['id'], $n, false, 60); + } + + include(LIB.'games/games.php'); + + $sql->query('SELECT ' + .'`id`,' + .'`unit`,' + .'`tarif`,' + .'`address`,' + .'`game`,' + .'`slots_start`,' + .'`online`,' + .'`status`,' + .'`name`,' + .'`pack`,' + .'`fps`,' + .'`tickrate`,' + .'`ram`,' + .'`map`,' + .'`time`,' + .'`date`,' + .'`overdue`' + .' FROM `servers` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + $wait_servers = ''; + $updates_servers = ''; + + while($server = $sql->get()) + { + $btn = sys::buttons($server['id'], $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('list', 'sections/servers'); + + $html->set('id', $server['id']); + $html->set('unit', $aUnits[$server['unit']]['name']); + $html->set('tarif', + games::info_tarif( + $server['game'], + $aTarifs[$server['tarif']]['name'], + array('fps' => $server['fps'], 'tickrate' => $server['tickrate'], 'ram' => $server['ram']) + ) + ); + + $html->set('pack', $aTarifs[$server['tarif']]['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('fps', $server['fps']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img', $server['game'])); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('list'); + + $wait_servers .= $server['id'].':false,'; + $updates_servers .= 'setTimeout(function() {update_info(\''.$server['id'].'\', true)}, 5000); setTimeout(function() {update_status(\''.$server['id'].'\', true)}, 10000);'; + } +?> \ No newline at end of file diff --git a/system/sections/servers/maps.php b/system/sections/servers/maps.php new file mode 100644 index 0000000..2bc0c1a --- /dev/null +++ b/system/sections/servers/maps.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'maps'); + + include(sys::route($server, 'maps', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/console.php b/system/sections/servers/mc/console.php new file mode 100644 index 0000000..3e7765f --- /dev/null +++ b/system/sections/servers/mc/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/'; + + $filecmd = $dir.'console.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/copy.php b/system/sections/servers/mc/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/mc/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mc/graph.php b/system/sections/servers/mc/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/mc/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mc/index.php b/system/sections/servers/mc/index.php new file mode 100644 index 0000000..f8fe3bd --- /dev/null +++ b/system/sections/servers/mc/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue`, `ram` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name'].' / '.$server['ram'].' RAM'); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], 'mc', 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/owners.php b/system/sections/servers/mc/owners.php new file mode 100644 index 0000000..db63c5e --- /dev/null +++ b/system/sections/servers/mc/owners.php @@ -0,0 +1,169 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'reinstall' => 'Переустановка', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"' + ); + + $aAccess = array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mc/plugins.php b/system/sections/servers/mc/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/mc/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/mc/settings.php b/system/sections/servers/mc/settings.php new file mode 100644 index 0000000..132d29b --- /dev/null +++ b/system/sections/servers/mc/settings.php @@ -0,0 +1,72 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'firewall', 'crontab', 'startlogs', 'pack', 'file', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/mc/settings/server.php b/system/sections/servers/mc/settings/server.php new file mode 100644 index 0000000..1d9c622 --- /dev/null +++ b/system/sections/servers/mc/settings/server.php @@ -0,0 +1,109 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).'='.$val.PHP_EOL; + + // Временый файл + $temp = sys::temp($config); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.properties', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/server.properties'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.properties + $file = $tarif['install'].$server['uid'].'/server.properties'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode('=', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.'=', '', $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/settings/start.php b/system/sections/servers/mc/settings/start.php new file mode 100644 index 0000000..6e1d332 --- /dev/null +++ b/system/sections/servers/mc/settings/start.php @@ -0,0 +1,47 @@ +nav('Параметры запуска'); + + $sql->query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/tarif.php b/system/sections/servers/mc/tarif.php new file mode 100644 index 0000000..c0e19f0 --- /dev/null +++ b/system/sections/servers/mc/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price`, `ram` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'plan', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/tarif/extend.php b/system/sections/servers/mc/tarif/extend.php new file mode 100644 index 0000000..1c37b4a --- /dev/null +++ b/system/sections/servers/mc/tarif/extend.php @@ -0,0 +1,53 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $ram = $server['slots_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['ram'] = $ram; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + $aPrice = explode(':', $tarif['price']); + + // Цена за 30 дней 1 слота + $price = $aPrice[array_search($ram, explode(':', $tarif['ram']))]; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/tarif/plan.php b/system/sections/servers/mc/tarif/plan.php new file mode 100644 index 0000000..36b0445 --- /dev/null +++ b/system/sections/servers/mc/tarif/plan.php @@ -0,0 +1,70 @@ + 'Переданые не все данные'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + // Проверка плана + if(array_search($plan, $aRAM) === FALSE) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $ram = $server['slots_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + if($plan == $ram) + sys::outjs(array('e' => 'Смысла в этой операции нет'), $nmch); + + if(!tarif::price($tarif['price'])) + sys::outjs(array('e' => 'Чтобы изменить тариф, перейдите в настройки запуска'), $nmch); + + if($server['time'] < $start_point+86400) + $time = $server['time']; + else{ + // Цена за 1 день аренды (по новому тарифному плану) + $price = $aPrice[array_search($plan, $aRAM)]/30*$server['slots']; + + // Цена за 1 день аренды (по старому тарифному плану) + $price_old = $aPrice[array_search($ram, $aRAM)]/30*$server['slots']; + + // Остаток дней аренды + $days = ($server['time']-$start_point)/86400; + + $time = date('H:i:s', $server['time']); + $date = date('d.m.Y', round($start_point+$days*$price_old/$price*86400-86400)); + + $aDate = explode('.', $date); + $aTime = explode(':', $time); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2]); + } + + $plan = $server['slots_fix'] ? $plan : $plan*$server['slots']; + + // Выполнение смена тарифного плана + if($go) + { + sys::benefitblock($id, $nmch); + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `ram`="'.$plan.'" WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart'))) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_plan').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/tarif/slots.php b/system/sections/servers/mc/tarif/slots.php new file mode 100644 index 0000000..efaccf8 --- /dev/null +++ b/system/sections/servers/mc/tarif/slots.php @@ -0,0 +1,162 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $aPrice[array_search($ram, $aRAM)]/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($aPrice[array_search($ram, $aRAM)]/30)*$slots, 2); + + // Изменение кол-ва слот за счет пересчета дней аренды или закончился срок аренды (иначе аренда дополнительных слот) + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']*$slots; + + // Если просрочен + if($overdue) + { + sys::outjs(array('i' => '')); + + if($go) + { + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `slots`="'.$slots.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // При возможности уменьшить + if($cfg['change_slots'][$server['game']]['down'] || $overdue) + { + // Проверка кол-ва слот + if($slots < $tarif['slots_min'] || $slots > $tarif['slots_max']) + sys::outjs(array('e' => 'Переданые неверные данные.'), $nmch); + + if($server['slots'] == $slots) + { + if($go) + sys::outjs(array('s' => 'ok'), $nmch); + + sys::outjs(array('s' => 'Сервер будет арендован до: '.date('d.m.Y - H:i', $server['time']).' ('.sys::date('min', $server['time']).')'), $nmch); + } + }else{ + // Установлено макс. значение + if($server['slots'] == $tarif['slots_max'] AND !$overdue) + sys::outjs(array('e' => 'На игровом сервере установлено максимальное значение.'), $nmch); + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + $slots += $server['slots']; + } + + $date = date('H.i.s.d.m.Y', round($start_point+$price_old/($price*$slots)*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + // При уменьшении кол-ва слот не добавлять дни + if($slots < $server['slots'] AND ($cfg['change_slots'][$server['game']]['days'] AND $cfg['change_slots'][$server['game']]['down'] AND !$cfg['change_slots'][$server['game']]['add'])) + $time = $server['time']; + + // Выполнение операции + if($go) + { + sys::benefitblock($id, $nmch); + + $start = $server['slots_start'] > $slots ? ', `slots_start`="'.$slots.'"' : ''; + + $sql->query('UPDATE `servers` set `time`="'.$time.'", `slots`="'.$slots.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart')) AND $slots < $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs_sys` set `user`="'.$user['id'].'", `server`="'.$id.'", `text`="'.sys::text('syslogs', 'change_slots').'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Сервер будет арендован до: '.$arenda.' '.date('d.m.Y - H:i', $time).' ('.sys::date('min', $time).')')); + } + + if($slots < 1 || $slots > $max) + sys::outjs(array('e' => 'Переданые неверные данные'), $nmch); + + // Выполнение операции + if($go) + { + sys::benefitblock($id, $nmch); + + $slots_new = $server['slots']+$slots; + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency']), $nmch); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $start = $server['slots_start'] == $server['slots'] ? ', `slots_start`="'.$slots_new.'"' : ''; + + $ram = $server['ram_fix'] ? $server['ram'] : $server['ram']/$server['slots']*$slots_new; + + // Обновление информации + $sql->query('UPDATE `servers` set `slots`="'.$slots_new.'" '.$start.', `ram`='.$ram.' WHERE `id`="'.$id.'" LIMIT 1'); + + if(in_array($server['status'], array('working', 'start', 'restart')) AND $slots_new != $server['slots_start']) + { + include(LIB.'games/'.$server['game'].'/action.php'); + + action::start($id, 'restart'); + } + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_slots'), + array('slots' => $slots, 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Выхлоп информации + sys::outjs(array('s' => 'Цена за дополнительные слоты: '.$sum.' '.$cfg['currency'])); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/tarif/unit.php b/system/sections/servers/mc/tarif/unit.php new file mode 100644 index 0000000..ddc5efc --- /dev/null +++ b/system/sections/servers/mc/tarif/unit.php @@ -0,0 +1,52 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `ram`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aRAMold = explode(':', $oldTarif['ram']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aRAM = explode(':', $tarif['ram']); + + $ram = $server['slots_fix'] ? $server['ram'] : $server['ram']/$server['slots']; + + if(!in_array($ram, $aRAM)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($ram, $aRAM)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($ram, $aRAMold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mc/web.php b/system/sections/servers/mc/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/mc/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/console.php b/system/sections/servers/mta/console.php new file mode 100644 index 0000000..7cd0730 --- /dev/null +++ b/system/sections/servers/mta/console.php @@ -0,0 +1,67 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + $command = isset($_POST['command']) ? sys::cmd($_POST['command']) : ''; + + if($server['status'] == 'off') + { + if($command) + sys::outjs(array('e' => sys::text('servers', 'off'))); + + sys::out(sys::text('servers', 'off')); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($command) + sys::outjs(array('e' => sys::text('error', 'ssh'))); + + sys::out(sys::text('error', 'ssh')); + } + + $dir = $tarif['install'].$server['uid'].'/mods/deathmatch/'; + + $filecmd = $dir.'logs/server.log'; + + if($command) + { + if(strtolower($command) == 'clear') + $ssh->set('sudo -u server'.$server['uid'].' sh -c "echo \"Очистка консоли\n\" > '.$filecmd.'"'); + else + $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff "'.$command.'"\015\';' + .'sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval \'stuff \015\''); + + sys::outjs(array('s' => 'ok')); + } + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/copy.php b/system/sections/servers/mta/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/mta/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/graph.php b/system/sections/servers/mta/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/mta/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/index.php b/system/sections/servers/mta/index.php new file mode 100644 index 0000000..9ca3443 --- /dev/null +++ b/system/sections/servers/mta/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], 'samp', 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/owners.php b/system/sections/servers/mta/owners.php new file mode 100644 index 0000000..db63c5e --- /dev/null +++ b/system/sections/servers/mta/owners.php @@ -0,0 +1,169 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'reinstall' => 'Переустановка', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"' + ); + + $aAccess = array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/plugins.php b/system/sections/servers/mta/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/mta/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/settings.php b/system/sections/servers/mta/settings.php new file mode 100644 index 0000000..fb529e4 --- /dev/null +++ b/system/sections/servers/mta/settings.php @@ -0,0 +1,72 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'file', 'firewall', 'crontab', 'startlogs', 'pack', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 20); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/mta/settings/start.php b/system/sections/servers/mta/settings/start.php new file mode 100644 index 0000000..11b9d0a --- /dev/null +++ b/system/sections/servers/mta/settings/start.php @@ -0,0 +1,52 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + + case 'autorestart': + if($value != $server['autorestart']) + $sql->query('UPDATE `servers` set `autorestart`="'.$value.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/tarif.php b/system/sections/servers/mta/tarif.php new file mode 100644 index 0000000..c321da7 --- /dev/null +++ b/system/sections/servers/mta/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/tarif/extend.php b/system/sections/servers/mta/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/servers/mta/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/tarif/slots.php b/system/sections/servers/mta/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/servers/mta/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/tarif/unit.php b/system/sections/servers/mta/tarif/unit.php new file mode 100644 index 0000000..b840bc7 --- /dev/null +++ b/system/sections/servers/mta/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aTICKold = explode(':', $oldTarif['tickrate']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + if(!in_array($server['tickrate'], $aTICK)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['tickrate'], $aTICKold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/mta/web.php b/system/sections/servers/mta/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/mta/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/noaccess.php b/system/sections/servers/noaccess.php new file mode 100644 index 0000000..db9cd53 --- /dev/null +++ b/system/sections/servers/noaccess.php @@ -0,0 +1,24 @@ +nav('Раздел недоступен'); + + if($server['time'] < $start_point) + $html->get('overdue'); + else{ + $status = array( + 'install' => 'установки', + 'reinstall' => 'переустановки', + 'update' => 'обновления', + 'recovery' => 'восстановления', + 'blocked' => 'блокировки' + ); + + $html->get('noaccess'); + + $html->set('status', $status[$server['status']]); + } + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/owners.php b/system/sections/servers/owners.php new file mode 100644 index 0000000..e639405 --- /dev/null +++ b/system/sections/servers/owners.php @@ -0,0 +1,11 @@ +query('SELECT `user`, `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'owners'); + + include(sys::route($server, 'owners', $go, true)); +?> \ No newline at end of file diff --git a/system/sections/servers/owners_list.php b/system/sections/servers/owners_list.php new file mode 100644 index 0000000..384f478 --- /dev/null +++ b/system/sections/servers/owners_list.php @@ -0,0 +1,125 @@ +query('SELECT `server` FROM `owners` WHERE `user`="'.$user['id'].'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC'); + + $n = $sql->num($owners); + + $aUnits = array(); + $aTarifs = array(); + + // Проверка массивов в кеше + if(is_array($mcache->get('owners_aut_'.$user['id'])) AND $mcache->get('owners_nser_'.$user['id']) == $n) + { + $aUT = $mcache->get('owners_aut_'.$user['id']); + $aUnits = $aUT[0]; + $aTarifs = $aUT[1]; + }else{ + while($owner = $sql->get($owners)) + { + $server_sql = $sql->query('SELECT `unit`, `tarif` FROM `servers` WHERE `id`="'.$owner['server'].'"'); + + while($server = $sql->get($server_sql)) + { + if(!array_key_exists($server['unit'], $aUnits)) + { + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $aUnits[$server['unit']] = array( + 'name' => $unit['name'] + ); + } + + if(!array_key_exists($server['tarif'], $aTarifs)) + { + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aTarifs[$server['tarif']] = array( + 'name' => $tarif['name'], + 'packs' => sys::b64djs($tarif['packs']) + ); + } + } + } + + // Запись массивов в кеш + $mcache->set('owners_aut_'.$user['id'], array($aUnits, $aTarifs), false, 60); + + // Запись кол-во серверов в кеш + $mcache->set('owners_nser_'.$user['id'], $n, false, 60); + } + + $owners = $sql->query('SELECT `id`, `server`, `time` FROM `owners` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + + while($owner = $sql->get($owners)) + { + if($owner['time'] < $start_point) + { + $sql->query('DELETE FROM `owners` WHERE `id`="'.$owner['id'].'" LIMIT 1'); + + continue; + } + + $sql->query('SELECT ' + .'`id`,' + .'`unit`,' + .'`tarif`,' + .'`address`,' + .'`game`,' + .'`slots_start`,' + .'`online`,' + .'`status`,' + .'`name`,' + .'`pack`,' + .'`fps`,' + .'`tickrate`,' + .'`ram`,' + .'`map`,' + .'`time`,' + .'`date`,' + .'`overdue`' + .' FROM `servers` WHERE `id`="'.$owner['server'].'" LIMIT 1'); + + while($server = $sql->get()) + { + $btn = sys::buttons($server['id'], $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('list', 'sections/servers'); + + $html->set('id', $server['id']); + $html->set('unit', $aUnits[$server['unit']]['name']); + $html->set('tarif', + games::info_tarif( + $server['game'], + $aTarifs[$server['tarif']]['name'], + array('fps' => $server['fps'], 'tickrate' => $server['tickrate'], 'ram' => $server['ram']) + ) + ); + + $html->set('pack', $aTarifs[$server['tarif']]['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('name', $server['name']); + $html->set('fps', $server['fps']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], $server['map'], 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('list'); + + $wait_servers .= $server['id'].':false,'; + $updates_servers .= 'setTimeout(function() {update_info(\''.$server['id'].'\', true)}, 5000); setTimeout(function() {update_status(\''.$server['id'].'\', true)}, 10000);'; + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/plugins.php b/system/sections/servers/plugins.php new file mode 100644 index 0000000..a7f1ec2 --- /dev/null +++ b/system/sections/servers/plugins.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'plugins'); + + include(sys::route($server, 'plugins', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/rcon.php b/system/sections/servers/rcon.php new file mode 100644 index 0000000..9694d70 --- /dev/null +++ b/system/sections/servers/rcon.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'rcon'); + + include(sys::route($server, 'rcon', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/console.php b/system/sections/servers/samp/console.php new file mode 100644 index 0000000..3c42b22 --- /dev/null +++ b/system/sections/servers/samp/console.php @@ -0,0 +1,44 @@ +query('SELECT `uid`, `unit`, `tarif`, `time_start` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + if($go) + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if($server['status'] == 'off') + sys::out(sys::text('servers', 'off')); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::out(sys::text('error', 'ssh')); + + $dir = $tarif['install'].$server['uid'].'/'; + + $filecmd = $dir.'server_log.txt'; + + $filecmd_copy = $dir.'oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log'; + + $weight = sys::int($ssh->get('du --block-size=1 '.$filecmd.' | awk \'{print $1}\'')); + + if($weight > 524288) + $ssh->set('sudo -u server'.$server['uid'].' sh -c "mkdir -p '.$dir.'oldstart; cat '.$filecmd.' >> '.$filecmd_copy.'; echo \"Выполнена очистка консоли, слишком большой объем данных\n\" > '.$filecmd.'"'); + + sys::out(htmlspecialchars($ssh->get('cat '.$filecmd), NULL, '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Консоль'); + + $html->get('console', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/copy.php b/system/sections/servers/samp/copy.php new file mode 100644 index 0000000..7a9c216 --- /dev/null +++ b/system/sections/servers/samp/copy.php @@ -0,0 +1,85 @@ + 'Игровой сервер должен быть выключен'), $nmch); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + include(SEC.'servers/games/copy/'.$url['subsection'].'.php'); + } + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Резервные копии'); + + if($mcache->get('server_copy_'.$id) != '') + $html->arr['main'] = $mcache->get('server_copy_'.$id); + else{ + // Построение списка создания копии + foreach(params::$section_copy[$server['game']]['aCopy'] as $name => $info) + { + $html->get('list', 'sections/servers/games/copy'); + + $html->set('name', $name); + $html->set('info', $info); + + $html->pack('list'); + } + + // Построение списка созданных копий + $sql->query('SELECT `id`, `server`, `info`, `date`, `status` FROM `copy` WHERE `user`="'.$server['user'].'_'.$server['unit'].'" AND `game`="'.$server['game'].'" ORDER BY `id` ASC'); + while($copy = $sql->get()) + { + $html->get('copy', 'sections/servers/games/copy'); + + $html->set('id', $copy['id']); + $html->set('info', $copy['info']); + $html->set('server', $copy['server']); + $html->set('date', sys::today($copy['date'])); + + if($copy['status']) + { + $html->unit('created', 1); + $html->unit('!created'); + }else{ + $html->unit('created'); + $html->unit('!created', 1); + } + + $html->pack('copy'); + } + + $html->get('copy', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->set('list', isset($html->arr['list']) ? $html->arr['list'] : ''); + $html->set('copy', isset($html->arr['copy']) ? $html->arr['copy'] : 'Резервные копии отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_copy_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/samp/graph.php b/system/sections/servers/samp/graph.php new file mode 100644 index 0000000..d8d8df8 --- /dev/null +++ b/system/sections/servers/samp/graph.php @@ -0,0 +1,71 @@ +query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + $graph = $sql->get(); + + $nmch = 'server_graph_full_'.$id; + + $time = isset($url['time']) ? $url['time'] : 'day'; + + if(!in_array($time, array('day', 'week', 'month'))) + $time = 'day'; + + // Выхлоп кеш графика + if($mcache->get($nmch) AND file_exists(TEMP.(md5($graph['key'].'full_'.$time)).'.png')) + { + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + include(LIB.'games/graph/pData.php'); + include(LIB.'games/graph/pDraw.php'); + include(LIB.'games/graph/pImage.php'); + + include(LIB.'games/graph.php'); + + graph::full($id, $server['slots_start'], $graph['key'], $time); + + $mcache->set($nmch, true, false, 300); + + header('Content-type: image/png'); + exit(file_get_contents(TEMP.(md5($graph['key'].'full_'.$time)).'.png')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Графики'); + + if($mcache->get('server_graph_'.$id) != '') + $html->arr['main'] = $mcache->get('server_graph_'.$id); + else{ + $sql->query('SELECT `key` FROM `graph` WHERE `server`="'.$id.'" LIMIT 1'); + + // Если отсутствует ключ, создать + if(!$sql->num()) + { + // Генерация ключа + $key = md5($id.sys::key('graph')); + + $sql->query('INSERT INTO `graph` set `server`="'.$id.'", `key`="'.$key.'", `time`="0"'); + }else{ + $graph = $sql->get(); + + $key = $graph['key']; + } + + $html->get('graph', 'sections/servers/games'); + + $html->set('id', $id); + + $html->set('key', $key); + $html->set('address', $server['address']); + $html->set('_img', '[img]'); + + $html->pack('main'); + + $mcache->set('server_graph_'.$id, $html->arr['main'], false, 4); + } +?> \ No newline at end of file diff --git a/system/sections/servers/samp/index.php b/system/sections/servers/samp/index.php new file mode 100644 index 0000000..9ca3443 --- /dev/null +++ b/system/sections/servers/samp/index.php @@ -0,0 +1,44 @@ +query('SELECT `unit`, `tarif`, `slots_start`, `online`, `players`, `name`, `pack`, `map`, `time`, `date`, `overdue` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address']); + + $sql->query('SELECT `name` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $btn = sys::buttons($id, $server['status'], $server['game']); + + $time_end = $server['status'] == 'overdue' ? 'Удаление через: '.sys::date('min', $server['overdue']+$cfg['server_delete']*86400) : 'Осталось: '.sys::date('min', $server['time']); + + $html->get('index', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('unit', $unit['name']); + $html->set('tarif', $tarif['name']); + + $tarif['packs'] = sys::b64djs($tarif['packs']); + + $html->set('pack', $tarif['packs'][$server['pack']]); + $html->set('address', $server['address']); + $html->set('game', $aGname[$server['game']]); + $html->set('slots', $server['slots_start']); + $html->set('online', $server['online']); + $html->set('players', base64_decode($server['players'])); + $html->set('name', $server['name']); + $html->set('status', sys::status($server['status'], $server['game'], $server['map'])); + $html->set('img', sys::status($server['status'], $server['game'], 'samp', 'img')); + $html->set('time_end', $time_end); + $html->set('time', sys::today($server['time'])); + $html->set('date', sys::today($server['date'])); + + $html->set('btn', $btn); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/owners.php b/system/sections/servers/samp/owners.php new file mode 100644 index 0000000..db63c5e --- /dev/null +++ b/system/sections/servers/samp/owners.php @@ -0,0 +1,169 @@ + 'Включение', + 'stop' => 'Выключение', + 'restart' => 'Перезагрузка', + 'reinstall' => 'Переустановка', + 'console' => 'Раздел "Консоль"', + 'settings' => 'Раздел "Настройки"', + 'plugins' => 'Раздел "Плагины"' + ); + + $aAccess = array('start', 'stop', 'restart', 'reinstall', 'console', 'settings', 'plugins'); + + // Проверка прав + if(isset($url['rights']) AND $url['rights'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['rights']).'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Совладелец не найден.')); + + $owner = $sql->get(); + + $aRights = sys::b64djs($owner['rights']); + + $rights = ''; + + foreach($aAccess as $access) + if($aRights[$access]) $rights .= $aAccessI[$access].', '; + + sys::outjs(array('s' => substr($rights, 0, -2))); + } + + // Удаление совладельца + if(isset($url['delete']) AND $url['delete'] > 0) + { + $sql->query('SELECT `rights` FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + if($sql->num()) + $sql->query('DELETE FROM `owners` WHERE `id`="'.sys::int($url['delete']).'" AND `server`="'.$id.'" LIMIT 1'); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/owners'); + } + + // Добавление совладельца + if($go) + { + $nmch = sys::rep_act('server_owners_go_'.$id, 5); + + $aData = (isset($_POST['owner']) AND is_array($_POST['owner'])) ? $_POST['owner'] : array(); + + $aDate = isset($aData['\'time\'']) ? explode('.', $aData['\'time\'']) : explode('.', date('d.m.Y', $start_point)); + $aTime = explode(':', date('H:i:s', $start_point)); + + if(!isset($aDate[1], $aDate[0], $aDate[2]) || !checkdate($aDate[1], $aDate[0], $aDate[2])) + sys::outjs(array('e' => 'Дата доступа указана неверно.'), $nmch); + + $time = mktime($aTime[0], $aTime[1], $aTime[2], $aDate[1], $aDate[0], $aDate[2])+3600; + + if($time < $start_point) + sys::outjs(array('e' => 'Время доступа не может быть меньше 60 минут.'), $nmch); + + // Проверка пользователя + if(!isset($aData['\'user\''])) + sys::outjs(array('e' => 'Необходимо указать пользователя.'), $nmch); + + if(is_numeric($aData['\'user\''])) + $sql->query('SELECT `id` FROM `users` WHERE `id`="'.$aData['\'user\''].'" LIMIT 1'); + else{ + if(sys::valid($aData['\'user\''], 'other', $aValid['login'])) + sys::outjs(array('e' => sys::text('input', 'login_valid')), $nmch); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['\'user\''].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Пользователь не найден в базе.'), $nmch); + + $uowner = $sql->get(); + + $owner = $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + + // Если не обновление доступа совладельца, проверить кол-во + if(!$sql->num($owner)) + { + $sql->query('SELECT `id` FROM `owners` WHERE `server`="'.$id.'" LIMIT 5'); + + if($sql->num() == 5) + sys::outjs(array('e' => 'Вы добавили максимально число совладельцев.'), $nmch); + } + + $sql->query('SELECT `id` FROM `servers` WHERE `id`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Владельца сервера нельзя добавить в совладельцы.'), $nmch); + + $aRights = array(); + + $check = 0; + + foreach($aAccess as $access) + { + $aRights[$access] = isset($aData['\''.$access.'\'']) ? 1 : 0; + + $check += $aRights[$access]; + } + + if(!$check) + sys::outjs(array('e' => 'Необходимо включить минимум одно разрешение.'), $nmch); + + + + if($sql->num($owner)) + $sql->query('UPDATE `owners` set `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'" WHERE `server`="'.$id.'" AND `user`="'.$uowner['id'].'" LIMIT 1'); + else + $sql->query('INSERT INTO `owners` set `server`="'.$id.'", `user`="'.$uowner['id'].'", `rights`="'.sys::b64js($aRights).'", `time`="'.$time.'"'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $html->nav('Друзья'); + + $cache = $mcache->get('server_owners_'.$id); + + if($cache != '') + $html->arr['main'] = $cache; + else{ + $owners = $sql->query('SELECT `id`, `user`, `rights`, `time` FROM `owners` WHERE `server`="'.$id.'" AND `time`>"'.$start_point.'" ORDER BY `id` ASC LIMIT 5'); + + if($sql->num()) + include(LIB.'games/games.php'); + + while($owner = $sql->get($owners)) + { + $sql->query('SELECT `login` FROM `users` WHERE `id`="'.$owner['user'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $uowner = $sql->get(); + + $rights = games::owners(sys::b64djs($owner['rights'])); + + $html->get('owners_list', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('oid', $owner['id']); + $html->set('user', $uowner['login']); + $html->set('rights', $rights); + $html->set('time', date('d.m.Y - H:i', $owner['time'])); + + $html->pack('owners'); + } + + $html->get('owners', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + $html->set('time', date('d.m.Y', $start_point)); + + $html->set('owners', isset($html->arr['owners']) ? $html->arr['owners'] : 'Для данного сервера совладельцы отсутсвуют.'); + + $html->pack('main'); + + $mcache->set('server_owners_'.$id, $html->arr['main'], false, 1); + } +?> \ No newline at end of file diff --git a/system/sections/servers/samp/plugins.php b/system/sections/servers/samp/plugins.php new file mode 100644 index 0000000..a116ca1 --- /dev/null +++ b/system/sections/servers/samp/plugins.php @@ -0,0 +1,158 @@ +query('SELECT `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + // Подразделы + $aSub = array('install', 'delete', 'update', 'plugin', 'config', 'search'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Плагины', $cfg['http'].'servers/id/'.$id.'/section/plugins'); + + $nmch = sys::rep_act('server_plugins_go_'.$id, 10); + + include(SEC.'servers/games/plugins/'.$url['subsection'].'.php'); + }else{ + $html->nav('Плагины'); + + // Если есть кеш + if($mcache->get('server_plugins_'.$id) != '') + $html->arr['main'] = $mcache->get('server_plugins_'.$id); + else{ + include(LIB.'games/plugins.php'); + + // Категории + $cats = $sql->query('SELECT `id`, `name` FROM `plugins_category` WHERE `game`="'.$server['game'].'" ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + // Плагины + $plugins = $sql->query('SELECT `id`, `name`, `desc`, `images`, `status`, `upd`, `packs`, `price` FROM `plugins` WHERE `cat`="'.$cat['id'].'" ORDER BY `sort`, `id` ASC'); + while($plugin = $sql->get($plugins)) + { + // Проверка, установлен ли плагин на сервер + $sql->query('SELECT `id` FROM `plugins_install` WHERE `server`="'.$id.'" AND `plugin`="'.$plugin['id'].'" LIMIT 1'); + if($sql->num()) + continue; + + // Проверка наличия обновленной версии плагина + if($plugin['upd']) + { + $idp = $plugin['id']; + + $sql->query('SELECT `name`, `desc`, `images`, `status`, `packs`, `price` FROM `plugins_update` WHERE `plugin`="'.$plugin['id'].'" ORDER BY `id` DESC LIMIT 1'); + if($sql->num()) + { + $plugin = $sql->get(); + + $plugin['id'] = $idp; + }else + $plugin['upd'] = 0; + } + + // Проверка на доступность плагина к установленной на сервере сборке + $packs = strpos($plugin['packs'], ':') ? explode(':',$plugin['packs']) : array($plugin['packs']); + if(!in_array($server['pack'], $packs) AND $plugin['packs'] != 'all') + continue; + + $images = plugins::images($plugin['images'], $plugin['id']); + + if($plugin['price']) + { + $sql->query('SELECT `id` FROM `plugins_buy` WHERE `plugin`="'.$plugin['id'].'" AND `server`="'.$id.'" LIMIT 1'); + $buy = $sql->num(); + } + + // Шаблон плагина + $html->get('plugin', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['id']); + + plugins::status($plugin['status']); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + if(!empty($images)) + { + $html->unit('images', 1); + $html->set('images', $images); + }else + $html->unit('images'); + + if(!$buy AND $plugin['price']) + { + $html->unit('price', true, true); + $html->set('price', $plugin['price']); + }else + $html->unit('price', false, true); + + $html->pack('plugins'); + } + + // Шаблон блока плагинов + $html->get('category', 'sections/servers/games/plugins'); + + $html->set('name', $cat['name']); + $html->set('plugins', isset($html->arr['plugins']) ? $html->arr['plugins'] : 'Доступных для установки плагинов нет.', 1); + + $html->pack('addons'); + } + + unset($cats, $cat, $plugins, $plugin); + + // Список установленных плагинов на сервер (отдельный блок) + $pl_ins = $sql->query('SELECT `plugin`, `upd`, `time` FROM `plugins_install` WHERE `server`="'.$id.'" ORDER BY `plugin`'); + while($plugin = $sql->get($pl_ins)) + { + $sql->query('SELECT `id` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $isUpd = $plugin['upd']; + + // Если установлен обновленный плагин + if($isUpd) + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins_update` WHERE `id`="'.$isUpd.'" LIMIT 1'); + else + $sql->query('SELECT `name`, `desc`, `status`, `cfg`, `upd` FROM `plugins` WHERE `id`="'.$plugin['plugin'].'" LIMIT 1'); + + $plugin = array_merge($plugin, $sql->get()); + + // Шаблон плагина + $html->get('plugin_install', 'sections/servers/games/plugins'); + + $html->set('id', $id); + $html->set('plugin', $plugin['plugin']); + + plugins::status($plugin['status']); + + if($plugin['cfg']) $html->unit('config', 1); else $html->unit('config'); + + if($plugin['upd']) $html->unit('update', 1); else $html->unit('update'); + + $html->set('name', htmlspecialchars_decode($plugin['name'])); + $html->set('time', sys::today($plugin['time'])); + $html->set('desc', htmlspecialchars_decode($plugin['desc'])); + + $html->pack('install'); + } + + $html->get('plugins', 'sections/servers/games'); + + $html->set('id', $id); + $html->set('addons', isset($html->arr['addons']) ? $html->arr['addons'] : ''); + $html->set('install', isset($html->arr['install']) ? $html->arr['install'] : 'Установленные плагины отсутствуют.'); + + $html->pack('main'); + + $mcache->set('server_plugins_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/samp/rcon.php b/system/sections/servers/samp/rcon.php new file mode 100644 index 0000000..1a0de70 --- /dev/null +++ b/system/sections/servers/samp/rcon.php @@ -0,0 +1,54 @@ + 'Необходимо выбрать игрока.')); + + if($url['action'] == 'kick') + rcon::cmd(array_merge($server, array('id' => $id)), 'kickid "'.$player.'" "EGP Panel"'); + else + rcon::cmd(array_merge($server, array('id' => $id)), 'sm_slay "'.$player.'"'); + + sys::outjs(array('s' => 'ok')); + } + + include(LIB.'geo.php'); + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $aPlayers = rcon::players(rcon::cmd(array_merge($server, array('id' => $id)))); + + foreach($aPlayers as $i => $aPlayer) + { + $html->get('player', 'sections/servers/'.$server['game'].'/rcon'); + + $html->set('i', $i); + $html->set('userid', $aPlayer['userid']); + $html->set('name', $aPlayer['name']); + $html->set('steamid', $aPlayer['steamid']); + $html->set('time', $aPlayer['time']); + $html->set('ping', $aPlayer['ping']); + $html->set('ip', $aPlayer['ip']); + $html->set('ico', $aPlayer['ico']); + $html->set('country', $aPlayer['country']); + + $html->pack('players'); + } + + sys::outjs(array('s' => isset($html->arr['players']) ? $html->arr['players'] : '')); + } + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + $html->nav('Rcon управление игроками'); + + $html->get('rcon', 'sections/servers/'.$server['game']); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/settings.php b/system/sections/servers/samp/settings.php new file mode 100644 index 0000000..b4de528 --- /dev/null +++ b/system/sections/servers/samp/settings.php @@ -0,0 +1,72 @@ +query('SELECT `uid`, `unit`, `tarif`, `pack` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + $html->nav($server['address'], $cfg['http'].'servers/id/'.$id); + + $aSub = array('start', 'server', 'firewall', 'crontab', 'startlogs', 'pack', 'file', 'api'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub)) + { + $html->nav('Настройки', $cfg['http'].'servers/id/'.$id.'/section/settings'); + + if($go) + $nmch = sys::rep_act('server_settings_go_'.$id, 10); + + if(in_array($url['subsection'], $aRouteSub['settings'])) + include(SEC.'servers/games/settings/'.$url['subsection'].'.php'); + else + include(SEC.'servers/'.$server['game'].'/settings/'.$url['subsection'].'.php'); + }else{ + $html->nav('Настройки'); + + if($mcache->get('server_settings_'.$id) != '') + $html->arr['main'] = $mcache->get('server_settings_'.$id); + else{ + $sql->query('SELECT `name`, `packs` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aEditslist = 1; + include(DATA.'filedits.php'); + + // Построение списка доступных сборок + $aPacks = sys::b64djs($tarif['packs']); + + $packs = ''; + unset($aPacks[$server['pack']]); + + foreach($aPacks as $pack => $desc) + $packs .= ''; + + include(SEC.'servers/'.$server['game'].'/settings/start.php'); + + $html->get('settings', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('packs', $packs); + $html->set('start', $html->arr['start']); + if(isset($html->arr['edits'])) + { + $html->set('edits', $html->arr['edits']); + $html->unit('edits', 1); + }else + $html->unit('edits'); + + $sql->query('SELECT `key` FROM `api` WHERE `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + { + $api = $sql->get(); + + $html->set('api', $api['key']); + $html->unit('api', 1, 1); + }else + $html->unit('api', 0, 1); + $html->pack('main'); + + $mcache->set('server_settings_'.$id, $html->arr['main'], false, 60); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/samp/settings/server.php b/system/sections/servers/samp/settings/server.php new file mode 100644 index 0000000..c9b07a5 --- /dev/null +++ b/system/sections/servers/samp/settings/server.php @@ -0,0 +1,119 @@ +nav('Параметры server.cfg'); + + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $sql->query('SELECT `install` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + { + if($go) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + sys::back($cfg['http'].'servers/id/'.$id.'/section/settings'); + } + + include(DATA.'scfg/'.$server['game'].'.php'); + + // Сохранение изменений + if($go) + { + $servercfg = isset($_POST['config']) ? $_POST['config'] : ''; + + $config = ''; + + $config_end = $servercfg['\'other\'']; + + unset($servercfg['\'other\'']); + + foreach($servercfg as $cvar => $val) + if($val != '') + $config .= str_replace("'", '', $cvar).' '.$val."\n"; + + // Временый файл + $temp = sys::temp($config.$config_end); + + $ssh->setfile($temp, $tarif['install'].$server['uid'].'/server.cfg', 0644); + + $ssh->set('chown server'.$server['uid'].':servers '.$tarif['install'].$server['uid'].'/server.cfg'); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + // Чтение файла - server.cfg + $file = $tarif['install'].$server['uid'].'/server.cfg'; + + $ssh->set('echo "" >> '.$file.' && cat '.$file.' | grep -ve "^#\|^[[:space:]]*$"'); + + $fScfg = explode("\n", strip_tags($ssh->get())); + + $servercfg = array(); + $other = ''; + + // Убираем пробелы и генерируем массив + foreach($fScfg as $line) + { + // имя квара + $cvar = sys::first(explode(' ', $line)); + + if($cvar == '') + continue; + + // убираем имя квара и оставляем только значение + $value = str_replace($cvar.' ', "", $line); + + // выбираем только то, что нам нужно + preg_match_all('~([^"]+)~', $value, $cvar_value, PREG_SET_ORDER); + + // Исключаем комментарии + if($cvar == '//') + continue; + + $val = sys::first(explode(' //', $cvar_value[0][1])); + + // Добавляем данные в массив + if(array_key_exists($cvar, $aScfg)) + $servercfg[$cvar] = trim($val); + else + $other .= $line."\n"; + } + + foreach($aScfg as $name => $desc) + { + if(!isset($servercfg[$name])) + $servercfg[$name] = ''; + + // Формирование формы + if(strpos($aScfg_form[$name], 'select')) + $form = str_replace('value="'.$servercfg[$name].'"', 'value="'.$servercfg[$name].'" selected="select"', $aScfg_form[$name]); + else + $form = str_replace('['.$name.']', $servercfg[$name], $aScfg_form[$name]); + + $html->get('servercfg_list', 'sections/servers/games/settings'); + + $html->set('name', $name); + $html->set('desc', $desc); + $html->set('form', $form); + + $html->pack('list'); + } + + $sql->query('UPDATE `servers` set `map_start`="'.htmlspecialchars($servercfg['rcon_password']).'" WHERE `id`="'.$id.'" LIMIT 1'); + + $html->get('servercfg', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('cfg', $html->arr['list']); + $html->set('other', $other); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/settings/start.php b/system/sections/servers/samp/settings/start.php new file mode 100644 index 0000000..862c835 --- /dev/null +++ b/system/sections/servers/samp/settings/start.php @@ -0,0 +1,45 @@ +query('SELECT `uid`, `slots`, `slots_start`, `autorestart` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = array_merge($server, $sql->get()); + + include(LIB.'games/games.php'); + + // Сохранение + if($go AND $url['save']) + { + $value = isset($url['value']) ? sys::int($url['value']) : sys::outjs(array('s' => 'ok'), $nmch); + + switch($url['save']) + { + case 'slots': + $slots = $value > $server['slots'] ? $server['slots'] : $value; + $slots = $value < 2 ? 2 : $slots; + + if($slots != $server['slots_start']) + $sql->query('UPDATE `servers` set `slots_start`="'.$slots.'" WHERE `id`="'.$id.'" LIMIT 1'); + + $mcache->delete('server_settings_'.$id); + sys::outjs(array('s' => 'ok'), $nmch); + } + } + + // Генерация списка слот + $slots = ''; + + for($slot = 2; $slot <= $server['slots']; $slot+=1) + $slots .= ''; + + // Авторестарт при зависании + $autorestart = $server['autorestart'] ? '' : ''; + + $html->get('start', 'sections/servers/'.$server['game'].'/settings'); + + $html->set('id', $id); + $html->set('autorestart', $autorestart); + $html->set('slots', str_replace('"'.$server['slots_start'].'"', '"'.$server['slots_start'].'" selected="select"', $slots)); + + $html->pack('start'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/tarif.php b/system/sections/servers/samp/tarif.php new file mode 100644 index 0000000..c321da7 --- /dev/null +++ b/system/sections/servers/samp/tarif.php @@ -0,0 +1,12 @@ +query('SELECT `name`, `slots_min`, `slots_max`, `install`, `timext`, `discount`, `price` FROM `tarifs` WHERE `id`="'.$server['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Подразделы + $aSub = array('extend', 'address', 'addextend', 'unit', 'slots'); + + include(SEC.'servers/games/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/tarif/extend.php b/system/sections/servers/samp/tarif/extend.php new file mode 100644 index 0000000..cf31b1e --- /dev/null +++ b/system/sections/servers/samp/tarif/extend.php @@ -0,0 +1,48 @@ + 'Переданы не все данные'), $nmch); + + // Проверка периода + if(!in_array($aData['time'], explode(':', $tarif['timext']))) + sys::outjs(array('e' => 'Переданы неверные данные'), $nmch); + + } + + $aData['promo'] = isset($_POST['promo']) ? $_POST['promo'] : ''; + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : false; + $aData['server'] = $id; + $aData['user'] = $server['user']; + $aData['tarif'] = $server['tarif']; + $aData['slots'] = $server['slots']; + + // Цена за выделенный адрес + $add_sum = tarifs::address_add_sum($aData['address'], $server); + + // Цена за 30 дней 1 слота + $price = $tarif['price']; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = $server['time']; + + // Цена аренды + $sum = games::define_sum($tarif['discount'], $price, $server['slots'], $aData['time'], 'extend')+$add_sum; + + // Если расчетный период + if($cfg['settlement_period']) + $aData['time'] = games::define_period('extend', params::$aDayMonth, $server['time']); + + $days = params::$aDayMonth[date('n', $server['time'])] == $aData['time'] ? 'месяц' : games::parse_day($aData['time'], true); + + include(SEC.'servers/games/tarif/extend.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/tarif/slots.php b/system/sections/servers/samp/tarif/slots.php new file mode 100644 index 0000000..3a60d63 --- /dev/null +++ b/system/sections/servers/samp/tarif/slots.php @@ -0,0 +1,31 @@ + 'На данном тарифе нельзя изменить количество слот.'), $nmch); + + $slots = isset($url['slots']) ? sys::int($url['slots']) : sys::outjs(array('e' => 'Переданы не все данные.'), $nmch); + + $overdue = $server['time'] < $start_point; + + if($cfg['change_slots'][$server['game']]['days'] || $overdue) + { + // Цена за 1 день + $price = $tarif['price']/30; + + // Цена аренды за остаток дней (с текущим кол-вом слот) + $price_old = ($server['time']-$start_point)/86400*$price*$server['slots']; + } + + $max = $tarif['slots_max']-$server['slots']; + + // Сумма за добавляемые слоты + $sum = round(($server['time']-$start_point)/86400*($tarif['price']/30)*$slots, 2); + + include(SEC.'servers/games/tarif/slots.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/tarif/unit.php b/system/sections/servers/samp/tarif/unit.php new file mode 100644 index 0000000..b840bc7 --- /dev/null +++ b/system/sections/servers/samp/tarif/unit.php @@ -0,0 +1,50 @@ + 'Переданы не все данные.'), $nmch); + + if(!$cfg['change_unit'][$server['game']] || $server['time'] < $start_point+86400 || $server['test']) + exit; + + $sql->query('SELECT `id`, `unit`, `packs`, `tickrate`, `price` FROM `tarifs` WHERE `unit`="'.$uid.'" AND `game`="'.$server['game'].'" AND `name`="'.$tarif['name'].'" AND `id`!="'.$server['tarif'].'" AND `show`="1" ORDER BY `unit`'); + if(!$sql->num()) + sys::outjs(array('e' => 'Не найден подходящий тариф.'), $nmch); + + $oldTarif = $tarif; + + $tarif = $sql->get(); + + $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $oldUnit = $sql->get(); + + $aPriceold = explode(':', $oldTarif['price']); + $aTICKold = explode(':', $oldTarif['tickrate']); + + $sql->query('SELECT `id` FROM `units` WHERE `id`="'.$tarif['unit'].'" AND `show`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Выбранная локация не доступна.'), $nmch); + + $aPrice = explode(':', $tarif['price']); + $aTICK = explode(':', $tarif['tickrate']); + + if(!in_array($server['tickrate'], $aTICK)) + sys::outjs(array('e' => 'Не найден подходящий тарифный план.'), $nmch); + + // Цена за 1 день (при новом тарифном плане) + $price = $aPrice[array_search($server['tickrate'], $aTICK)]/30*$server['slots']; + + // Цена аренды за остаток дней (с текущим тарифным планом) + $oldprice = ($server['time']-$start_point)/86400*($aPriceold[array_search($server['tickrate'], $aTICKold)]/30*$server['slots']); + + $date = date('H.i.s.d.m.Y', round($start_point+$oldprice/$price*86400-86400)); + + $aDate = explode('.', $date); + + $time = mktime($aDate[0], $aDate[1], $aDate[2], $aDate[4], $aDate[3], $aDate[5]); + + include(SEC.'servers/games/tarif/unit.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/samp/web.php b/system/sections/servers/samp/web.php new file mode 100644 index 0000000..634e9b6 --- /dev/null +++ b/system/sections/servers/samp/web.php @@ -0,0 +1,87 @@ +nav($server['address'], $cfg['http'].'servers/id/'.$id); + + include(DATA.'web.php'); + + // Если выбран подраздел + if(isset($url['subsection']) AND in_array($url['subsection'], $aSub) AND in_array($url['action'], array_merge($aAction[$url['subsection']], array('install', 'manage')))) + { + if($go) + $nmch = sys::rep_act('server_web_go_'.$id, 10); + else + $html->nav('Web', $cfg['http'].'servers/id/'.$id.'/section/web'); + + include(SEC.'web/'.$url['subsection'].'/free/'.$url['action'].'.php'); + }else{ + $html->nav('Web'); + + if($mcache->get('server_web_'.$id) != '') + $html->arr['main'] = $mcache->get('server_web_'.$id); + else{ + // Услуги + foreach($aWeb[$server['game']] as $service => $active) + { + if($active) + { + if($service == 'hosting') + { + if(!$aWebVHTtype && !in_array($server['tarif'], $aWebVHT)) + continue; + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + continue; + } + + // Проверка на установку + switch($aWebInstall[$server['game']][$service]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$service.'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if($sql->num()) + $html->get('list_install', 'sections/servers/games/web'); + else + $html->get('list', 'sections/servers/games/web'); + + $html->set('id', $id); + $html->set('service', $service); + $html->set('name', $aWebname[$service]); + $html->set('desc', $aWebDesc[$service]); + + $html->pack($aWebType[$service]); + } + } + + // Блоки услуг + foreach($aWebTypeInfo[$server['game']] as $type => $name) + { + if(!isset($html->arr[$type])) + continue; + + $html->get('block', 'sections/servers/games/web'); + $html->set('name', $name); + $html->set('list', $html->arr[$type]); + $html->pack('web'); + } + + $html->get('web', 'sections/servers/'.$server['game']); + $html->set('id', $id); + $html->set('web', isset($html->arr['web']) ? $html->arr['web'] : 'Дополнительные услуги отсутствуют'); + $html->pack('main'); + + $mcache->set('server_web_'.$id, $html->arr['main'], false, 4); + } + } +?> \ No newline at end of file diff --git a/system/sections/servers/scan.php b/system/sections/servers/scan.php new file mode 100644 index 0000000..f2e2f23 --- /dev/null +++ b/system/sections/servers/scan.php @@ -0,0 +1,27 @@ +query('SELECT `game` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + include(LIB.'games/'.$server['game'].'/scan.php'); + + // Запрошена информация (статус, онлайн, название) + if(isset($url['mon'])) + sys::outjs(scan::mon($id)); + + // Запрошена информация (статус, онлайн, название, игроки) + if(isset($url['fmon'])) + sys::outjs(scan::mon($id, true)); + + // Запрошена информация (cpu, ram, hdd) + if(isset($url['resources'])) + sys::outjs(scan::resources($id)); + + // Запрошена информация (работает, меняется карта, переустанавливается) + if(isset($url['status'])) + sys::outjs(scan::status($id)); + + exit; +?> \ No newline at end of file diff --git a/system/sections/servers/settings.php b/system/sections/servers/settings.php new file mode 100644 index 0000000..d8dd817 --- /dev/null +++ b/system/sections/servers/settings.php @@ -0,0 +1,11 @@ +query('SELECT `unit`, `address`, `game`, `status`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'settings'); + + include(sys::route($server, 'settings', $go)); +?> \ No newline at end of file diff --git a/system/sections/servers/tarif.php b/system/sections/servers/tarif.php new file mode 100644 index 0000000..0d5bbfe --- /dev/null +++ b/system/sections/servers/tarif.php @@ -0,0 +1,18 @@ +query('SELECT `uid`, `unit`, `user`, `tarif`, `address`, `port`, `game`, `status`, `slots`, `slots_start`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time`, `test`, `fps`, `tickrate`, `ram`, `ram_fix` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'tarif'); + + if($server['status'] == 'blocked') + { + if($go) + sys::out('Раздел недоступен'); + + include(SEC.'servers/noaccess.php'); + }else + include(SEC.'servers/'.$server['game'].'/tarif.php'); +?> \ No newline at end of file diff --git a/system/sections/servers/web.php b/system/sections/servers/web.php new file mode 100644 index 0000000..ea2e3e5 --- /dev/null +++ b/system/sections/servers/web.php @@ -0,0 +1,11 @@ +query('SELECT `uid`, `unit`, `tarif`, `user`, `address`, `game`, `status`, `name`, `slots_start`, `plugins_use`, `ftp_use`, `console_use`, `stats_use`, `copy_use`, `web_use`, `time` FROM `servers` WHERE `id`="'.$id.'" LIMIT 1'); + $server = $sql->get(); + + sys::nav($server, $id, 'web'); + + include(sys::route($server, 'web', $go)); +?> \ No newline at end of file diff --git a/system/sections/services/control.php b/system/sections/services/control.php new file mode 100644 index 0000000..23a3362 --- /dev/null +++ b/system/sections/services/control.php @@ -0,0 +1,114 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + $aData = array( + 'address' => isset($_POST['address']) ? trim($_POST['address']) : 0, + 'passwd' => isset($_POST['passwd']) ? $_POST['passwd'] : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'limit' => isset($_POST['limit']) ? sys::int($_POST['limit']) : key(array_shift($cfg['control_limit'])) + ); + + if(sys::valid($aData['address'], 'ip')) + sys::outjs(array('e' => 'Указанный адрес имеет неправильный формат')); + + $sql->query('SELECT `id` FROM `control` WHERE `address`="'.$aData['address'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный сервер уже подключен')); + + if(sys::strlen($aData['passwd']) > 32) + sys::outjs(array('e' => 'Указанный пароль слишком длинный')); + + if(sys::valid($aData['passwd'], 'other', $aValid['passwd'])) + sys::outjs(array('e' => 'Пожалуйста, поменяйте пароль используя только латинские буквы и цифры')); + + if(!array_key_exists($aData['limit'], $cfg['control_limit'])) + $aData['limit'] = key(array_shift($cfg['control_limit'])); + + if(!in_array($aData['time'], $cfg['control_time'])) + $aData['time'] = array_shift($cfg['control_time']); + + $sum = games::define_sum(false, $cfg['control_limit'][$aData['limit']], 1, $aData['time']); + + // Проверка баланса + if($user['balance'] < $sum) + sys::outjs(array('e' => 'У вас не хватает '.(round($sum-$user['balance'], 2)).' '.$cfg['currency'])); + + include(LIB.'ssh.php'); + + // Проверка ssh соединения с физ. сервером + if(!$ssh->auth($aData['passwd'], $aData['address'])) + sys::outjs(array('e' => 'Не удалось создать связь с физическим сервером, проверьте адрес и пароль')); + + // Списание средств с баланса пользователя + $sql->query('UPDATE `users` set `balance`="'.($user['balance']-$sum).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Реф. система + games::part($user['id'], $sum); + + $days = $cfg['settlement_period'] ? games::define_period('buy', params::$aDayMonth) : $aData['time']; + + $sql->query('INSERT INTO `control` set ' + .'`user`="'.$user['id'].'",' + .'`address`="'.$aData['address'].'",' + .'`passwd`="'.$aData['passwd'].'",' + .'`time`="'.($start_point+$days*86400).'",' + .'`date`="'.$start_point.'",' + .'`limit`="'.$aData['limit'].'",' + .'`price`="'.$sum.'",' + .'`status`="install"'); + + $id = $sql->id(); + + // Запись логов + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'buy_control'), array('days' => games::parse_day($days, true), 'money' => $sum, 'id' => $id)).'", `date`="'.$start_point.'", `type`="buy", `money`="'.$sum.'"'); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + if(isset($url['get'])) + { + if(!isset($url['time']) || !in_array($url['time'], $cfg['control_time'])) + $url['time'] = array_shift($cfg['control_time']); + + if(!isset($url['limit']) || !array_key_exists($url['limit'], $cfg['control_limit'])) + $url['limit'] = key(array_shift($cfg['control_limit'])); + + sys::out(games::define_sum(false, $cfg['control_limit'][$url['limit']], 1, $url['time'])); + } + + $options = ''; + + foreach($cfg['control_time'] as $time) + $options .= ''; + + $limits = ''; + + foreach($cfg['control_limit'] as $limit => $price) + $limits .= ''; + + $html->get('index', 'sections/services/control'); + $html->set('time', $options); + $html->set('limit', $limits); + $html->set('cur', $cfg['currency']); + if($cfg['settlement_period']) + { + $html->set('date', date('d.m.Y', $start_point)); + $html->unit('settlement_period', true, true); + }else + $html->unit('settlement_period', false, true); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/services/crmp.php b/system/sections/services/crmp.php new file mode 100644 index 0000000..b76d999 --- /dev/null +++ b/system/sections/services/crmp.php @@ -0,0 +1,144 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/cs.php b/system/sections/services/cs.php new file mode 100644 index 0000000..ac7004f --- /dev/null +++ b/system/sections/services/cs.php @@ -0,0 +1,152 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'fps' => isset($_POST['fps']) ? sys::int($_POST['fps']) : 0, + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'fps' => sys::int($url['fps']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `fps`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPrice = explode(':', $tarif['price']); + + // Определение цены + $price = $aPrice[array_search($aGet['fps'], explode(':', $tarif['fps']))]; + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `fps`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `fps`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('fps', $aTarif['fps']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/csgo.php b/system/sections/services/csgo.php new file mode 100644 index 0000000..1e3c431 --- /dev/null +++ b/system/sections/services/csgo.php @@ -0,0 +1,152 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'tickrate' => isset($_POST['tickrate']) ? sys::int($_POST['tickrate']) : 0, + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'tickrate' => sys::int($url['tickrate']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `tickrate`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPrice = explode(':', $tarif['price']); + + // Определение цены + $price = $aPrice[array_search($aGet['tickrate'], explode(':', $tarif['tickrate']))]; + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('tickrate', $aTarif['tickrate']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/css.php b/system/sections/services/css.php new file mode 100644 index 0000000..1e3c431 --- /dev/null +++ b/system/sections/services/css.php @@ -0,0 +1,152 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'tickrate' => isset($_POST['tickrate']) ? sys::int($_POST['tickrate']) : 0, + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'tickrate' => sys::int($url['tickrate']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `tickrate`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPrice = explode(':', $tarif['price']); + + // Определение цены + $price = $aPrice[array_search($aGet['tickrate'], explode(':', $tarif['tickrate']))]; + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('tickrate', $aTarif['tickrate']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/cssold.php b/system/sections/services/cssold.php new file mode 100644 index 0000000..586446b --- /dev/null +++ b/system/sections/services/cssold.php @@ -0,0 +1,155 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'tickrate' => isset($_POST['tickrate']) ? sys::int($_POST['tickrate']) : 0, + 'fps' => isset($_POST['fps']) ? sys::int($_POST['fps']) : 0, + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'tickrate' => sys::int($url['tickrate']), + 'fps' => sys::int($url['fps']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `fps`, `tickrate`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPrice = sys::b64djs($tarif['price'], true); + + // Определение цены + $price = $aPrice[$aGet['tickrate'].'_'.$aGet['fps']]; + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `fps`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `tickrate`, `fps`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('tickrate', $aTarif['tickrate']); + $html->set('fps', $aTarif['fps']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/mc.php b/system/sections/services/mc.php new file mode 100644 index 0000000..69efcde --- /dev/null +++ b/system/sections/services/mc.php @@ -0,0 +1,152 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'ram' => isset($_POST['ram']) ? sys::int($_POST['ram']) : 0, + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'ram' => sys::int($url['ram']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `ram`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + $aPrice = explode(':', $tarif['price']); + + // Определение цены + $price = $aPrice[array_search($aGet['ram'], explode(':', $tarif['ram']))]; + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $price, $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `ram`, `param_fix`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `ram`, `param_fix`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('ram', $aTarif['ram']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/mta.php b/system/sections/services/mta.php new file mode 100644 index 0000000..b76d999 --- /dev/null +++ b/system/sections/services/mta.php @@ -0,0 +1,144 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/services/privileges.php b/system/sections/services/privileges.php new file mode 100644 index 0000000..2075f8c --- /dev/null +++ b/system/sections/services/privileges.php @@ -0,0 +1,225 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + $mcache->set($nmch, 1, false, 10); + + $aData = array(); + + $aData['address'] = isset($_POST['address']) ? $_POST['address'] : sys::outjs(array('e' => 'Необходимо указать адрес сервера'), $nmch); + $aData['type'] = isset($_POST['type']) ? $_POST['type'] : sys::outjs(array('e' => 'Необходимо указать тип авторизации на сервере'), $nmch); + $aData['data'] = isset($_POST['data']) ? str_replace('"', '', $_POST['data']) : sys::outjs(array('e' => 'Необходимо указать данные авторизации'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + $aData['service'] = isset($_POST['service']) ? sys::int($_POST['service']) : sys::outjs(array('e' => 'Необходимо указать услугу'), $nmch); + $aData['time'] = isset($_POST['time']) ? sys::int($_POST['time']) : sys::outjs(array('e' => 'Необходимо указать период'), $nmch); + $aData['mail'] = isset($_POST['mail']) ? $_POST['mail'] : sys::outjs(array('e' => 'Необходимо указать почту'), $nmch); + + if(!in_array($aData['type'], array('a', 'ca', 'de'))) + sys::outjs(array('e' => 'Неправильно передан тип авторизации на сервере'), $nmch); + + switch($aData['type']) + { + case 'a': + if($aData['data'] == '') + sys::outjs(array('e' => 'Необходимо указать ник'), $nmch); + break; + case 'ca': + if(sys::valid($aData['data'], 'steamid') || sys::valid($aData['data'], 'steamid3')) + sys::outjs(array('e' => 'Неправильный формат SteamID'), $nmch); + break; + default: + if(sys::valid($aData['data'], 'ip')) + sys::outjs(array('e' => 'Неправильный формат IP'), $nmch); + } + + if(sys::valid($aData['address'], 'other', $aValid['address'])) + sys::outjs(array('e' => 'Адрес игрового сервера имеет неверный формат'), $nmch); + + $sql->query('SELECT `id`, `name`, `game` FROM `servers` WHERE `address`="'.$aData['address'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Игровой сервер не найден в базе'), $nmch); + + $server = $sql->get(); + + $sql->query('SELECT `id` FROM `admins_'.$server['game'].'` WHERE `server`="'.$server['id'].'" AND `value`="'.htmlspecialchars($aData['data']).'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Привилегия для данного игрока уже установлена, дождитесь её завершения.'), $nmch); + + if($aData['type'] != 'de' AND sys::valid($aData['passwd'], 'other', $aValid['passwd'])) + sys::outjs(array('e' => 'Неправильный формат пароля, используйте латинские буквы и цифры от 6 до 20 символов'), $nmch); + + if(sys::valid($aData['mail'], 'other', $aValid['mail'])) + sys::outjs(array('e' => 'Неправильный формат почты'), $nmch); + + $sql->query('SELECT `flags`, `immunity`, `data` FROM `privileges_list` WHERE `id`="'.$aData['service'].'" AND `server`="'.$server['id'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Указанная услуга не найдена'), $nmch); + + $privilege = $sql->get(); + + $data = sys::b64djs($privilege['data']); + + if(!array_key_exists($aData['time'], $data)) + sys::outjs(array('e' => 'Неправильно указан период'), $nmch); + + $price = $data[$aData['time']]; + + $time = !$aData['time'] ? $start_point+172800000 : $start_point+$aData['time']*86400; + + if($server['game'] == 'cs') + { + $text = '"'.$aData['data'].'" "'.$aData['passwd'].'" "'.$privilege['flags'].'" "'.$aData['type'].'"'; + $sqlq = 'INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$server['id'].'",' + .'`value`="'.htmlspecialchars($aData['data']).'",' + .'`active`="1",' + .'`passwd`="'.$aData['passwd'].'",' + .'`flags`="'.$privilege['flags'].'",' + .'`type`="'.$aData['type'].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="Онлайн покупка"'; + }else{ + $text = '"'.$aData['data'].'" "'.$aData['immunity'].':'.$privilege['flags'].'" "'.$aData['passwd'].'"'; + $sqlq = 'INSERT INTO `admins_'.$server['game'].'` set' + .'`server`="'.$server['id'].'",' + .'`value`="'.$aData['data'].'",' + .'`active`="1",' + .'`passwd`="'.htmlspecialchars($aData['passwd']).'",' + .'`flags`="'.$aData['flags'].'",' + .'`immunity`="'.$privilege['immunity'].'",' + .'`time`="'.$time.'",' + .'`text`="'.htmlspecialchars($text).'",' + .'`info`="Онлайн покупка"'; + } + + $sql->query('SELECT `key` FROM `privileges_buy` WHERE ' + .'`server`="'.$server['id'].'" AND' + .'`text`="'.base64_encode($text).'" AND' + .'`price`="'.$price.'" AND' + .'`mail`="'.$aData['mail'].'" AND' + .'`status`="0" LIMIT 1'); + + if(!$sql->num()) + { + $key = sys::key(); + + $sql->query('INSERT INTO `privileges_buy` set ' + .'`server`="'.$server['id'].'",' + .'`text`="'.base64_encode($text).'",' + .'`sql`="'.base64_encode($sqlq).'",' + .'`price`="'.$price.'",' + .'`key`="'.$key.'",' + .'`date`="'.$start_point.'",' + .'`mail`="'.$aData['mail'].'",' + .'`status`="0"'); + }else{ + $pay = $sql->get(); + $key = $pay['key']; + } + + $html->get('pay', 'sections/services/privileges'); + + $html->set('cur', $cfg['currency']); + $html->set('wmr', $cfg['webmoney_wmr']); + $html->set('key', $key); + $html->set('sum', $price); + + $html->pack('pay'); + + sys::outjs(array('s' => $html->arr['pay']), $nmch); + } + + if(isset($url['select'])) + { + if($url['select'] == 'time') + { + $service = isset($url['service']) ? sys::int($url['service']) : sys::out(); + + $sql->query('SELECT `data` FROM `privileges_list` WHERE `id`="'.$service.'" LIMIT 1'); + $list = $sql->get(); + + $time = ''; + + $data = sys::b64djs($list['data']); + + if(isset($data[0])) + { + $time = ''; + + unset($data[0]); + } + + foreach($data as $days => $price) + $time .= ''; + + sys::out($time); + } + + $address = isset($_POST['address']) ? trim($_POST['address']) : sys::outjs(array('e' => 'Необходимо указать адрес игрового сервера')); + + if(sys::valid($address, 'other', $aValid['address'])) + sys::outjs(array('e' => 'Указанный адрес имеет неверный формат')); + + $sql->query('SELECT `id`, `name` FROM `servers` WHERE `address`="'.$address.'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Игровой сервер не найден в базе')); + + $server = $sql->get(); + + $sql->query('SELECT `active` FROM `privileges` WHERE `server`="'.$server['id'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Игровой сервер не предоставляет услуги')); + + $privilege = $sql->get(); + + if(!$privilege['active']) + sys::outjs(array('e' => 'Игровой сервер времено не предоставляет услуги')); + + $name = ''; + + $sql->query('SELECT `id`, `name` FROM `privileges_list` WHERE `server`="'.$server['id'].'" ORDER BY `id` ASC LIMIT 5'); + while($list = $sql->get()) + $name .= ''; + + $sql->query('SELECT `data` FROM `privileges_list` WHERE `server`="'.$server['id'].'" ORDER BY `id` ASC LIMIT 1'); + $list = $sql->get(); + + $time = ''; + + $data = sys::b64djs($list['data']); + + if(isset($data[0])) + { + $time = ''; + + unset($data[0]); + } + + foreach($data as $days => $price) + $time .= ''; + + $html->get('form', 'sections/services/privileges'); + + $html->set('home', $cfg['http']); + $html->set('name', $server['name']); + $html->set('address', $address); + $html->set('services', $name); + $html->set('time', $time); + + $html->pack('form'); + + sys::outjs(array('s' => $html->arr['form'])); + } + + $html->get('index', 'sections/services/privileges'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/services/samp.php b/system/sections/services/samp.php new file mode 100644 index 0000000..b76d999 --- /dev/null +++ b/system/sections/services/samp.php @@ -0,0 +1,144 @@ +get('buy_server')) + sleep(1.5); + + $mcache->set('buy_server', true, false, 3); + + include(LIB.'games/'.$section.'/service.php'); + + // Входные данные + $aData = array( + 'unit' => isset($_POST['unit']) ? sys::int($_POST['unit']) : 0, + 'tarif' => isset($_POST['tarif']) ? sys::int($_POST['tarif']) : 0, + 'pack' => isset($_POST['pack']) ? $_POST['pack'] : '', + 'slots' => isset($_POST['slots']) ? sys::int($_POST['slots']) : 0, + 'time' => isset($_POST['time']) ? sys::int($_POST['time']) : 30, + 'test' => (isset($_POST['time']) AND $_POST['time'] == 'test') ? true : false, + 'promo' => isset($_POST['promo']) ? $_POST['promo'] : false, + ); + + // Массвив данных + $aSDATA = service::buy($aData); + + // Процесс выдачи игрового сервера + $id = service::install($aSDATA); + + sys::outjs(array('s' => 'ok', 'id' => $id)); + } + + include(LIB.'games/services.php'); + + $check = false; + + // Проверка наличия доступной локации + $sql->query(services::unit($section)); + if($sql->num()) + { + // Выбранная локация + if(isset($url['get']) AND in_array($url['get'], array('tarifs', 'data'))) + $sql->query('SELECT `id`, `test` FROM `units` WHERE `id`="'.$id.'" LIMIT 1'); + + $select_unit = $sql->get(); + + // Генерация списка локаций + $units = services::units($section); + + // Генерация списка тарифов + $tarifs = services::tarifs($section, $select_unit['id']); + + if(isset($url['get']) AND in_array($url['get'], array('price', 'promo'))) + { + $aGet = array( + 'tarif' => sys::int($url['tarif']), + 'slots' => sys::int($url['slots']), + 'time' => sys::int($url['time']), + 'user' => $user['id'] + ); + + $sql->query('SELECT `price`, `discount` FROM `tarifs` WHERE `id`="'.$aGet['tarif'].'" LIMIT 1'); + $tarif = $sql->get(); + + // Выхлоп цены за выбранные параметры + if($url['get'] == 'price') + { + // Если выбран тестовый период + if($url['time'] == 'test') + sys::outjs(array('sum' => 0)); + + sys::outjs(array( + 'sum' => games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + )); + } + + // Выхлоп цены с учетом промо-кода + if($url['get'] == 'promo') + games::define_promo( + $url['cod'], + $aGet, + $tarif['discount'], + games::define_sum($tarif['discount'], $tarif['price'], $aGet['slots'], $aGet['time']) + ); + } + + // Генерация сборок/слот/периодов + if(isset($url['get']) AND $url['get'] == 'data') + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `id`="'.sys::int($url['tarif']).'" LIMIT 1'); + else + $sql->query('SELECT `id`, `name`, `price`, `slots_min`, `slots_max`, `packs`, `time`, `test`, `discount` FROM `tarifs` WHERE `game`="'.$section.'" AND `unit`="'.$select_unit['id'].'" AND `show`="1" ORDER BY `sort` ASC LIMIT 1'); + + if($sql->num()) + { + $select_tarif = $sql->get(); + + $aTarif = games::parse_tarif($select_tarif, $select_unit); + + if(isset($url['get'])) + { + // Выхлоп при выборе локации + if($url['get'] == 'tarifs') + sys::outjs(array_merge(array('tarifs' => $tarifs), $aTarif)); + + // Выхлоп при выборе тарифа + if($url['get'] == 'data') + sys::outjs($aTarif); + } + + $html->get($section, 'sections/services/games'); + $html->set('units', $units); + $html->set('tarifs', $tarifs); + $html->set('packs', $aTarif['packs']); + $html->set('slots', $aTarif['slots']); + $html->set('time', $aTarif['time']); + $html->set('cur', $cfg['currency']); + $html->set('date', date('d.m.Y', $start_point)); + + if($cfg['settlement_period']) + $html->unit('settlement_period', true, true); + else + $html->unit('settlement_period', false, true); + + $html->unit('informer', false, true); + $html->pack('main'); + + $check = true; + } + } + + if(!$check) + { + $html->get($section, 'sections/services/games'); + $html->unit('informer', true, true); + $html->pack('main'); + } +?> \ No newline at end of file diff --git a/system/sections/user/auth.php b/system/sections/user/auth.php new file mode 100644 index 0000000..cb486a5 --- /dev/null +++ b/system/sections/user/auth.php @@ -0,0 +1,129 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + $mcache->set($nmch, 1, false, 15); + + // Проверка капчи + if(!isset($_POST['captcha']) || sys::captcha_check('auth', $uip, $_POST['captcha'])) + sys::outjs(array('e' => sys::text('other', 'captcha')), $nmch); + + $aData = array(); + + $aData['login'] = isset($_POST['login']) ? $_POST['login'] : ''; + $aData['passwd'] = isset($_POST['passwd']) ? sys::passwdkey($_POST['passwd']) : ''; + + // Проверка входных данных + foreach($aData as $val) + if($val == '') + sys::outjs(array('e' => sys::text('input', 'all')), $nmch); + + // Проверка логина/почты на валидность + if(sys::valid($aData['login'], 'other', $aValid['mail']) AND sys::valid($aData['login'], 'other', $aValid['login'])) + { + $out = 'login'; + + // Если в логине указана почта + if(sys::ismail($aData['login'])) + $out = 'mail'; + + sys::outjs(array('e' => sys::text('input', $out.'_valid')), $nmch); + } + + $sql_q = '`login`'; + + // Если в логине указана почта + if(sys::ismail($aData['login'])) + $sql_q = '`mail`'; + + // Проверка существования пользователя + $sql->query('SELECT `id`, `login`, `mail`, `security_ip`, `security_code` FROM `users` WHERE '.$sql_q.'="'.$aData['login'].'" AND `passwd`="'.$aData['passwd'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => sys::text('input', 'auth')), $nmch); + + $user = $sql->get(); + + $subnetwork = sys::whois($uip); + + // Если включена защита по ip + if($user['security_ip']) + { + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `address`="'.$uip.'" LIMIT 1'); + + if(!$sql->num()) + { + if($subnetwork != 'не определена') + { + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `address`="'.$subnetwork.'" LIMIT 1'); + + if(!$sql->num()) + sys::outjs(array('e' => 'Ваш ip адрес не найден в числе указаных адресов для авторизации.'), $nmch); + }else + sys::outjs(array('e' => 'Ваш ip адрес не найден в числе указаных адресов для авторизации.'), $nmch); + } + } + + // Если включена защита по коду + if($user['security_code']) + { + $code = isset($_POST['code']) ? $_POST['code'] : ''; + + if($code == '' || $code != $mcache->get('auth_code_security_'.$user['id'])) + { + $ncod = sys::code(); + + // Отправка сообщения на почту + if(sys::mail('Авторизация', sys::updtext(sys::text('mail', 'security_code'), array('site' => $cfg['name'], 'code' => $ncod)), $user['mail'])) + { + $mcache->set('auth_code_security_'.$user['id'], $ncod, false, 180); + + if($code == '') + sys::outjs(array('i' => 'На вашу почту отправлено письмо с кодом подтверждения.', 'mail' => sys::mail_domain($user['mail'])), $nmch); + + sys::outjs(array('i' => 'На вашу почту отправлено письмо с кодом подтверждения снова.', 'mail' => sys::mail_domain($user['mail'])), $nmch); + } + + // Выхлоп: не удалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $nmch); + } + } + + $_SERVER['HTTP_USER_AGENT'] = mb_substr($_SERVER['HTTP_USER_AGENT'], 0, 200); + + // Обновление информации о пользователе + $sql->query('UPDATE `users` set `ip`="'.$uip.'", `browser`="'.sys::browser($_SERVER['HTTP_USER_AGENT']).'", `time`="'.$start_point.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Логирование ip + $sql->query('INSERT INTO `auth` set `user`="'.$user['id'].'", `ip`="'.$uip.'", `date`="'.$start_point.'", `browser`="'.sys::hb64($_SERVER['HTTP_USER_AGENT']).'"'); + + // Запись cookie пользователю + sys::cookie('egp_login', $user['login'], 14); + sys::cookie('egp_passwd', $aData['passwd'], 14); + sys::cookie('egp_authkeycheck', md5($user['login'].$uip.$aData['passwd']), 14); + + // Выхлоп удачной авторизации + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->get('auth', 'sections/user'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/lk.php b/system/sections/user/lk.php new file mode 100644 index 0000000..7d37e69 --- /dev/null +++ b/system/sections/user/lk.php @@ -0,0 +1,35 @@ + 'Профиль', + 'settings' => 'Настройки', + 'auth' => 'Логи авторизаций', + 'logs' => 'История операций', + 'security' => 'Безопасность' + ); + + $url['subsection'] = isset($url['subsection']) ? $url['subsection'] : 'index'; + + // Подключение раздела + if(in_array($url['subsection'], array('index', 'settings', 'auth', 'logs', 'security', 'action', 'cashback'))) + { + $title = isset($aTitle[$url['subsection']]) ? $aTitle[$url['subsection']] : ''; + $html->nav($title); + + include(LIB.'users.php'); + + users::nav($url['subsection']); + + include(SEC.'user/lk/'.$url['subsection'].'.php'); + }else + include(ENG.'404.php'); +?> \ No newline at end of file diff --git a/system/sections/user/lk/action.php b/system/sections/user/lk/action.php new file mode 100644 index 0000000..217cdbc --- /dev/null +++ b/system/sections/user/lk/action.php @@ -0,0 +1,189 @@ +query('SELECT `mail`, `new_mail`, `confirm_mail`, `wmr`, `phone`, `confirm_phone`, `contacts` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + if($go) + { + $name_mcache = 'lk_'.$user['id']; + + // Проверка сессии + if($mcache->get($name_mcache)) + sys::outjs(array('e' => $text['mcache']), $name_mcache); + + // Создание сессии + $mcache->set($name_mcache, 1, false, 10); + + if(!isset($url['type'])) + exit; + + switch($url['type']) + { + case 'contacts': + $contacts = isset($_POST['contacts']) ? $_POST['contacts'] : ''; + + if($contacts != '') + { + if(sys::valid($contacts, 'other', $aValid['contacts'])) + sys::outjs(array('e' => sys::text('input', 'contacts_valid')), $name_mcache); + } + + // Запись контактов в базу, если не совпадает с текущими данными + if($contacts != $user['contacts']) + $sql->query('UPDATE `users` set `contacts`="'.$contacts.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Выхлоп удачного выполнения операции + sys::outjs(array('s' => 'ok'), $name_mcache); + + case 'passwd': + $passwd = isset($_POST['passwd']) ? $_POST['passwd'] : ''; + + if(sys::valid($passwd, 'other', $aValid['passwd'])) + sys::outjs(array('e' => sys::text('input', 'passwd_valid')), $name_mcache); + + $passwd = sys::passwdkey($passwd); + + // Обновление пароля в базе, если он не совпадает с текущим + if($auth_data['passwd'] != $passwd) + { + $sql->query('UPDATE `users` set `passwd`="'.$passwd.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Обновление cookie + sys::cookie('login', $user['login'], 14); + sys::cookie('passwd', $passwd, 14); + sys::cookie('authkeycheck', md5($user['login'].$_SERVER['REMOTE_ADDR'].$passwd), 14); + } + + // Выхлоп удачного выполнения операции + sys::outjs(array('s' => 'ok'), $name_mcache); + + case 'mail': + $mail = isset($_POST['mail']) ? $_POST['mail'] : ''; + + // Проверка введенной почты + if(sys::valid($mail, 'other', $aValid['mail'])) + sys::outjs(array('e' => sys::text('input', 'mail_valid')), $name_mcache); + + if($mail == $user['mail']) + sys::outjs(array('e' => sys::text('input', 'similar')), $name_mcache); + + // Проверка почты на занятость + $sql->query('SELECT `id` FROM `users` WHERE `mail`="'.$mail.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => sys::text('input', 'mail_use')), $name_mcache); + + // Генерация кода + $key = sys::key('mail_change'.$user['id']); + + // Отправка письма на старую почту + if(sys::mail('Смена почты', sys::updtext(sys::text('mail', 'change'), array('site' => $cfg['name'], 'url' => $cfg['http'].'user/section/lk/subsection/action/type/confirm_mail/confirm/'.$key.'/go/1')), $user['mail'])) + { + $sql->query('UPDATE `users` set `new_mail`="'.$mail.'", `confirm_mail`="'.$key.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => sys::text('output', 'oldmail'), 'mail' => sys::mail_domain($user['mail'])), $name_mcache); + } + + // Выхлоп: неудалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $name_mcache); + + case 'confirm_mail': + $key = isset($url['confirm']) ? $url['confirm'] : ''; + + if($key != $user['confirm_mail']) + sys::outhtml(sys::text('output', 'confirm_key_error'), 4, $cfg['http'].'user/section/lk', $name_mcache); + + // Проверка почты на занятость + $sql->query('SELECT `id` FROM `users` WHERE `mail`="'.$user['confirm_mail'].'" LIMIT 1'); + if($sql->num()) + sys::outhtml(sys::text('input', 'mail_use'), 4, $cfg['http'].'user/section/lk', $name_mcache); + + $sql->query('UPDATE `users` set `mail`="'.$user['new_mail'].'", `new_mail`="", `confirm_mail`="" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Выхлоп удачного выполнения операции + sys::outhtml(sys::text('output', 'confirm_mail_done'), 4, $cfg['http'].'user/section/lk', $name_mcache); + + case 'phone': + // Проверка, подтвержден ли номер + if($user['confirm_phone'] == '1') + sys::outjs(array('e' => sys::text('output', 'confirm_phone')), $name_mcache); + + $phone = isset($_POST['phone']) ? str_replace('+', '', trim($_POST['phone'])) : ''; + + // Проверка введенного номера + if($phone != '') + { + if(sys::valid($phone, 'other', $aValid['phone'])) + sys::outjs(array('e' => sys::text('input', 'phone_valid')), $name_mcache); + } + + // Запись номера, если не совпадает с текущим + if($phone != $user['phone']) + $sql->query('UPDATE `users` set `phone`="'.$phone.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Выхлоп удачного выполнения операции + sys::outjs(array('s' => 'ok'), $name_mcache); + + case 'confirm_phone': + // Проверка, подтвержден ли номер + if($user['confirm_phone'] == '1') + sys::outjs(array('e' => sys::text('output', 'confirm_phone_done')), $name_mcache); + + if($user['phone'] == '') + sys::outjs(array('e' => sys::text('input', 'phone')), $name_mcache); + + // Проверка, отправлялось ли сообщение + if(strlen($user['confirm_phone']) == 6) + sys::outjs(array('s' => 'ok'), $name_mcache); + + // Генерация кода подтверждения + $code = sys::smscode(); + + // Отправка кода подтверждения на номер + if(sys::sms('code: '.$code, $user['phone'])) + { + $sql->query('UPDATE `users` set `confirm_phone`="'.$code.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + // Выхлоп: неудалось отправить сообщение + sys::outjs(array('e' => sys::text('output', 'confirm_phone_error')), $name_mcache); + + case 'confirm_phone_end': + // Проверка, подтвержден ли номер + if($user['confirm_phone'] == '1') + sys::outjs(array('e' => sys::text('output', 'confirm_phone_done')), $name_mcache); + + if($user['phone'] == '') + sys::outjs(array('e' => sys::text('input', 'phone')), $name_mcache); + + $code = isset($_POST['smscode']) ? sys::int($_POST['smscode']) : ''; + + if($code != $user['confirm_phone']) + sys::outjs(array('e' => sys::text('output', 'confirm_key_error')), $name_mcache); + + $sql->query('UPDATE `users` set `confirm_phone`="1" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Выхлоп удачного выполнения операции + sys::outjs(array('s' => 'ok'), $name_mcache); + + case 'wmr': + $wmr = isset($_POST['wmr']) ? $_POST['wmr'] : ''; + + // Проверка наличия указанного кошелька + if(isset($user['wmr']{0}) AND in_array($user['wmr']{0}, array('R', 'Z', 'U'))) + sys::outjs(array('e' => sys::text('input', 'wmr_confirm')), $name_mcache); + + if(sys::valid($wmr, 'wm')) + sys::outjs(array('e' => sys::text('input', 'wmr_valid')), $name_mcache); + + // Обновление кошелька в базе + $sql->query('UPDATE `users` set `wmr`="'.$wmr.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + // Выхлоп удачного выполнения операции + sys::outjs(array('s' => 'ok'), $name_mcache); + } + } +?> \ No newline at end of file diff --git a/system/sections/user/lk/auth.php b/system/sections/user/lk/auth.php new file mode 100644 index 0000000..fde5edb --- /dev/null +++ b/system/sections/user/lk/auth.php @@ -0,0 +1,34 @@ +query('SELECT `ip`, `date`, `browser` FROM `auth` WHERE `user`="'.$user['id'].'" ORDER BY `id` DESC LIMIT 20'); + while($aBro = $sql->get($qBro)) + { + $browser = base64_decode($aBro['browser']); + + $cData = $SxGeo->getCityFull($aBro['ip']); + $ico = sys::country($cData['country']['iso']); + + $html->get('list', 'sections/user/lk/auth'); + + $html->set('ip', $aBro['ip']); + $html->set('date', sys::today($aBro['date'], true)); + $html->set('browser', sys::browser($browser)); + $html->set('more', $browser); + $html->set('flag', $ico); + $html->set('country', empty($cData['country']['name_ru']) ? 'Не определена' : $cData['country']['name_ru']); + + $html->pack('auth'); + } + + $html->get('auth', 'sections/user/lk'); + + $html->set('auth', isset($html->arr['auth']) ? $html->arr['auth'] : '', true); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/lk/cashback.php b/system/sections/user/lk/cashback.php new file mode 100644 index 0000000..16ceed7 --- /dev/null +++ b/system/sections/user/lk/cashback.php @@ -0,0 +1,125 @@ +get($name_mcache)) + sys::outjs(array('e' => $text['mcache']), $name_mcache); + + // Создание сессии + $mcache->set($name_mcache, 1, false, 10); + + if(!$cfg['part_money']) + sys::outjs(array('e' => 'Вывод средств невозможен'), $name_mcache); + + $aData = array(); + + $aData['purse'] = isset($url['purse']) ? strtolower(trim($url['purse'])) : sys::outjs(array('e' => 'Необходимо указать кошелек'), $name_mcache); + $aData['sum'] = isset($url['sum']) ? round(floatval($url['sum']), 2) : sys::outjs(array('e' => 'Необходимо указать сумму'), $name_mcache); + + $sql->query('SELECT `part_money` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + // Проверка доступной суммы + if($aData['sum'] > $user['part_money']) + sys::outjs(array('e' => 'У вас нет указанной суммы'), $name_mcache); + + if(!in_array($aData['purse'], array('phone', 'wmr', 'lk'))) + sys::outjs(array('e' => 'Неверно указан кошелек'), $name_mcache); + + // Вывод на баланс сайта + if($aData['purse'] == 'lk') + { + if($aData['sum'] < 1) + sys::outjs(array('e' => 'Сумма не должна быть меньше 1 '.$cfg['currency']), $name_mcache); + + $sql->query('UPDATE `users` set `balance`="'.($user['balance']+$aData['sum']).'", `part_money`="'.($user['part_money']-$aData['sum']).'" WHERE `id`="'.$user['id'].'"'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'cashback'), + array('purse' => $cfg['part_log'], 'money' => $aData['sum'])).'", `date`="'.$start_point.'", `type`="cashback", `money`="'.$aData['sum'].'"'); + + sys::outjs(array('s' => 'Перевод средств был успешно произведен'), $name_mcache); + } + + // Проверка лимита на мин. сумму за перевод + if($aData['sum'] < $cfg['part_limit_min']) + sys::outjs(array('e' => 'Миниммальная сумма вывода '.$cfg['part_limit_min'].' '.$cfg['currency']), $name_mcache); + + // Проверка кошелька + if($aData['purse'] == 'wmr') + { + $sql->query('SELECT `wmr` FROM `users` WHERE `id`="'.$user['id'].'" AND `wmr`!="" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Чтобы вывести деньги на WMR-кошелек, необходимо его указать в профиле'), $name_mcache); + }else{ + $sql->query('SELECT `phone` FROM `users` WHERE `id`="'.$user['id'].'" AND `confirm_phone`="1" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Чтобы вывести деньги на QIWI, необходим подтвержденный номер в профиле'), $name_mcache); + } + + $purse = $sql->get(); + + // Вывод без одобрения + if($cfg['part_output']) + { + // Проверка лимита на макс. сумму за 24 часа + $sql->query('SELECT SUM(`money`) FROM `cashback` WHERE `user`="'.$user['id'].'" AND `time`<"'.($start_point-86400).'" AND `status`="0"'); + $sum = $sql->get(); + + if(($aData['sum']+$sum['SUM(`money`)']) > $cfg['part_limit_max']) + sys::outjs(array('e' => 'Максимальная сумма вывода за 24 часа '.$cfg['part_limit_max'].' '.$cfg['currency']), $name_mcache); + + // Проверка общего лимита за 24 часа + $sql->query('SELECT SUM(`money`) FROM `cashback` WHERE `time`<"'.($start_point-86400).'" AND `status`="0"'); + $sum = $sql->get(); + + if(($aData['sum']+$sum['SUM(`money`)']) > $cfg['part_limit_day']) + sys::outjs(array('e' => 'Общий лимит на вывод за 24 часа достигнут, попробуйте вывести завтра'), $name_mcache); + + // Запрос на шлюз + if($cfg['part_gateway'] == 'unitpay') + { + $aType = array('phone' => 'qiwi', 'wmr' => 'webmoney'); + + $sql->query('INSERT INTO `cashback` set `user`="'.$user['id'].'", `purse`="'.$purse[$aData['purse']].'", `money`="'.$aData['sum'].'", `date`="'.$start_point.'", `status`="0"'); + $id = $sql->id(); + + $sum = $aData['sum']-($aData['sum']/100*$cfg['part_output_proc']); + + $json = file_get_contents('https://unitpay.ru/api?method=massPayment¶ms[sum]='.$sum.'¶ms[purse]='.$purse[$aData['purse']].'¶ms[login]='.$cfg['unitpay_mail'].'¶ms[transactionId]='.$id.' ¶ms[secretKey]='.$cfg['unitpay_api'].'¶ms[paymentType]='.$aType[$aData['purse']]); + + $array = json_decode($json, true); + + // Упешный вывод средств + if(is_array($array) AND isset($array['result']) AND in_array($array['result']['status'], array('success', 'not_completed '))) + { + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']-$aData['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + $sql->query('INSERT INTO `logs` set `user`="'.$user['id'].'", `text`="'.sys::updtext(sys::text('logs', 'cashback'), + array('purse' => $aType[$aData['purse']], 'money' => $aData['sum'])).'", `date`="'.$start_point.'", `type`="cashback", `money`="'.$aData['sum'].'"'); + + sys::outjs(array('s' => 'Запрос на вывод средств был успешно выполнен'), $name_mcache); + } + + if(!is_array($array)) + sys::outjs(array('e' => 'Неудалось выполнить запрос'), $name_mcache); + + switch($array['error']['code']) + { + case '103': + sys::outjs(array('e' => 'На данный момент вы не можете вывести средства, обратитесь к администратору'), $name_mcache); + case '104': + sys::outjs(array('e' => 'Номер телефона не входит в список доступных для выплат стран'), $name_mcache); + case '1053': + sys::outjs(array('e' => 'Платежная система не смогла получить информацию о номере телефона'), $name_mcache); + } + } + + sys::outjs(array('e' => 'Технические проблемы, обратитесь в службу поддержки'.$array['error']['code']), $name_mcache); + } + + $sql->query('UPDATE `users` set `part_money`="'.($user['part_money']-$aData['sum']).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + $sql->query('INSERT INTO `cashback` set `user`="'.$user['id'].'", `purse`="'.$purse[$aData['purse']].'", `money`="'.$aData['sum'].'", `date`="'.$start_point.'", `status`="1"'); + + sys::outjs(array('s' => 'Заявка на вывод средств была успешно создана'), $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/user/lk/index.php b/system/sections/user/lk/index.php new file mode 100644 index 0000000..91ca6aa --- /dev/null +++ b/system/sections/user/lk/index.php @@ -0,0 +1,81 @@ +query('SELECT `name`, `lastname`, `patronymic`, `mail`, `wmr`, `phone`, `contacts`, `date`, `part_money`, `rental`, `extend` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + // Подсчет рефералов + $nmch = 'part_'.$user['id']; + + if($mcache->get($nmch) != '') + $part_users = $mcache->get($nmch); + else{ + $sql->query('SELECT `id` FROM `users` WHERE `part`="'.$user['id'].'"'); + $part_users = $sql->num(); + + $mcache->set($nmch, $part_users, false, 300); + } + + if($user['rental']) + $rental = strpos($user['rental'], '%') ? $user['rental'] : $user['rental'].' '.$cfg['currency']; + else + $rental = 'отсутствует'; + + if($user['extend']) + $extend = strpos($user['extend'], '%') ? $user['extend'] : $user['extend'].' '.$cfg['currency']; + else + $extend = 'отсутствует'; + + $i = 1; + + $part_user = ''; + + $part_inf =$sql->query('SELECT `id`, `login`, `date` FROM `users` WHERE `part`="'.$user['id'].'" ORDER BY `date` ASC'); + while($part_info = $sql->get($part_inf)) + { + $sql->query('SELECT `id` FROM `servers` WHERE `user`="'.$part_info['id'].'" LIMIT 10'); + $servers = $sql->num(); + + $part_user .= ''; + $part_user .= ''.$i++.''; + $part_user .= ''.$part_info['login'].''; + $part_user .= ''.sys::today($part_info['date'], true).''; + $part_user .= ''.$servers.''; + $part_user .= ''; + } + + $html->get('index', 'sections/user/lk'); + + $html->set('id', $user['id']); + $html->set('name', $user['name']); + $html->set('lastname', $user['lastname']); + $html->set('patronymic', $user['patronymic']); + $html->set('login', $user['login']); + $html->set('mail', $user['mail']); + $html->set('phone', $user['phone']); + $html->set('contacts', $user['contacts']); + $html->set('cur', $cfg['currency']); + $html->set('wmr', $user['wmr']); + $html->set('rental', $rental); + $html->set('extend', $extend); + $html->set('date', sys::today($user['date'], true)); + $html->set('balance', round($user['balance'], 2)); + + $html->set('part_users', $part_users); + $html->set('part_money', $user['part_money']); + $html->set('part_user', $part_user); + + if($user['name']) $html->unit('name', true); else $html->unit('name'); + if($user['lastname']) $html->unit('lastname', true); else $html->unit('lastname'); + if($user['patronymic']) $html->unit('patronymic', true); else $html->unit('patronymic'); + + if($user['name'] || $user['lastname'] || $user['patronymic']) $html->unit('nlp', true); else $html->unit('nlp'); + + if(isset($user['wmr']{0}) AND in_array($user['wmr']{0}, array('R', 'Z', 'U'))) + $html->unit('wmr', true, true); + else + $html->unit('wmr', false, true); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/lk/logs.php b/system/sections/user/lk/logs.php new file mode 100644 index 0000000..d2f3818 --- /dev/null +++ b/system/sections/user/lk/logs.php @@ -0,0 +1,20 @@ +query('SELECT `text`, `date` FROM `logs` WHERE `user`="'.$user['id'].'" ORDER BY `id` DESC LIMIT 40'); + while($aLog = $sql->get($qLog)) + { + $html->get('list', 'sections/user/lk/logs'); + $html->set('text', $aLog['text']); + $html->set('date', sys::today($aLog['date'], true)); + $html->pack('logs'); + } + + $html->get('logs', 'sections/user/lk'); + + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : 'Нет логов операций', true); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/lk/security.php b/system/sections/user/lk/security.php new file mode 100644 index 0000000..24ed831 --- /dev/null +++ b/system/sections/user/lk/security.php @@ -0,0 +1,160 @@ +query('SELECT `security_ip`, `security_code` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + // Выполнений действий + if(isset($url['action']) AND in_array($url['action'], array('on', 'off', 'on_code', 'off_code', 'add', 'del', 'info'))) + { + $snw = isset($_POST['subnetwork']) ? true : false; + + switch($url['action']) + { + case 'on': + $sql->query('UPDATE `users` set `security_ip`="1" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'off': + $sql->query('UPDATE `users` set `security_ip`="0" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'on_code': + $sql->query('UPDATE `users` set `security_code`="1" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'off_code': + $sql->query('UPDATE `users` set `security_code`="0" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'add': + $address = isset($_POST['address']) ? trim($_POST['address']) : exit(); + + if(sys::valid($address, 'ip')) + sys::outjs(array('e' => 'Указанный адрес имеет неверный формат.')); + + // Если подсеть + if($snw) + { + $address = sys::whois($address); + + if($address == 'не определена') + sys::outjs(array('e' => 'Не удалось определить подсеть для указанного адреса.')); + } + + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `address`="'.$address.'" LIMIT 1'); + + // Если такой адрес уже добавлен + if($sql->num()) + sys::outjs(array('s' => 'ok')); + + $sql->query('INSERT INTO `security` set `user`="'.$user['id'].'", `address`="'.$address.'", `time`="'.$start_point.'"'); + + sys::outjs(array('s' => 'ok')); + + case 'del': + $address = isset($_POST['address']) ? trim($_POST['address']) : exit(); + + if(!is_numeric($address) AND sys::valid($address, 'ip')) + sys::outjs(array('e' => sys::outjs(array('e' => 'Указанный адрес имеет неверный формат.')))); + + if(is_numeric($address)) + { + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `id`="'.$address.'" LIMIT 1'); + + // Если такое правило отсутствует + if(!$sql->num()) + sys::outjs(array('s' => 'ok')); + }else{ + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `address`="'.$address.'" LIMIT 1'); + + // Если одиночный адрес не найден, проверить на разрешенную подсеть + if(!$sql->num()) + { + $address = sys::whois($address); + + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$user['id'].'" AND `address`="'.$address.'" LIMIT 1'); + + if($sql->num()) + { + $security = $sql->get(); + + sys::outjs(array('i' => 'Указанный адрес входит в разрешенную подсеть, удалить подсеть?', 'id' => $security['id'])); + } + + sys::outjs(array('s' => 'ok')); + } + } + + $security = $sql->get(); + + $sql->query('DELETE FROM `security` WHERE `id`="'.$security['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'info': + $address = isset($_POST['address']) ? trim($_POST['address']) : sys::outjs(array('info' => 'Не удалось получить информацию.')); + + if(sys::valid($address, 'ip')) + sys::outjs(array('e' => 'Указанный адрес имеет неверный формат.')); + + include(LIB.'geo.php'); + + $SxGeo = new SxGeo(DATA.'SxGeoCity.dat'); + + $data = $SxGeo->getCityFull($address); + + $info = 'Информация об IP адресе:'; + + if($data['country']['name_ru'] != '') + { + $info .= '

    Страна: '.$data['country']['name_ru']; + + if($data['city']['name_ru'] != '') + $info .= '

    Город: '.$data['city']['name_ru']; + + $info .= '

    Подсеть: '.sys::whois($address); + + }else + $info = 'Не удалось получить информацию.'; + + sys::outjs(array('info' => $info)); + } + } + + // Построение списка добавленных адресов + $sql->query('SELECT `id`, `address` FROM `security` WHERE `user`="'.$user['id'].'" ORDER BY `id` ASC'); + while($security = $sql->get()) + { + $html->get('list', 'sections/user/lk/security'); + + $html->set('id', $security['id']); + $html->set('address', $security['address']); + + $html->pack('security'); + } + + $html->get('security', 'sections/user/lk'); + + $html->set('ip', $uip); + $html->set('subnetwork', sys::whois($uip)); + + $html->set('security', isset($html->arr['security']) ? $html->arr['security'] : '', true); + + if($user['security_ip']) + $html->unit('security_ip', true, true); + else + $html->unit('security_ip', false, true); + + if($user['security_code']) + $html->unit('security_code', true, true); + else + $html->unit('security_code', false, true); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/lk/settings.php b/system/sections/user/lk/settings.php new file mode 100644 index 0000000..27c2e97 --- /dev/null +++ b/system/sections/user/lk/settings.php @@ -0,0 +1,61 @@ +query('SELECT `notice_news`, `notice_help` FROM `users` WHERE `id`="'.$user['id'].'" LIMIT 1'); + $user = array_merge($user, $sql->get()); + + if(isset($url['action']) AND in_array($url['action'], array('upload', 'news', 'help', 'important'))) + { + switch($url['action']) + { + case 'upload': + $file = isset($_POST['value']) ? $_POST['value'] : exit; + $name = isset($_POST['name']) ? $_POST['name'] : exit; + + $pname = explode('.', $name); + $type = strtolower(end($pname)); + + if(!in_array($type, array('png', 'gif', 'jpg', 'bmp'))) + exit('Допустимый формат изображений: png, gif, jpg, bmp.'); + + $aData = explode(',', $file); + + if(file_put_contents(ROOT.'upload/avatars/'.$user['id'].'.'.$type, base64_decode(str_replace(' ','+', $aData[1])))) + exit($user['id'].':ok'); + + exit('Ошибка загрузки: убедитесь, что изображение не повреждено и имеет правильный формат.'); + + case 'news': + $notice = $user['notice_news'] ? 0 : 1; + + $sql->query('UPDATE `users` set `notice_news`="'.$notice.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + + case 'help': + $notice = $user['notice_help'] ? 0 : 1; + + $sql->query('UPDATE `users` set `notice_help`="'.$notice.'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok')); + } + } + + $html->get('settings', 'sections/user/lk'); + + $html->set('id', $user['id']); + $html->set('ava', users::ava($user['id'])); + + if($user['notice_news']) + $html->unit('notice_news', true); + else + $html->unit('notice_news'); + + if($user['notice_help']) + $html->unit('notice_help', true); + else + $html->unit('notice_help'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/quit.php b/system/sections/user/quit.php new file mode 100644 index 0000000..ea3e4aa --- /dev/null +++ b/system/sections/user/quit.php @@ -0,0 +1,17 @@ +query('UPDATE `users` set `time`="'.($start_point-10).'" WHERE `id`="'.$user['id'].'" LIMIT 1'); + + sys::users($users, $user, $authkey, true); + sys::back($cfg['http']); +?> \ No newline at end of file diff --git a/system/sections/user/recovery.php b/system/sections/user/recovery.php new file mode 100644 index 0000000..52a0924 --- /dev/null +++ b/system/sections/user/recovery.php @@ -0,0 +1,121 @@ +get($nmch)) + sys::outjs(array('e' => sys::text('all', 'mcache')), $nmch); + + $mcache->set($nmch, 1, false, 15); + + // Проверка капчи + if(!isset($_POST['captcha']) || sys::captcha_check('recovery', $uip, $_POST['captcha'])) + sys::outjs(array('e' => sys::text('other', 'captcha')), $nmch); + + $aData = array(); + + $aData['login'] = isset($_POST['login']) ? $_POST['login'] : ''; + + // Проверка логина/почты на валидность + if(sys::valid($aData['login'], 'other', $aValid['mail']) && sys::valid($aData['login'], 'other', $aValid['login'])) + { + $out = 'login'; + + // Если в логине указана почта + if(sys::ismail($aData['login'])) + $out = 'mail'; + + sys::outjs(array('e' => sys::text('input', $out.'_valid')), $nmch); + } + + $sql_q = '`login`'; + + // Если в логине указана почта + if(sys::ismail($aData['login'])) + $sql_q = '`mail`'; + + // Проверка существования пользователя + $sql->query('SELECT `id`, `mail` FROM `users` WHERE '.$sql_q.'="'.$aData['login'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => sys::text('input', 'recovery')), $nmch); + + $user = $sql->get(); + + $link = $device == '!mobile' ? 'user/section/recovery/confirm/' : 'recovery/confirm/'; + + // Проверка подачи запроса на восстановление + $sql->query('SELECT `id`, `key` FROM `recovery` WHERE `user`="'.$user['id'].'" LIMIT 1'); + if($sql->num()) + { + $recovery = $sql->get(); + $sql->query('UPDATE `recovery` set `date`="'.$start_point.'" WHERE `id`="'.$recovery['id'].'" LIMIT 1'); + + // Повторная отправка письма на почту + if(sys::mail('Восстановление доступа', sys::updtext(sys::text('mail', 'recovery'), array('site' => $cfg['name'], 'url' => $cfg['http'].$link.$recovery['key'])), $user['mail'])) + sys::outjs(array('s' => sys::text('output', 'remail'), 'mail' => sys::mail_domain($user['mail'])), $nmch); + + // Выхлоп: не удалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $nmch); + } + + // Генерация ключа + $key = sys::key('recovery_'.$uip); + + // Запись данных в базу + $sql->query('INSERT INTO `recovery` set `user`="'.$user['id'].'", `mail`="'.$user['mail'].'", `key`="'.$key.'", `date`="'.$start_point.'"'); + + // Отправка письма на почту + if(sys::mail('Восстановление доступа', sys::updtext(sys::text('mail', 'recovery'), array('site' => $cfg['name'], 'url' => $cfg['http'].$link.$key)), $user['mail'])) + sys::outjs(array('s' => sys::text('output', 'mail'), 'mail' => sys::mail_domain($user['mail'])), $nmch); + + // Выхлоп: не удалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $nmch); + } + + // Завершение восстановления + if(isset($url['confirm']) && !sys::valid($url['confirm'], 'md5')) + { + $sql->query('SELECT `id`, `user`, `mail` FROM `recovery` WHERE `key`="'.$url['confirm'].'" LIMIT 1'); + if($sql->num()) + { + $data = $sql->get(); + $passwd = sys::passwd(10); + + $sql->query('SELECT `security_ip` FROM `users` WHERE `id`="'.$data['user'].'" LIMIT 1'); + $user = $sql->get(); + + // Если включена защита по ip + if($user['security_ip']) + { + $sql->query('SELECT `id` FROM `security` WHERE `user`="'.$data['user'].'" AND `address`="'.$uip.'" LIMIT 1'); + + if(!$sql->num()) + $sql->query('INSERT INTO `security` set `user`="'.$data['user'].'", `address`="'.$uip.'", `time`="'.$start_point.'"'); + } + + $sql->query('UPDATE `users` set `passwd`="'.sys::passwdkey($passwd).'" WHERE `id`="'.$data['user'].'" LIMIT 1'); + $sql->query('DELETE FROM `recovery` WHERE `id`="'.$data['id'].'" LIMIT 1'); + + if(sys::mail('Восстановление доступа', sys::updtext(sys::text('mail', 'recovery_end'), array('site' => $cfg['name'], 'passwd' => $passwd)), $data['mail'])) + sys::outhtml('Операция по восстановлению успешно выполнена, на вашу почту отправлен новый пароль.', 5, 'http://'.sys::mail_domain($data['mail'])); + + sys::outhtml(sys::text('error', 'mail'), 5); + } + + sys::outhtml(sys::text('error', 'recovery'), 5); + } + + $html->get('recovery', 'sections/user'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/replenish.php b/system/sections/user/replenish.php new file mode 100644 index 0000000..fccbef5 --- /dev/null +++ b/system/sections/user/replenish.php @@ -0,0 +1,29 @@ +query('SELECT `text`, `date` FROM `logs` WHERE `user`="'.$user['id'].'" AND `type`="replenish" ORDER BY `id` DESC LIMIT 10'); + while($aLog = $sql->get($qLog)) + { + $html->get('replenish', 'sections/user/lk/logs'); + $html->set('text', $aLog['text']); + $html->set('date', sys::today($aLog['date'], true)); + $html->pack('logs'); + } + + $html->get('replenish', 'sections/user'); + $html->set('id', $user['id']); + $html->set('wmr', $cfg['webmoney_wmr']); + $html->set('freekassa', $cfg['freekassa_id']); + $html->set('balance', round($user['balance'], 2)); + $html->set('cur', $cfg['currency']); + $html->set('logs', isset($html->arr['logs']) ? $html->arr['logs'] : 'Нет логов операций', true); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/user/signup.php b/system/sections/user/signup.php new file mode 100644 index 0000000..ad6a4a4 --- /dev/null +++ b/system/sections/user/signup.php @@ -0,0 +1,217 @@ + $add) + { + if(!$add) + continue; + + $aData[$name] = isset($_POST[$name]) ? trim($_POST[$name]) : ''; + } + } + + // Регистрация + if($go) + { + $nmch = 'go_signup_'.$uip; + + if($mcache->get($nmch)) + sys::outjs(array('e' => sys::text('other', 'mcache')), $nmch); + + $mcache->set($nmch, 1, false, 15); + + // Проверка капчи + if(!isset($_POST['captcha']) || sys::captcha_check('signup', $uip, $_POST['captcha'])) + sys::outjs(array('e' => sys::text('other', 'captcha')), $nmch); + + // Проверка входных данных + foreach($aData as $input => $val) + { + // Если не заполнено поле + if($val == '') + sys::outjs(array('e' => sys::text('input', 'all')), $nmch); + + // Проверка данных на валидность + if(sys::valid($val, 'other', $aValid[$input])) + sys::outjs(array('e' => sys::text('input', $input.'_valid')), $nmch); + } + + // Проверка логина на занятость + if(isset($aData['login'])) + { + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aData['login'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => sys::text('input', 'login_use')), $nmch); + } + + if(!isset($aData['mail'])) + sys::outjs(array('e' => sys::text('input', 'mail_valid')), $nmch); + + // Проверка почты на занятость + $sql->query('SELECT `id` FROM `users` WHERE `mail`="'.$aData['mail'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => sys::text('input', 'mail_use')), $nmch); + + // Проверка телефона на занятость + if(isset($aData['phone'])) + { + $sql->query('SELECT `id` FROM `users` WHERE `phone`="'.$aData['phone'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => sys::text('input', 'phone_use')), $nmch); + } + + // Проверка контактов на занятость + if(isset($aData['contacts'])) + { + $sql->query('SELECT `id` FROM `users` WHERE `contacts`="'.$aData['contacts'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => sys::text('input', 'use_contacts')), $nmch); + } + + // Проверка почты на подачу регистрации + $sql->query('SELECT `id`, `key` FROM `signup` WHERE `mail`="'.$aData['mail'].'" LIMIT 1'); + if($sql->num()) + { + $signup = $sql->get(); + $sql->query('UPDATE `signup` set `date`="'.$start_point.'" WHERE `id`="'.$signup['id'].'" LIMIT 1'); + + // Повторная отправка письма на почту + sys::mail( + 'Регистрация', + sys::updtext( + sys::text('mail', 'signup'), + array( + 'site' => $cfg['name'], + 'url' => $cfg['http'].'user/section/signup/confirm/'.$signup['key'] + ) + ), + $aData['mail'] + ); + sys::outjs(array('s' => sys::text('output', 'remail'), 'mail' => sys::mail_domain($aData['mail'])), $nmch); + } + + // Генерация ключа + $key = sys::key('signup_'.$uip); + + $data = sys::b64js($aData); + + // Запись данных в базу + $sql->query('INSERT INTO `signup` set `mail`="'.$aData['mail'].'", `key`="'.$key.'", `data`="'.$data.'", `date`="'.$start_point.'"'); + + // Отправка сообщения на почту + if(sys::mail('Регистрация', sys::updtext(sys::text('mail', 'signup'), array('site' => $cfg['name'], 'url' => $cfg['http'].'user/section/signup/confirm/'.$key)), $aData['mail'])) + sys::outjs(array('s' => sys::text('output', 'mail'), 'mail' => sys::mail_domain($aData['mail'])), $nmch); + + // Выхлоп: не удалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $nmch); + } + + // Завершение регистрации + if(isset($url['confirm']) && !sys::valid($url['confirm'], 'md5')) + { + $sql->query('SELECT `id`, `data` FROM `signup` WHERE `key`="'.$url['confirm'].'" LIMIT 1'); + if($sql->num()) + { + $signup = $sql->get(); + + $aData = sys::b64djs($signup['data']); + + foreach($aSignup['input'] as $name => $add) + $aNData[$name] = isset($aData[$name]) ? $aData[$name] : ''; + + unset($aData); + + // Если регистрация без указания логина + if(empty($aNData['login'])) + { + $lchar = false; + + while(1) + { + $aNData['login'] = sys::login($aNData['mail'], $lchar); + + $sql->query('SELECT `id` FROM `users` WHERE `login`="'.$aNData['login'].'" LIMIT 1'); + if(!$sql->num()) + break; + + $lchar = true; + } + } + + // Если регистрация без указания пароля + if(empty($aNData['passwd'])) + $aNData['passwd'] = sys::passwd(10); + + // Реферал + if(isset($_COOKIE['part'])) + $part = ', `part`="'.sys::int($_COOKIE['part']).'"'; + + // Запись данных в базу + $sql->query('INSERT INTO `users` set ' + .'`login`="'.$aNData['login'].'",' + .'`passwd`="'.sys::passwdkey($aNData['passwd']).'",' + .'`mail`="'.$aNData['mail'].'",' + .'`name`="'.$aNData['name'].'",' + .'`lastname`="'.$aNData['lastname'].'",' + .'`patronymic`="'.$aNData['patronymic'].'",' + .'`phone`="'.$aNData['phone'].'",' + .'`contacts`="'.$aNData['contacts'].'",' + .'`balance`="0", `group`="user", `date`="'.$start_point.'"'.$part); + + $sql->query('DELETE FROM `signup` WHERE `id`="'.$signup['id'].'" LIMIT 1'); + + // Отправка сообщения на почту + if(sys::mail('Завершение регистрации', sys::updtext(sys::text('mail', 'signup_end'), array('site' => $cfg['name'], 'login' => $aNData['login'], 'passwd' => $aNData['passwd'])), $aNData['mail'])) + sys::outhtml(sys::text('output', 'signup'), 5, 'http://'.sys::mail_domain($aNData['mail'])); + + // Выхлоп: не удалось отправить письмо + sys::outjs(array('e' => sys::text('error', 'mail')), $nmch); + } + + sys::outhtml(sys::text('error', 'signup'), 5); + } + + // Генерация формы + foreach($aSignup['input'] as $name => $add) + { + if(!$add) + continue; + + $html->get('signup', 'sections/user/inputs'); + $html->set('name', $name); + $html->set('info', $aSignup['info'][$name]); + $html->set('type', $aSignup['type'][$name]); + $html->set('placeholder', $aSignup['placeholder'][$name]); + $html->pack('inputs'); + } + + $html->get('signup', 'sections/user'); + + $inputsjs = ''; + + foreach($aSignup['input'] as $name => $add) + { + if(!$add) + continue; + + $inputsjs .= '"'.$name.'",'; + } + + $html->set('inputs', $html->arr['inputs'], true); + $html->set('inputsjs', $inputsjs); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/aes/free/connect.php b/system/sections/web/aes/free/connect.php new file mode 100644 index 0000000..3f5090b --- /dev/null +++ b/system/sections/web/aes/free/connect.php @@ -0,0 +1,30 @@ + 'Длина ключа не должна превышать 32 символа.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array(); + + $aData['server'] = sys::int($url['server']); + $aData['type'] = $url['subsection']; + $aData['user'] = $server['user']; + $aData['file'] = 'cstrike/addons/amxmodx/configs/csstats_mysql.cfg'; + $aData['cfg'] = 'cstrike/server.cfg'; + + $aData['orcfg'] = array( + 'key' => $key + ); + + $aData['orsql'] = array(); + + web::connect($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/aes/free/delete.php b/system/sections/web/aes/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/aes/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/aes/free/install.php b/system/sections/web/aes/free/install.php new file mode 100644 index 0000000..c631da5 --- /dev/null +++ b/system/sections/web/aes/free/install.php @@ -0,0 +1,75 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = 'csstats_key "[key]"'.PHP_EOL + .'csstats_url "[domain]"'.PHP_EOL + .'csstats_sort "-2"'.PHP_EOL + .'csstats_double "0"'.PHP_EOL + .'csstats_host "[host]"'.PHP_EOL + .'csstats_user "[login]"'.PHP_EOL + .'csstats_pass "[passwd]"'.PHP_EOL + .'csstats_db "[login]"'.PHP_EOL + .'csstats_table_players "csstats_players"'.PHP_EOL + .'csstats_table_settings "csstats_settings"'.PHP_EOL + .'csstats_delete_time "15 120 2"'.PHP_EOL + .'csstats_insert_time "60 1"'.PHP_EOL + .'csstats_update_time "30 0"'.PHP_EOL + .'csstats_slow "0"'; + + $aData['config_php'] = ''; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/aes/free/manage.php b/system/sections/web/aes/free/manage.php new file mode 100644 index 0000000..68bfdf0 --- /dev/null +++ b/system/sections/web/aes/free/manage.php @@ -0,0 +1,29 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', ''); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/aes/free/update.php b/system/sections/web/aes/free/update.php new file mode 100644 index 0000000..3971e3c --- /dev/null +++ b/system/sections/web/aes/free/update.php @@ -0,0 +1,65 @@ +query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + // Проверка времени последнего обновления + include(LIB.'games/games.php'); + + $upd = $web['update']+86400; + + if($upd > $start_point) + sys::outjs(array('e' => 'Для повторного обновления должно пройти: '.games::date('max', $upd))); + + include(LIB.'ssh.php'); + + if($aWebUnit['unit'][$url['subsection']] == 'local') + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + }else{ + $unit = array( + 'address' => $aWebUnit['address'], + 'passwd' => $aWebUnit['passwd'], + ); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $install = $aWebUnit['install'][$aWebUnit['unit'][$url['subsection']]][$url['subsection']].$web['domain']; + + $path = $aWebUnit['path'][$aWebUnit['unit'][$url['subsection']]][$url['subsection']].$web['desing']; + + $ssh->set('cat '.$install.'/include/db.config.inc.php > '.$path.'/include/db.config.inc.php;' + .'cd '.$install.' && sudo -u web'.$web['uid'].' screen -dmS u_w_'.$web['uid'].' sh -c "YES | cp -rf '.$path.'/. .; '.$aWebChmod[$url['subsection']].'"'); + + $sql->query('UPDATE `web` set `update`="'.$start_point.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/amxbans/free/connect.php b/system/sections/web/amxbans/free/connect.php new file mode 100644 index 0000000..732a9ed --- /dev/null +++ b/system/sections/web/amxbans/free/connect.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/system/sections/web/amxbans/free/delete.php b/system/sections/web/amxbans/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/amxbans/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/amxbans/free/install.php b/system/sections/web/amxbans/free/install.php new file mode 100644 index 0000000..8b7ff24 --- /dev/null +++ b/system/sections/web/amxbans/free/install.php @@ -0,0 +1,60 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = 'amx_sql_host "[host]"'.PHP_EOL + .'amx_sql_user "[login]"'.PHP_EOL + .'amx_sql_pass "[passwd]"'.PHP_EOL + .'amx_sql_db "[login]"'.PHP_EOL + .'amx_sql_table "admins"'.PHP_EOL + .'amx_sql_type "mysql"'; + + $aData['config_php'] = 'db_host = "[host]";'.PHP_EOL + .' $config->db_user = "[login]";'.PHP_EOL + .' $config->db_pass = "[passwd]";'.PHP_EOL + .' $config->db_db = "[login]";'.PHP_EOL + .' $config->db_prefix = "amx";'.PHP_EOL + .'?>'; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/amxbans/free/manage.php b/system/sections/web/amxbans/free/manage.php new file mode 100644 index 0000000..bf62ce5 --- /dev/null +++ b/system/sections/web/amxbans/free/manage.php @@ -0,0 +1,57 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', $options); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/amxbans/free/passwd.php b/system/sections/web/amxbans/free/passwd.php new file mode 100644 index 0000000..5945d09 --- /dev/null +++ b/system/sections/web/amxbans/free/passwd.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::passwd($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/amxbans/free/update.php b/system/sections/web/amxbans/free/update.php new file mode 100644 index 0000000..97689c3 --- /dev/null +++ b/system/sections/web/amxbans/free/update.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::update($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/astats/free/connect.php b/system/sections/web/astats/free/connect.php new file mode 100644 index 0000000..21d8862 --- /dev/null +++ b/system/sections/web/astats/free/connect.php @@ -0,0 +1,97 @@ + 'Необходимо выбрать игровой сервер.'), $nmch); + $aData['type'] = $url['subsection']; + + switch($aWebInstall[$server['game']][$aData['type']]) + { + case 'server': + $sql->query('SELECT `unit`, `domain`, `login` FROM `web` WHERE `type`="'.$aData['type'].'" AND `server`="'.$server['id'].'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `unit`, `domain`, `login` FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `unit`, `domain`, `login` FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + $aData['config'] = 'query('SELECT `id`, `uid`, `unit`, `user`, `address`, `game`, `ftp_use`, `ftp`, `ftp_root`, `ftp_passwd` FROM `servers` WHERE `id`="'.$sid.'" AND `user`="'.$server['user'].'" AND `game`="cs" LIMIT 1'); + if(!$sql->num()) + continue; + + $server = $sql->get(); + + $address = explode(':', $server['address']); + + if(!$server['ftp_use']) + continue; + + if(!$server['ftp']) + sys::outjs(array('r' => 'Для подключения игрового сервера необходимо включить FileTP.', 'url' => $cfg['http'].'servers/id/'.$sid.'/section/filetp'), $nmch); + + $stack = web::stack($aData, '`login`'); + + if(!$sql->num($stack)) + continue; + + // Каталог логов сервера + $dir = ($cfg['ftp']['root'][$server['game']] || $server['ftp_root']) ? '/cstrike/addons/amxmodx/data' : '/addons/amxmodx/data'; + + $i+=1; + + $aData['config'] .= $i.' => array('.PHP_EOL + .'\'ip\' => \''.$address[0].'\','.PHP_EOL + .'\'port\' => '.$address[1].','.PHP_EOL + .'\'engine\' => \'GOLDSOURCE\','.PHP_EOL + .'\'ftp_host\' => \''.$address[0].'\','.PHP_EOL + .'\'ftp_port\' => 21,'.PHP_EOL + .'\'ftp_user\' => \''.$server['uid'].'\','.PHP_EOL + .'\'ftp_pass\' => \''.$server['ftp_passwd'].'\','.PHP_EOL + .'\'ftp_path\' => \''.$dir.'\''.PHP_EOL + .'),'.PHP_EOL; + + } + + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('ssh', 'error')), $nmch); + + // Директория дополнительной услуги + $install = $aWebUnit['install'][$aWebUnit['unit'][$aData['type']]][$aData['type']].$web['domain']; + + $temp = sys::temp($aData['config'].');'); + $ssh->setfile($temp, $install.'/config/servers.config.php', 0644); + + unlink($temp); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/astats/free/delete.php b/system/sections/web/astats/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/astats/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/astats/free/install.php b/system/sections/web/astats/free/install.php new file mode 100644 index 0000000..9824f1a --- /dev/null +++ b/system/sections/web/astats/free/install.php @@ -0,0 +1,47 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = ''; + $aData['config_php'] = ''; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/astats/free/manage.php b/system/sections/web/astats/free/manage.php new file mode 100644 index 0000000..bf62ce5 --- /dev/null +++ b/system/sections/web/astats/free/manage.php @@ -0,0 +1,57 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', $options); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/astats/free/update.php b/system/sections/web/astats/free/update.php new file mode 100644 index 0000000..97689c3 --- /dev/null +++ b/system/sections/web/astats/free/update.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::update($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/bp/free/delete.php b/system/sections/web/bp/free/delete.php new file mode 100644 index 0000000..1ea4a90 --- /dev/null +++ b/system/sections/web/bp/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $name_mcache); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/web/bp/free/install.php b/system/sections/web/bp/free/install.php new file mode 100644 index 0000000..f1d8120 --- /dev/null +++ b/system/sections/web/bp/free/install.php @@ -0,0 +1,103 @@ + 'Необходимо указать адрес.'), $name_mcache); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $name_mcache); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $name_mcache); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $sql->query('SELECT `mail`, `contacts` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + $us = $sql->get(); + + if($us['contacts'] == '') + sys::outjs(array('e' => 'Укажите в профиле контактную информацию')); + + if(strpos($us['contacts'], 'ttp', 1)) + { + $vk = $us['contacts']; + $skype = ''; + }else{ + $vk = ''; + $skype = $us['contacts']; + } + + $aData['config_sql'] = ''; + + $aData['config_php'] = ' "[host]",'.PHP_EOL + ."\t\t\t".'\'db_user\' => "[login]",'.PHP_EOL + ."\t\t\t".'\'db_pass\' => "[passwd]",'.PHP_EOL + ."\t\t\t".'\'db_name\' => "[login]",'.PHP_EOL + ."\t\t\t".'\'db_prefix\' => "bp"'.PHP_EOL + ."\t\t".');'.PHP_EOL + ."\t".'}'.PHP_EOL + ."\t".'@mb_internal_encoding("UTF-8");'.PHP_EOL + ."\t".'@date_default_timezone_set("Europe/Moscow");'.PHP_EOL + ."\t".'$site_name = "Online Market";'.PHP_EOL + ."\t".'$url = "http://'.$aData['subdomain'].'.'.$aData['domain'].'/";'.PHP_EOL + ."\t".'$num_page = "15";'.PHP_EOL + ."\t".'$cron = "874319";'.PHP_EOL + ."\n\t".'$wmr_on = "0";'.PHP_EOL + ."\t".'$purse = "";'.PHP_EOL + ."\t".'$secret_key = "";'.PHP_EOL + ."\t".'$uni_on = "0";'.PHP_EOL + ."\t".'$uni_purse = "";'.PHP_EOL + ."\t".'$uni_secret_key = "";'.PHP_EOL + ."\t".'$robo_on = "0";'.PHP_EOL + ."\t".'$robo_login = "";'.PHP_EOL + ."\t".'$robo_pass1 = "";'.PHP_EOL + ."\t".'$robo_pass2 = "";'.PHP_EOL + ."\t".'$curr = "руб.";'.PHP_EOL + ."\t".'$adm_login = "admin";'.PHP_EOL + ."\t".'$adm_pass = "[passwd]";'.PHP_EOL + ."\t".'$adm_ip = "";'.PHP_EOL + ."\t".'$to = "'.$us['mail'].'";'.PHP_EOL + ."\t".'$vk = "'.$vk.'";'.PHP_EOL + ."\t".'$skype = "'.$skype.'";'.PHP_EOL + ."\t".'require_once "core.php";'.PHP_EOL + ."\t".'$db = new DataBase();'.PHP_EOL + ."\t".'$eng = new Engine();'.PHP_EOL + ."\t".'$at = new Auth();'.PHP_EOL + .'?>'; + + include(LIB.'web/free.php'); + + web::install($aData, $name_mcache); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/bp/free/manage.php b/system/sections/web/bp/free/manage.php new file mode 100644 index 0000000..de16d4e --- /dev/null +++ b/system/sections/web/bp/free/manage.php @@ -0,0 +1,40 @@ +query('SELECT `domain`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `domain`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `domain`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/bp/free/settings.php b/system/sections/web/bp/free/settings.php new file mode 100644 index 0000000..ef93d4e --- /dev/null +++ b/system/sections/web/bp/free/settings.php @@ -0,0 +1,141 @@ +query('SELECT `id`, `domain` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `id`, `domain` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `domain` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + } + + if(!$sql->num()) + exit; + + $web = $sql->get(); + + include(DATA.'web.php'); + + include(LIB.'web/free.php'); + include(LIB.'ssh.php'); + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $name_mcache); + + // Директория дополнительной услуги + $install = $aWebUnit['install'][$aWebUnit['unit'][$url['subsection']]][$url['subsection']].$web['domain']; + + $unit = web::unit($aWebUnit, $aData['type'], $web['unit']); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $name_mcache); + + $arSel = array('$adm_login', '$adm_pass', '$wmr_on', '$purse', '$secret_key', '$to', '$vk', '$skype'); + + $conf = explode("\n", $ssh->get('cat '.$install.'/core/cfg.php')); + + $aData = array(); + + if($go) + { + $aData['bp_login'] = isset($_POST['bp_login']) ? trim($_POST['bp_login']) : ''; + $aData['bp_passwd'] = isset($_POST['bp_passwd']) ? trim($_POST['bp_passwd']) : ''; + $aData['bp_mail'] = isset($_POST['bp_mail']) ? trim($_POST['bp_mail']) : ''; + $aData['bp_vk'] = isset($_POST['bp_vk']) ? trim($_POST['bp_vk']) : ''; + $aData['bp_skype'] = isset($_POST['bp_skype']) ? trim($_POST['bp_skype']) : ''; + $aData['bp_webmoney'] = isset($_POST['bp_webmoney']) ? $_POST['bp_webmoney'] : '0'; + $aData['bp_wmr'] = isset($_POST['bp_wmr']) ? trim($_POST['bp_wmr']) : ''; + $aData['bp_sign_key'] = isset($_POST['bp_sign_key']) ? trim($_POST['bp_sign_key']) : ''; + + $aData['bp_webmoney'] = $aData['bp_webmoney'] == 'on' ? '1' : '0'; + + foreach($aData as $var => $val) + $aData[$var] = str_replace('"', '', $val); + + $str_search = array( + '#\$adm_login = ".*"#iu', + '#\$adm_pass = ".*"#iu', + '#\$to = ".*"#iu', + '#\$vk = ".*"#iu', + '#\$skype = ".*"#iu', + '#\$wmr_on = ".*"#iu', + '#\$purse = ".*"#iu', + '#\$secret_key = ".*"#iu', + ); + + $str_replace = array( + '$adm_login = "'.$aData['bp_login'].'"', + '$adm_pass = "'.$aData['bp_passwd'].'"', + '$to = "'.$aData['bp_mail'].'"', + '$vk = "'.$aData['bp_vk'].'"', + '$skype = "'.$aData['bp_skype'].'"', + '$wmr_on = "'.$aData['bp_webmoney'].'"', + '$purse = "'.$aData['bp_wmr'].'"', + '$secret_key = "'.$aData['bp_sign_key'].'"' + ); + + $data = ''; + + foreach($conf as $line => $val) + { + if($val == 'setfile($temp, $install.'/core/cfg.php', 0644); + + sys::outjs(array('s' => 'ok'), $name_mcache); + } + + foreach($conf as $str) + { + $aStr = explode('=', $str); + + if(!isset($aStr[0]) || !isset($aStr[1])) + continue; + + $var = trim($aStr[0]); + $val = str_replace(array('"', ';'), '', trim($aStr[1])); + + if(!in_array($var, $arSel)) + continue; + + $aData[$var] = isset($val{0}) ? $val : ''; + } + + $webmoney = $aData['$wmr_on'] == 'on' ? '' : ''; + + sys::outjs(array( + 's' => 'ok', + 'bp_login' => $aData['$adm_login'], + 'bp_passwd' => $aData['$adm_pass'], + 'bp_mail' => $aData['$to'], + 'bp_vk' => $aData['$vk'], + 'bp_skype' => $aData['$skype'], + 'bp_wmr' => $aData['$purse'], + 'bp_sign_key' => $aData['$secret_key'], + 'bp_webmoney' => $webmoney), $name_mcache); +?> \ No newline at end of file diff --git a/system/sections/web/csbans/free/connect.php b/system/sections/web/csbans/free/connect.php new file mode 100644 index 0000000..732a9ed --- /dev/null +++ b/system/sections/web/csbans/free/connect.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/system/sections/web/csbans/free/delete.php b/system/sections/web/csbans/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/csbans/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/csbans/free/install.php b/system/sections/web/csbans/free/install.php new file mode 100644 index 0000000..8b7ff24 --- /dev/null +++ b/system/sections/web/csbans/free/install.php @@ -0,0 +1,60 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = 'amx_sql_host "[host]"'.PHP_EOL + .'amx_sql_user "[login]"'.PHP_EOL + .'amx_sql_pass "[passwd]"'.PHP_EOL + .'amx_sql_db "[login]"'.PHP_EOL + .'amx_sql_table "admins"'.PHP_EOL + .'amx_sql_type "mysql"'; + + $aData['config_php'] = 'db_host = "[host]";'.PHP_EOL + .' $config->db_user = "[login]";'.PHP_EOL + .' $config->db_pass = "[passwd]";'.PHP_EOL + .' $config->db_db = "[login]";'.PHP_EOL + .' $config->db_prefix = "amx";'.PHP_EOL + .'?>'; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/csbans/free/manage.php b/system/sections/web/csbans/free/manage.php new file mode 100644 index 0000000..bf62ce5 --- /dev/null +++ b/system/sections/web/csbans/free/manage.php @@ -0,0 +1,57 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', $options); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/csbans/free/passwd.php b/system/sections/web/csbans/free/passwd.php new file mode 100644 index 0000000..5945d09 --- /dev/null +++ b/system/sections/web/csbans/free/passwd.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::passwd($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/csbans/free/update.php b/system/sections/web/csbans/free/update.php new file mode 100644 index 0000000..97689c3 --- /dev/null +++ b/system/sections/web/csbans/free/update.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::update($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/csstats/free/connect.php b/system/sections/web/csstats/free/connect.php new file mode 100644 index 0000000..3f5090b --- /dev/null +++ b/system/sections/web/csstats/free/connect.php @@ -0,0 +1,30 @@ + 'Длина ключа не должна превышать 32 символа.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array(); + + $aData['server'] = sys::int($url['server']); + $aData['type'] = $url['subsection']; + $aData['user'] = $server['user']; + $aData['file'] = 'cstrike/addons/amxmodx/configs/csstats_mysql.cfg'; + $aData['cfg'] = 'cstrike/server.cfg'; + + $aData['orcfg'] = array( + 'key' => $key + ); + + $aData['orsql'] = array(); + + web::connect($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/csstats/free/delete.php b/system/sections/web/csstats/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/csstats/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/csstats/free/install.php b/system/sections/web/csstats/free/install.php new file mode 100644 index 0000000..c631da5 --- /dev/null +++ b/system/sections/web/csstats/free/install.php @@ -0,0 +1,75 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = 'csstats_key "[key]"'.PHP_EOL + .'csstats_url "[domain]"'.PHP_EOL + .'csstats_sort "-2"'.PHP_EOL + .'csstats_double "0"'.PHP_EOL + .'csstats_host "[host]"'.PHP_EOL + .'csstats_user "[login]"'.PHP_EOL + .'csstats_pass "[passwd]"'.PHP_EOL + .'csstats_db "[login]"'.PHP_EOL + .'csstats_table_players "csstats_players"'.PHP_EOL + .'csstats_table_settings "csstats_settings"'.PHP_EOL + .'csstats_delete_time "15 120 2"'.PHP_EOL + .'csstats_insert_time "60 1"'.PHP_EOL + .'csstats_update_time "30 0"'.PHP_EOL + .'csstats_slow "0"'; + + $aData['config_php'] = ''; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/csstats/free/manage.php b/system/sections/web/csstats/free/manage.php new file mode 100644 index 0000000..68bfdf0 --- /dev/null +++ b/system/sections/web/csstats/free/manage.php @@ -0,0 +1,29 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', ''); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/csstats/free/update.php b/system/sections/web/csstats/free/update.php new file mode 100644 index 0000000..3971e3c --- /dev/null +++ b/system/sections/web/csstats/free/update.php @@ -0,0 +1,65 @@ +query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `uid`, `desing`, `domain`, `update` FROM `web` WHERE `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + // Проверка времени последнего обновления + include(LIB.'games/games.php'); + + $upd = $web['update']+86400; + + if($upd > $start_point) + sys::outjs(array('e' => 'Для повторного обновления должно пройти: '.games::date('max', $upd))); + + include(LIB.'ssh.php'); + + if($aWebUnit['unit'][$url['subsection']] == 'local') + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + }else{ + $unit = array( + 'address' => $aWebUnit['address'], + 'passwd' => $aWebUnit['passwd'], + ); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $install = $aWebUnit['install'][$aWebUnit['unit'][$url['subsection']]][$url['subsection']].$web['domain']; + + $path = $aWebUnit['path'][$aWebUnit['unit'][$url['subsection']]][$url['subsection']].$web['desing']; + + $ssh->set('cat '.$install.'/include/db.config.inc.php > '.$path.'/include/db.config.inc.php;' + .'cd '.$install.' && sudo -u web'.$web['uid'].' screen -dmS u_w_'.$web['uid'].' sh -c "YES | cp -rf '.$path.'/. .; '.$aWebChmod[$url['subsection']].'"'); + + $sql->query('UPDATE `web` set `update`="'.$start_point.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/hosting/free/delete.php b/system/sections/web/hosting/free/delete.php new file mode 100644 index 0000000..5b683c9 --- /dev/null +++ b/system/sections/web/hosting/free/delete.php @@ -0,0 +1,42 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + // Проверка на наличие установленной услуги + switch($aWebInstall[$server['game']][$url['subsection']]) + { + case 'server': + $sql->query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + break; + } + + if(!$sql->num()) + sys::outjs(array('i' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + // Удаление вирт. хостинга + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['account']['delete'], array('login' => $web['login']))), true); + + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + sys::outjs(array('e' => 'Не удалось удалить виртуальный хостинг.'), $nmch); + + // Обновление данных + $sql->query('DELETE FROM `web` WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/hosting/free/install.php b/system/sections/web/hosting/free/install.php new file mode 100644 index 0000000..c28d0b5 --- /dev/null +++ b/system/sections/web/hosting/free/install.php @@ -0,0 +1,163 @@ + 'Недоступно для данного тарифа.'), $nmch); + + if($aWebVHTtype && in_array($server['tarif'], $aWebVHT)) + sys::outjs(array('e' => 'Недоступно для данного тарифа.'), $nmch); + + $aData = array(); + + $aData['subdomain'] = isset($_POST['subdomain']) ? strtolower($_POST['subdomain']) : sys::outjs(array('e' => 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + + if(!$aWeb[$server['game']][$aData['type']]) + sys::outjs(array('e' => 'Дополнительная услуга недоступна для установки.'), $nmch); + + // Проверка на наличие уже установленной выбранной услуги + switch($aWebInstall[$server['game']][$aData['type']]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$aData['type'].'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$aData['type'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + break; + } + + if($sql->num()) + sys::outjs(array('i' => 'Дополнительная услуга уже установлена.'), $nmch); + + // Проверка на наличие уже установленной подобной услуги + switch($aWebInstall[$server['game']][$aData['type']]) + { + case 'server': + foreach($aWebOne[$server['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `server`="'.$id.'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $nmch); + } + break; + + case 'user': + foreach($aWebOne[$server['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `user`="'.$server['user'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $nmch); + } + break; + + case 'unit': + foreach($aWebOne[$server['game']][$aData['type']] as $type) + { + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$type.'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('i' => 'Подобная услуга уже установлена.', 'type' => $type), $nmch); + } + } + + // Проверка валидности поддомена + if(sys::valid($aData['subdomain'], 'other', "/^[a-z0-9]+$/")) + sys::outjs(array('e' => 'Адрес должен состоять из букв a-z и цифр.'), $nmch); + + // Проверка длины поддомена + if(!isset($aData['subdomain']{3}) || isset($aData['subdomain']{15})) + sys::outjs(array('e' => 'Длина адреса не должна превышать 16-и символов и быть не менее 4-х символов.'), $nmch); + + // Проверка наличия основного домена + if(!in_array($aData['domain'], $aWebUnit['domains'])) + sys::outjs(array('e' => 'Выбранный домен не найден.'), $nmch); + + // Проверка запрещенного поддомена + if(in_array($aData['subdomain'], $aWebUnit['subdomains'])) + sys::outjs(array('e' => 'Нельзя создать данный адрес, придумайте другой.'), $nmch); + + // Проверка поддомена на занятость + $sql->query('SELECT `id` FROM `web` WHERE `domain`="'.$aData['subdomain'].'.'.$aData['domain'].'" LIMIT 1'); + if($sql->num()) + sys::outjs(array('e' => 'Данный адрес уже занят.'), $nmch); + + // Если не указан пароль сгенерировать + if($aData['passwd'] == '') + $aData['passwd'] = sys::passwd($aWebParam[$aData['type']]['passwd']); + + // Проверка длинны пароля + if(!isset($aData['passwd']{5})) + sys::outjs(array('e' => 'Необходимо указать пароль длинной не менее 6-и символов.'), $nmch); + + // Проверка валидности пароля + if(sys::valid($aData['passwd'], 'other', "/^[A-Za-z0-9]{6,16}$/")) + sys::outjs(array('e' => 'Пароль должен состоять из букв a-z и цифр, не менее 4-х и не более 16-и символов.'), $nmch); + + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$server['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо указать пользователя игрового сервера.'), $nmch); + + $u = $sql->get(); + + $sql->query('INSERT INTO `web` set `type`="'.$aData['type'].'", `server`="'.$id.'", `user`="'.$server['user'].'", `unit`="0", `config`=""'); + $wid = $sql->id(); + $uid = $wid+10000; + + $login = 'h'.$uid; + + if(in_array($aData['subdomain'], $aWebUnit['isp']['subdomains'])) + { + $sql->query('DELETE FROM `web` WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('e' => 'Нельзя создать указанный поддомен, придумайте что-то другое.'), $mcache); + } + + // Создание вирт. хостинга + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['account']['create'], + array('login' => $login, + 'mail' => $u['mail'], + 'passwd' => $aData['passwd'], + 'domain' => $aData['subdomain'].'.'.$aData['domain']) + )), true); + + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + { + $sql->query('DELETE FROM `web` WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('e' => 'Не удалось создать виртуальный хостинг, обратитесь в тех.поддержку.'), $nmch); + } + + // Обновление данных + $sql->query('UPDATE `web` set `uid`="'.$uid.'", ' + .'`domain`="'.$aData['subdomain'].'.'.$aData['domain'].'", ' + .'`passwd`="'.$aData['passwd'].'", ' + .'`login`="'.$login.'", `date`="'.$start_point.'" ' + .'WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + $html->set('id', $id); + $html->set('domains', $domains); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/hosting/free/manage.php b/system/sections/web/hosting/free/manage.php new file mode 100644 index 0000000..a9cbd71 --- /dev/null +++ b/system/sections/web/hosting/free/manage.php @@ -0,0 +1,52 @@ +query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `user`="'.$server['user'].'" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `user`="'.$server['user'].'" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $aWebUnit['isp']['panel']); + $html->set('login', $web['login']); + $html->set('passwd', $web['passwd']); + $html->set('date', sys::today($web['date'])); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/hosting/free/passwd.php b/system/sections/web/hosting/free/passwd.php new file mode 100644 index 0000000..564651b --- /dev/null +++ b/system/sections/web/hosting/free/passwd.php @@ -0,0 +1,52 @@ +query('SELECT `id`, `login`, `user` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id`, `login`, `user` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id`, `login`, `user` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + break; + } + + if(!$sql->num()) + sys::outjs(array('i' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + $sql->query('SELECT `mail` FROM `users` WHERE `id`="'.$web['user'].'" LIMIT 1'); + if(!$sql->num()) + sys::outjs(array('e' => 'Необходимо указать пользователя доп. услуги.'), $nmch); + + $u = $sql->get(); + + $passwd = sys::passwd($aWebParam[$url['subsection']]['passwd']); + + // Смена пароля вирт. хостинга + $result = json_decode(file_get_contents(sys::updtext($aWebUnit['isp']['account']['passwd'], + array('login' => $web['login'], + 'mail' => $u['mail'], + 'hdd' => $aWebUnit['isp']['hdd'], + 'passwd' => $passwd) + )), true); + + if(!isset($result['result']) || strtolower($result['result']) != 'ok') + sys::outjs(array('e' => 'Не удалось изменить пароль виртуального хостинга, обратитесь в тех.поддержку.'), $nmch); + + // Обновление данных + $sql->query('UPDATE `web` set `passwd`="'.$passwd.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/mysql/free/delete.php b/system/sections/web/mysql/free/delete.php new file mode 100644 index 0000000..4aaac0e --- /dev/null +++ b/system/sections/web/mysql/free/delete.php @@ -0,0 +1,55 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + switch($aWebInstall[$server['game']][$url['subsection']]) + { + case 'server': + $sql->query('SELECT `id`, `uid`, `unit`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `id`, `uid`, `unit`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `uid`, `unit`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + if($aWebUnit['unit'][$url['subsection']] == 'local') + { + $sql->query('SELECT `address`, `passwd` FROM `units` WHERE `id`="'.$web['unit'].'" LIMIT 1'); + $unit = $sql->get(); + }else{ + $unit = array( + 'address' => $aWebUnit['address'], + 'passwd' => $aWebUnit['passwd'], + ); + } + + include(LIB.'ssh.php'); + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('error', 'ssh')), $nmch); + + $ssh->set("mysql --login-path=local -e \"DROP DATABASE IF EXISTS ".$web['login']."; DROP USER ".$web['login']."\""); + + $sql->query('DELETE FROM `web` WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/mysql/free/install.php b/system/sections/web/mysql/free/install.php new file mode 100644 index 0000000..9b44c06 --- /dev/null +++ b/system/sections/web/mysql/free/install.php @@ -0,0 +1,99 @@ + 'Дополнительная услуга недоступна для установки.'), $nmch); + + // Проверка на наличие уже установленной выбранной услуги + switch($aWebInstall[$server['game']][$url['subsection']]) + { + case 'server': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + break; + } + + if($sql->num()) + sys::outjs(array('s' => 'ok'), $nmch); + + include(LIB.'ssh.php'); + + if($aWebUnit['unit'][$url['subsection']] == 'local') + { + $sql->query('SELECT `address`, `passwd`, `domain` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + + $pma = $unit['domain']; + }else{ + $unit = array( + 'address' => $aWebUnit['address'], + 'passwd' => $aWebUnit['passwd'], + ); + + $pma = $aWebUnit['pma']; + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('ssh', 'error')), $nmch); + + if(isset($_POST['passwd'])) + { + // Если не указан пароль сгенерировать + if($_POST['passwd'] == '') + $passwd = sys::passwd($aWebParam[$url['subsection']]['passwd']); + else{ + // Проверка длинны пароля + if(!isset($_POST['passwd']{5}) || isset($_POST['passwd']{16})) + sys::outjs(array('e' => 'Необходимо указать пароль длинной не менее 6-и символов и не более 16-и.'), $nmch); + + // Проверка валидности пароля + if(sys::valid($_POST['passwd'], 'other', "/^[A-Za-z0-9]{6,16}$/")) + sys::outjs(array('e' => 'Пароль должен состоять из букв a-z и цифр.'), $nmch); + + $passwd = $_POST['passwd']; + } + }else + $passwd = sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $sql->query('INSERT INTO `web` set `type`="'.$url['subsection'].'", `server`="'.$id.'", `user`="'.$server['user'].'", `unit`="'.$server['unit'].'", `config`=""'); + $wid = $sql->id(); + $uid = $wid+10000; + + // Данные + $login = substr('sql_'.$wid.'_free', 0, 14); + + $sql_q = 'mysql --login-path=local -e "CREATE DATABASE '.$login.';' + ."CREATE USER '".$login."'@'%' IDENTIFIED BY '".$passwd."';" + .'GRANT ALL PRIVILEGES ON '.$login.' . * TO \''.$login.'\'@\'%\';";'; + + $ssh->set($sql_q); + + // Обновление данных + $sql->query('UPDATE `web` set `uid`="'.$uid.'",' + .'`domain`="'.$pma.'",' + .'`passwd`="'.$passwd.'",' + .'`login`="'.$login.'", `date`="'.$start_point.'" ' + .'WHERE `id`="'.$wid.'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/mysql/free/manage.php b/system/sections/web/mysql/free/manage.php new file mode 100644 index 0000000..23725c1 --- /dev/null +++ b/system/sections/web/mysql/free/manage.php @@ -0,0 +1,39 @@ +query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + break; + + case 'user': + $sql->query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `domain`, `passwd`, `login`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('login', $web['login']); + $html->set('passwd', $web['passwd']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/mysql/free/passwd.php b/system/sections/web/mysql/free/passwd.php new file mode 100644 index 0000000..e7319e7 --- /dev/null +++ b/system/sections/web/mysql/free/passwd.php @@ -0,0 +1,53 @@ +query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + break; + + case 'user': + $sql->query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + break; + + case 'unit': + $sql->query('SELECT `id`, `login` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + break; + } + + if(!$sql->num()) + sys::outjs(array('e' => 'Дополнительная услуга не установлена.'), $nmch); + + $web = $sql->get(); + + include(LIB.'ssh.php'); + + if($aWebUnit['unit'][$url['subsection']] == 'local') + { + $sql->query('SELECT `address`, `passwd`, `domain` FROM `units` WHERE `id`="'.$server['unit'].'" LIMIT 1'); + $unit = $sql->get(); + }else{ + $unit = array( + 'address' => $aWebUnit['address'], + 'passwd' => $aWebUnit['passwd'], + ); + } + + if(!$ssh->auth($unit['passwd'], $unit['address'])) + sys::outjs(array('e' => sys::text('ssh', 'error')), $nmch); + + $passwd = sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $ssh->set('mysql --login-path=local -e "SET PASSWORD FOR \''.$web['login'].'\'@\'%\' = PASSWORD(\''.$passwd.'\');"'); + + // Обновление данных + $sql->query('UPDATE `web` set `passwd`="'.$passwd.'" WHERE `id`="'.$web['id'].'" LIMIT 1'); + + sys::outjs(array('s' => 'ok'), $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/connect.php b/system/sections/web/sourcebans/free/connect.php new file mode 100644 index 0000000..ffc8e67 --- /dev/null +++ b/system/sections/web/sourcebans/free/connect.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/delete.php b/system/sections/web/sourcebans/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/sourcebans/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/install.php b/system/sections/web/sourcebans/free/install.php new file mode 100644 index 0000000..d4884d4 --- /dev/null +++ b/system/sections/web/sourcebans/free/install.php @@ -0,0 +1,81 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = '"Databases"'.PHP_EOL + .'{'.PHP_EOL + .' "driver_default" "mysql"'.PHP_EOL + .''.PHP_EOL + .' "sourcebans"'.PHP_EOL + .' {'.PHP_EOL + .' "driver" "mysql"'.PHP_EOL + .' "host" "[host]"'.PHP_EOL + .' "database" "[login]"'.PHP_EOL + .' "user" "[login]"'.PHP_EOL + .' "pass" "[passwd]"'.PHP_EOL + .' //"timeout" "0"'.PHP_EOL + .' "port" "3306"'.PHP_EOL + .' }'.PHP_EOL + .''.PHP_EOL + .' "storage-local"'.PHP_EOL + .' {'.PHP_EOL + .' "driver" "sqlite"'.PHP_EOL + .' "database" "sourcemod-local"'.PHP_EOL + .' }'.PHP_EOL + .'}'; + + $aData['config_php'] = ''; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/manage.php b/system/sections/web/sourcebans/free/manage.php new file mode 100644 index 0000000..210f5f4 --- /dev/null +++ b/system/sections/web/sourcebans/free/manage.php @@ -0,0 +1,57 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `game`="'.$server['game'].'" AND `user`="'.$server['user'].'" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `game`="'.$server['game'].'" AND `user`="'.$server['user'].'" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', $options); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/passwd.php b/system/sections/web/sourcebans/free/passwd.php new file mode 100644 index 0000000..5945d09 --- /dev/null +++ b/system/sections/web/sourcebans/free/passwd.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::passwd($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/sourcebans/free/update.php b/system/sections/web/sourcebans/free/update.php new file mode 100644 index 0000000..97689c3 --- /dev/null +++ b/system/sections/web/sourcebans/free/update.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::update($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/superban/free/connect.php b/system/sections/web/superban/free/connect.php new file mode 100644 index 0000000..732a9ed --- /dev/null +++ b/system/sections/web/superban/free/connect.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/system/sections/web/superban/free/delete.php b/system/sections/web/superban/free/delete.php new file mode 100644 index 0000000..0f47665 --- /dev/null +++ b/system/sections/web/superban/free/delete.php @@ -0,0 +1,19 @@ + 'Чтобы удалить услугу, создайте вопрос выбрав свой сервер с причиной удаления.'), $nmch); + + include(LIB.'web/free.php'); + + $aData = array( + 'type' => $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::delete($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/superban/free/install.php b/system/sections/web/superban/free/install.php new file mode 100644 index 0000000..8b7ff24 --- /dev/null +++ b/system/sections/web/superban/free/install.php @@ -0,0 +1,60 @@ + 'Необходимо указать адрес.'), $nmch); + $aData['domain'] = isset($_POST['domain']) ? strtolower($_POST['domain']) : sys::outjs(array('e' => 'Необходимо выбрать домен.'), $nmch); + $aData['desing'] = isset($_POST['desing']) ? strtolower($_POST['desing']) : sys::outjs(array('e' => 'Необходимо выбрать шаблон.'), $nmch); + $aData['passwd'] = isset($_POST['passwd']) ? $_POST['passwd'] : sys::passwd($aWebParam[$url['subsection']]['passwd']); + + $aData['type'] = $url['subsection']; + $aData['server'] = array_merge($server, array('id' => $id)); + + $aData['config_sql'] = 'amx_sql_host "[host]"'.PHP_EOL + .'amx_sql_user "[login]"'.PHP_EOL + .'amx_sql_pass "[passwd]"'.PHP_EOL + .'amx_sql_db "[login]"'.PHP_EOL + .'amx_sql_table "admins"'.PHP_EOL + .'amx_sql_type "mysql"'; + + $aData['config_php'] = 'db_host = "[host]";'.PHP_EOL + .' $config->db_user = "[login]";'.PHP_EOL + .' $config->db_pass = "[passwd]";'.PHP_EOL + .' $config->db_db = "[login]";'.PHP_EOL + .' $config->db_prefix = "amx";'.PHP_EOL + .'?>'; + + web::install($aData, $nmch); + } + + $html->nav('Установка '.$aWebname[$url['subsection']]); + + $desing = ''; + + // Генерация списка шаблонов + foreach($aWebParam[$url['subsection']]['desing'] as $name => $desc) + $desing .= ''; + + $domains = ''; + + // Генерация списка доменов + foreach($aWebUnit['domains'] as $domain) + $domains .= ''; + + $html->get('install', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('desing', $desing); + $html->set('domains', $domains); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/superban/free/manage.php b/system/sections/web/superban/free/manage.php new file mode 100644 index 0000000..bf62ce5 --- /dev/null +++ b/system/sections/web/superban/free/manage.php @@ -0,0 +1,57 @@ +query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `server`="'.$id.'" LIMIT 1'); + + $options = ''; + + break; + + case 'user': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" LIMIT 1'); + + break; + + case 'unit': + $sql->query('SELECT `id`, `address`, `name` FROM `servers` WHERE `unit`="'.$server['unit'].'" AND `user`="'.$server['user'].'" AND `game`="cs" AND (`status`!="overdue" OR `status`!="block")'); + while($sers = $sql->get()) + $options .= ''; + + $sql->query('SELECT `domain`, `passwd`, `config`, `date` FROM `web` WHERE `type`="'.$url['subsection'].'" AND `user`="'.$server['user'].'" AND `unit`="'.$server['unit'].'" LIMIT 1'); + + break; + } + + if(!$sql->num()) + sys::back($cfg['http'].'servers/id/'.$id.'/section/web/subsection/'.$url['subsection'].'/action/install'); + + $web = $sql->get(); + + $html->nav('Управление '.$aWebname[$url['subsection']]); + + $html->get('manage', 'sections/web/'.$url['subsection'].'/free'); + + $html->set('id', $id); + + $html->set('url', $web['domain']); + $html->set('passwd', $web['passwd']); + $html->set('config', base64_decode($web['config'])); + $html->set('servers', $options); + + if(in_array('update', $aAction[$url['subsection']])) + $html->unit('update', 1); + else + $html->unit('update'); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/web/superban/free/passwd.php b/system/sections/web/superban/free/passwd.php new file mode 100644 index 0000000..5945d09 --- /dev/null +++ b/system/sections/web/superban/free/passwd.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::passwd($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/web/superban/free/update.php b/system/sections/web/superban/free/update.php new file mode 100644 index 0000000..97689c3 --- /dev/null +++ b/system/sections/web/superban/free/update.php @@ -0,0 +1,16 @@ + $url['subsection'], + 'server' => array_merge($server, array('id' => $id)) + ); + + web::update($aData, $nmch); +?> \ No newline at end of file diff --git a/system/sections/wiki/answer.php b/system/sections/wiki/answer.php new file mode 100644 index 0000000..6310fe5 --- /dev/null +++ b/system/sections/wiki/answer.php @@ -0,0 +1,44 @@ +nav('Категории вопросов', $cfg['http'].'wiki'); + + $quest = isset($url['question']) ? sys::int($url['question']) : sys::back($cfg['http'].'wiki'); + + $sql->query('SELECT `name`, `cat`, `tags` FROM `wiki` WHERE `id`="'.$quest.'" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'wiki'); + + $wiki = $sql->get(); + + $sql->query('SELECT `name` FROM `wiki_category` WHERE `id`="'.$wiki['cat'].'" LIMIT 1'); + $cat = $sql->get(); + + $title = $wiki['name']; + $description = $answer['text']; + $keywords = $wiki['tags']; + + $html->nav($cat['name'], $cfg['http'].'wiki/section/question/category/'.$wiki['cat']); + $html->nav('Ответ на вопрос'); + + $sql->query('SELECT `text` FROM `wiki_answer` WHERE `wiki`="'.$quest.'" LIMIT 1'); + $answer = $sql->get(); + + $aTags = explode(',', $wiki['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + $tags .= ''.$tag.''; + } + + $html->get('answer', 'sections/wiki'); + $html->set('id', $quest); + $html->set('question', $wiki['name']); + $html->set('text', htmlspecialchars_decode($answer['text'])); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/wiki/index.php b/system/sections/wiki/index.php new file mode 100644 index 0000000..4571016 --- /dev/null +++ b/system/sections/wiki/index.php @@ -0,0 +1,27 @@ +nav('Категории вопросов'); + + $cats = $sql->query('SELECT `id`, `name` FROM `wiki_category` ORDER BY `sort` ASC'); + while($cat = $sql->get($cats)) + { + $sql->query('SELECT `id` FROM `wiki` WHERE `cat`="'.$cat['id'].'" LIMIT 1'); + if(!$sql->num()) + continue; + + $html->get('list', 'sections/wiki/category'); + + $html->set('id', $cat['id']); + $html->set('name', $cat['name']); + + $html->pack('category'); + } + + $html->get('category', 'sections/wiki'); + + $html->set('list', isset($html->arr['category']) ? $html->arr['category'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/wiki/msearch.php b/system/sections/wiki/msearch.php new file mode 100644 index 0000000..a278599 --- /dev/null +++ b/system/sections/wiki/msearch.php @@ -0,0 +1,156 @@ + ''))); + + $mkey = md5($text.'wiki'); + + if($mcache->get($mkey) != '' AND !isset($url['tag'])) + sys::outjs(array('s' => $mcache->get($mkey))); + + if(!isset($text{2}) AND !isset($url['tag'])) + sys::outjs(array('s' => 'Для выполнения поиска, необходимо больше данных', $nmch)); + + $aWiki_q = array(); + $aNswer_q = array(); + + // Поиск по вопросу + $wiki_q = $sql->query('SELECT `id` FROM `wiki` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `tags` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 3'); + + // Поиск по тексту (ответу) + $answer_q = $sql->query('SELECT `wiki` FROM `wiki_answer` WHERE `text` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 5'); + + // Если нет ниодного совпадения по вводимому тексту + if(!$sql->num($wiki_q) AND !$sql->num($answer_q) AND !isset($url['tag'])) + { + // Поиск по словам + if(!strpos($text, ' ')) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + + // Массив слов + $aText = explode(' ', $text); + + // Метка, которая изменится в процессе, если будет найдено хоть одно совпадение + $sWord = false; + + foreach($aText as $word) + { + if($word == '' || !isset($word{2})) + continue; + + // Поиск по вопросу + $wiki_q = $sql->query('SELECT `id` FROM `wiki` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `tags` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 3'); + + // Поиск по тексту (ответу) + $answer_q = $sql->query('SELECT `wiki` FROM `wiki_answer` WHERE `text` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 5'); + + if($sql->num($wiki_q)) + $aWiki_q[] = $wiki_q; + + if($sql->num($answer_q)) + $aNswer_q[] = $answer_q; + } + + }else{ + $aWiki_q[] = $wiki_q; + $aNswer_q[] = $answer_q; + } + + if(!count($aWiki_q) AND !count($aNswer_q) AND !isset($url['tag'])) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + + // Защита от дублирования + $aResult = array(); + + foreach($aWiki_q as $index => $wiki_q) + { + // Генерация списка (совпадение по вопросу) + while($wiki = $sql->get($wiki_q)) + { + // Проверка дублирования + if(in_array($wiki['id'], $aResult)) + continue; + + $sql->query('SELECT `id`, `name`, `tags`, `date` FROM `wiki` WHERE `id`="'.$wiki['id'].'" LIMIT 1'); + $quest = $sql->get(); + + $aTags = explode(',', $quest['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + + $tags .= ''.$tag.''; + } + + $html->get('list', 'sections/wiki/question'); + + $html->set('id', $quest['id']); + $html->set('name', sys::find($quest['name'], $text)); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->set('date', sys::today($quest['date'])); + + $html->set('home', $cfg['http']); + + $html->pack('question'); + + array_push($aResult, $wiki['id']); + } + } + + foreach($aNswer_q as $index => $answer_q) + { + // Генерация списка (совпадение по ответу) + while($answer = $sql->get($answer_q)) + { + // Проверка дублирования + if(in_array($answer['wiki'], $aResult)) + continue; + + $sql->query('SELECT `id`, `name`, `tags`, `date` FROM `wiki` WHERE `id`="'.$answer['wiki'].'" LIMIT 1'); + $quest = $sql->get(); + + $aTags = explode(',', $quest['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + + $tags .= ''.$tag.''; + } + + $html->get('list', 'sections/wiki/question'); + + $html->set('id', $quest['id']); + $html->set('name', sys::find($quest['name'], $text)); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->set('date', sys::today($quest['date'])); + + $html->set('home', $cfg['http']); + + $html->pack('question'); + } + } + + $html->arr['question'] = isset($html->arr['question']) ? $html->arr['question'] : 'По вашему запросу ничего не найдено'; + + $mcache->set($mkey, $html->arr['question'], false, 15); + + sys::outjs(array('s' => $html->arr['question']), $nmch); +?> \ No newline at end of file diff --git a/system/sections/wiki/question.php b/system/sections/wiki/question.php new file mode 100644 index 0000000..1b66637 --- /dev/null +++ b/system/sections/wiki/question.php @@ -0,0 +1,46 @@ +nav('Категории вопросов', $cfg['http'].'wiki'); + $html->nav('Часто задаваемые вопросы'); + + $cat = isset($url['category']) ? sys::int($url['category']) : sys::back($cfg['http'].'wiki'); + + $sql->query('SELECT `name` FROM `wiki_category` WHERE `id`="'.$cat.'" LIMIT 1'); + if(!$sql->num()) + sys::back($cfg['http'].'wiki'); + + $category = $sql->get(); + + $sql->query('SELECT `id`, `name`, `tags`, `date` FROM `wiki` WHERE `cat`="'.$cat.'" ORDER BY `id` ASC'); + while($quest = $sql->get()) + { + $aTags = explode(',', $quest['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + + $tags .= ''.$tag.''; + } + + $html->get('list', 'sections/wiki/question'); + + $html->set('id', $quest['id']); + $html->set('name', $quest['name']); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->set('date', sys::today($quest['date'])); + + $html->pack('question'); + } + + $html->get('question', 'sections/wiki'); + + $html->set('category', $category['name']); + $html->set('list', isset($html->arr['question']) ? $html->arr['question'] : ''); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/system/sections/wiki/search.php b/system/sections/wiki/search.php new file mode 100644 index 0000000..a4fee85 --- /dev/null +++ b/system/sections/wiki/search.php @@ -0,0 +1,167 @@ + ''))); + + $mkey = md5($text.'wiki'); + + if($mcache->get($mkey) != '' AND !isset($url['tag'])) + sys::outjs(array('s' => $mcache->get($mkey))); + + if(!isset($text{2}) AND !isset($url['tag'])) + sys::outjs(array('s' => 'Для выполнения поиска, необходимо больше данных', $nmch)); + + $aWiki_q = array(); + $aNswer_q = array(); + + // Поиск по вопросу + $wiki_q = $sql->query('SELECT `id` FROM `wiki` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') OR `tags` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 5'); + + // Поиск по тексту (ответу) + $answer_q = $sql->query('SELECT `wiki` FROM `wiki_answer` WHERE `text` LIKE FROM_BASE64(\''.base64_encode('%'.$text.'%').'\') LIMIT 5'); + + // Если нет ниодного совпадения по вводимому тексту + if(!$sql->num($wiki_q) AND !$sql->num($answer_q) AND !isset($url['tag'])) + { + // Поиск по словам + if(!strpos($text, ' ')) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + + // Массив слов + $aText = explode(' ', $text); + + // Метка, которая изменится в процессе, если будет найдено хоть одно совпадение + $sWord = false; + + foreach($aText as $word) + { + if($word == '' || !isset($word{2})) + continue; + + // Поиск по вопросу + $wiki_q = $sql->query('SELECT `id` FROM `wiki` WHERE `name` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') OR `tags` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 5'); + + // Поиск по тексту (ответу) + $answer_q = $sql->query('SELECT `wiki` FROM `wiki_answer` WHERE `text` LIKE FROM_BASE64(\''.base64_encode('%'.$word.'%').'\') LIMIT 5'); + + if($sql->num($wiki_q)) + $aWiki_q[] = $wiki_q; + + if($sql->num($answer_q)) + $aNswer_q[] = $answer_q; + } + + }else{ + $aWiki_q[] = $wiki_q; + $aNswer_q[] = $answer_q; + } + + if(!count($aWiki_q) AND !count($aNswer_q) AND !isset($url['tag'])) + { + $mcache->set($mkey, 'По вашему запросу ничего не найдено', false, 15); + + sys::outjs(array('s' => 'По вашему запросу ничего не найдено')); + } + + // Защита от дублирования + $aResult = array(); + + foreach($aWiki_q as $index => $wiki_q) + { + // Генерация списка (совпадение по вопросу) + while($wiki = $sql->get($wiki_q)) + { + // Проверка дублирования + if(in_array($wiki['id'], $aResult)) + continue; + + $sql->query('SELECT `id`, `name`, `tags`, `date` FROM `wiki` WHERE `id`="'.$wiki['id'].'" LIMIT 1'); + $quest = $sql->get(); + + $aTags = explode(',', $quest['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + + $tags .= ''.$tag.''; + } + + $html->get('list', 'sections/wiki/question'); + + $html->set('id', $quest['id']); + $html->set('name', sys::find($quest['name'], $text)); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->set('date', sys::today($quest['date'])); + + $html->set('home', $cfg['http']); + + $html->pack('question'); + + array_push($aResult, $wiki['id']); + } + } + + foreach($aNswer_q as $index => $answer_q) + { + // Генерация списка (совпадение по ответу) + while($answer = $sql->get($answer_q)) + { + // Проверка дублирования + if(in_array($answer['wiki'], $aResult)) + continue; + + $sql->query('SELECT `id`, `name`, `tags`, `date` FROM `wiki` WHERE `id`="'.$answer['wiki'].'" LIMIT 1'); + $quest = $sql->get(); + + $aTags = explode(',', $quest['tags']); + + $tags = ''; + + foreach($aTags as $tag) + { + $tag = trim($tag); + + $tags .= ''.$tag.''; + } + + $html->get('list', 'sections/wiki/question'); + + $html->set('id', $quest['id']); + $html->set('name', sys::find($quest['name'], $text)); + $html->set('tags', $tags != '' ? $tags : 'Теги отсутствуют'); + $html->set('date', sys::today($quest['date'])); + + $html->set('home', $cfg['http']); + + $html->pack('question'); + } + } + + $html->arr['question'] = isset($html->arr['question']) ? $html->arr['question'] : 'По вашему запросу ничего не найдено'; + + $mcache->set($mkey, $html->arr['question'], false, 15); + + if(!isset($url['tag'])) + sys::outjs(array('s' => $html->arr['question']), $nmch); + + $html->nav('Категории вопросов', $cfg['http'].'wiki'); + $html->nav('Поиск по тегам'); + + $html->get('search', 'sections/wiki'); + + $html->set('text', $text); + $html->set('result', $html->arr['question']); + + $html->pack('main'); +?> \ No newline at end of file diff --git a/temp/.htaccess b/temp/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/template/acp/all.html b/template/acp/all.html new file mode 100644 index 0000000..ce763b9 --- /dev/null +++ b/template/acp/all.html @@ -0,0 +1,145 @@ + + + + Панель администатора + + + + + + + + + + + + + + + + + +

    + + |section| + + |_section| + +
    + +
    + + + |section||_section| + +
    +
    + [main] +
    +
    +
    + +
    + +
    +
    + + + + + + +
    +
    + + \ No newline at end of file diff --git a/template/acp/cashback.html b/template/acp/cashback.html new file mode 100644 index 0000000..a62d9f8 --- /dev/null +++ b/template/acp/cashback.html @@ -0,0 +1,9 @@ + + #[id] + USER_[user] + [mail] + [purse] + [money] (Выводить: [cashback]) + [type] + Вывести + \ No newline at end of file diff --git a/template/acp/css/bootbox.css b/template/acp/css/bootbox.css new file mode 100644 index 0000000..2e7cbcd --- /dev/null +++ b/template/acp/css/bootbox.css @@ -0,0 +1,123 @@ +.fade +{ + opacity:0; + -webkit-transition:opacity .15s linear; + -moz-transition:opacity .15s linear; + -o-transition:opacity .15s linear; + transition:opacity .15s linear +} +.fade.in{ + opacity:1 +} +.modal-backdrop +{ + position:fixed; + top:0; + right:0; + bottom:0; + left:0; + z-index:1040; + background-color:#000 +} +.modal-backdrop.fade{ + opacity:0 +} +.modal-backdrop,.modal-backdrop.fade.in +{ + opacity: 0.5; + filter: alpha(opacity=50); + background-color: #90D3F4; +} +.modal +{ + position:fixed; + top:40%; + left:45%; + z-index:1050; + width:560px; + margin-left:-280px; + background-color:#fff; + border:1px solid #EEE; + *border:1px solid #EEE; + outline:0; + -webkit-background-clip:padding-box; + -moz-background-clip:padding-box; + background-clip:padding-box +} +.modal.fade +{ + top:-25%; + -webkit-transition:opacity .3s linear,top .3s ease-out; + -moz-transition:opacity .3s linear,top .3s ease-out; + -o-transition:opacity .3s linear,top .3s ease-out; + transition:opacity .3s linear,top .3s ease-out +} +.modal.fade.in +{ + top:40%; + left: 50%; +} +.modal-header +{ + padding:9px 15px; + border-bottom:1px solid #eee +} +.modal-header .close +{ + margin-top:2px +} +.modal-header h3 +{ + margin:0; + line-height:30px +} +.modal-body +{ + position:relative; + max-height:400px; + padding:15px; + overflow-y:auto +} +.modal-form +{ + margin-bottom:0 +} +.modal-footer +{ + padding:14px 15px 15px; + margin-bottom:0; + text-align:right; + background-color:#f5f5f5; + border-top:1px solid #ddd; + -webkit-border-radius:0 0 6px 6px; + -moz-border-radius:0 0 6px 6px; + border-radius:0 0 6px 6px; + *zoom:1; + -webkit-box-shadow:inset 0 1px 0 #fff; + -moz-box-shadow:inset 0 1px 0 #fff; + box-shadow:inset 0 1px 0 #fff +} +.modal-footer:before,.modal-footer:after +{ + display:table; + line-height:0; + content:"" +} +.modal-footer:after +{ + clear:both +} +.modal-footer .btn+.btn +{ + margin-bottom:0; + margin-left:5px +} +.modal-footer .btn-group .btn+.btn +{ + margin-left:-1px +} +.modal-footer .btn-block+.btn-block +{ + margin-left:0 +} + diff --git a/template/acp/css/fonts.css b/template/acp/css/fonts.css new file mode 100644 index 0000000..e3ac4b3 --- /dev/null +++ b/template/acp/css/fonts.css @@ -0,0 +1,2337 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eee; + border-radius: .1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #fff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper-pp:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-pied-piper:before { + content: "\f2ae"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/template/acp/css/jquery.datetimepicker.css b/template/acp/css/jquery.datetimepicker.css new file mode 100644 index 0000000..4ed981a --- /dev/null +++ b/template/acp/css/jquery.datetimepicker.css @@ -0,0 +1,568 @@ +.xdsoft_datetimepicker { + box-shadow: 0 5px 15px -5px rgba(0, 0, 0, 0.506); + background: #fff; + border-bottom: 1px solid #bbb; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-top: 1px solid #ccc; + color: #333; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 8px; + padding-left: 0; + padding-top: 2px; + position: absolute; + z-index: 9999; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: none; +} +.xdsoft_datetimepicker.xdsoft_rtl { + padding: 8px 0 8px 8px; +} + +.xdsoft_datetimepicker iframe { + position: absolute; + left: 0; + top: 0; + width: 75px; + height: 210px; + background: transparent; + border: none; +} + +/*For IE8 or lower*/ +.xdsoft_datetimepicker button { + border: none !important; +} + +.xdsoft_noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.xdsoft_noselect::selection { background: transparent } +.xdsoft_noselect::-moz-selection { background: transparent } + +.xdsoft_datetimepicker.xdsoft_inline { + display: inline-block; + position: static; + box-shadow: none; +} + +.xdsoft_datetimepicker * { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin: 0; +} + +.xdsoft_datetimepicker .xdsoft_datepicker, .xdsoft_datetimepicker .xdsoft_timepicker { + display: none; +} + +.xdsoft_datetimepicker .xdsoft_datepicker.active, .xdsoft_datetimepicker .xdsoft_timepicker.active { + display: block; +} + +.xdsoft_datetimepicker .xdsoft_datepicker { + width: 224px; + float: left; + margin-left: 8px; +} +.xdsoft_datetimepicker.xdsoft_rtl .xdsoft_datepicker { + float: right; + margin-right: 8px; + margin-left: 0; +} + +.xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_datepicker { + width: 256px; +} + +.xdsoft_datetimepicker .xdsoft_timepicker { + width: 58px; + float: left; + text-align: center; + margin-left: 8px; + margin-top: 0; +} +.xdsoft_datetimepicker.xdsoft_rtl .xdsoft_timepicker { + float: right; + margin-right: 8px; + margin-left: 0; +} + +.xdsoft_datetimepicker .xdsoft_datepicker.active+.xdsoft_timepicker { + margin-top: 8px; + margin-bottom: 3px +} + +.xdsoft_datetimepicker .xdsoft_monthpicker { + position: relative; + text-align: center; +} + +.xdsoft_datetimepicker .xdsoft_label i, +.xdsoft_datetimepicker .xdsoft_prev, +.xdsoft_datetimepicker .xdsoft_next, +.xdsoft_datetimepicker .xdsoft_today_button { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0NBRjI1NjM0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0NBRjI1NjQ0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQ0FGMjU2MTQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQ0FGMjU2MjQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoNEP54AAAIOSURBVHja7Jq9TsMwEMcxrZD4WpBYeKUCe+kTMCACHZh4BFfHO/AAIHZGFhYkBBsSEqxsLCAgXKhbXYOTxh9pfJVP+qutnZ5s/5Lz2Y5I03QhWji2GIcgAokWgfCxNvcOCCGKqiSqhUp0laHOne05vdEyGMfkdxJDVjgwDlEQgYQBgx+ULJaWSXXS6r/ER5FBVR8VfGftTKcITNs+a1XpcFoExREIDF14AVIFxgQUS+h520cdud6wNkC0UBw6BCO/HoCYwBhD8QCkQ/x1mwDyD4plh4D6DDV0TAGyo4HcawLIBBSLDkHeH0Mg2yVP3l4TQMZQDDsEOl/MgHQqhMNuE0D+oBh0CIr8MAKyazBH9WyBuKxDWgbXfjNf32TZ1KWm/Ap1oSk/R53UtQ5xTh3LUlMmT8gt6g51Q9p+SobxgJQ/qmsfZhWywGFSl0yBjCLJCMgXail3b7+rumdVJ2YRss4cN+r6qAHDkPWjPjdJCF4n9RmAD/V9A/Wp4NQassDjwlB6XBiCxcJQWmZZb8THFilfy/lfrTvLghq2TqTHrRMTKNJ0sIhdo15RT+RpyWwFdY96UZ/LdQKBGjcXpcc1AlSFEfLmouD+1knuxBDUVrvOBmoOC/rEcN7OQxKVeJTCiAdUzUJhA2Oez9QTkp72OTVcxDcXY8iKNkxGAJXmJCOQwOa6dhyXsOa6XwEGAKdeb5ET3rQdAAAAAElFTkSuQmCC); +} + +.xdsoft_datetimepicker .xdsoft_label i { + opacity: 0.5; + background-position: -92px -19px; + display: inline-block; + width: 9px; + height: 20px; + vertical-align: middle; +} + +.xdsoft_datetimepicker .xdsoft_prev { + float: left; + background-position: -20px 0; +} +.xdsoft_datetimepicker .xdsoft_today_button { + float: left; + background-position: -70px 0; + margin-left: 5px; +} + +.xdsoft_datetimepicker .xdsoft_next { + float: right; + background-position: 0 0; +} + +.xdsoft_datetimepicker .xdsoft_next, +.xdsoft_datetimepicker .xdsoft_prev , +.xdsoft_datetimepicker .xdsoft_today_button { + background-color: transparent; + background-repeat: no-repeat; + border: 0 none; + cursor: pointer; + display: block; + height: 30px; + opacity: 0.5; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + outline: medium none; + overflow: hidden; + padding: 0; + position: relative; + text-indent: 100%; + white-space: nowrap; + width: 20px; + min-width: 0; +} + +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_prev, +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_next { + float: none; + background-position: -40px -15px; + height: 15px; + width: 30px; + display: block; + margin-left: 14px; + margin-top: 7px; +} +.xdsoft_datetimepicker.xdsoft_rtl .xdsoft_timepicker .xdsoft_prev, +.xdsoft_datetimepicker.xdsoft_rtl .xdsoft_timepicker .xdsoft_next { + float: none; + margin-left: 0; + margin-right: 14px; +} + +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_prev { + background-position: -40px 0; + margin-bottom: 7px; + margin-top: 0; +} + +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box { + height: 151px; + overflow: hidden; + border-bottom: 1px solid #ddd; +} + +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div { + background: #f5f5f5; + border-top: 1px solid #ddd; + color: #666; + font-size: 12px; + text-align: center; + border-collapse: collapse; + cursor: pointer; + border-bottom-width: 0; + height: 25px; + line-height: 25px; +} + +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div > div:first-child { + border-top-width: 0; +} + +.xdsoft_datetimepicker .xdsoft_today_button:hover, +.xdsoft_datetimepicker .xdsoft_next:hover, +.xdsoft_datetimepicker .xdsoft_prev:hover { + opacity: 1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; +} + +.xdsoft_datetimepicker .xdsoft_label { + display: inline; + position: relative; + z-index: 9999; + margin: 0; + padding: 5px 3px; + font-size: 14px; + line-height: 20px; + font-weight: bold; + background-color: #fff; + float: left; + width: 182px; + text-align: center; + cursor: pointer; +} + +.xdsoft_datetimepicker .xdsoft_label:hover>span { + text-decoration: underline; +} + +.xdsoft_datetimepicker .xdsoft_label:hover i { + opacity: 1.0; +} + +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select { + border: 1px solid #ccc; + position: absolute; + right: 0; + top: 30px; + z-index: 101; + display: none; + background: #fff; + max-height: 160px; + overflow-y: hidden; +} + +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select.xdsoft_monthselect{ right: -7px } +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select.xdsoft_yearselect{ right: 2px } +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option:hover { + color: #fff; + background: #ff8000; +} + +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option { + padding: 2px 10px 2px 5px; + text-decoration: none !important; +} + +.xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current { + background: #33aaff; + box-shadow: #178fe5 0 1px 3px 0 inset; + color: #fff; + font-weight: 700; +} + +.xdsoft_datetimepicker .xdsoft_month { + width: 100px; + text-align: right; +} + +.xdsoft_datetimepicker .xdsoft_calendar { + clear: both; +} + +.xdsoft_datetimepicker .xdsoft_year{ + width: 48px; + margin-left: 5px; +} + +.xdsoft_datetimepicker .xdsoft_calendar table { + border-collapse: collapse; + width: 100%; + +} + +.xdsoft_datetimepicker .xdsoft_calendar td > div { + padding-right: 5px; +} + +.xdsoft_datetimepicker .xdsoft_calendar th { + height: 25px; +} + +.xdsoft_datetimepicker .xdsoft_calendar td,.xdsoft_datetimepicker .xdsoft_calendar th { + width: 14.2857142%; + background: #f5f5f5; + border: 1px solid #ddd; + color: #666; + font-size: 12px; + text-align: right; + vertical-align: middle; + padding: 0; + border-collapse: collapse; + cursor: pointer; + height: 25px; +} +.xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_calendar td,.xdsoft_datetimepicker.xdsoft_showweeks .xdsoft_calendar th { + width: 12.5%; +} + +.xdsoft_datetimepicker .xdsoft_calendar th { + background: #f1f1f1; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today { + color: #33aaff; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_highlighted_default { + background: #ffe9d2; + box-shadow: #ffb871 0 1px 4px 0 inset; + color: #000; +} +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_highlighted_mint { + background: #c1ffc9; + box-shadow: #00dd1c 0 1px 4px 0 inset; + color: #000; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_default, +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current, +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current { + background: #33aaff; + box-shadow: #178fe5 0 1px 3px 0 inset; + color: #fff; + font-weight: 700; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_other_month, +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled, +.xdsoft_datetimepicker .xdsoft_time_box >div >div.xdsoft_disabled { + opacity: 0.5; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + cursor: default; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_other_month.xdsoft_disabled { + opacity: 0.2; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"; +} + +.xdsoft_datetimepicker .xdsoft_calendar td:hover, +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div:hover { + color: #fff !important; + background: #ff8000 !important; + box-shadow: none !important; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current.xdsoft_disabled:hover, +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box>div>div.xdsoft_current.xdsoft_disabled:hover { + background: #33aaff !important; + box-shadow: #178fe5 0 1px 3px 0 inset !important; + color: #fff !important; +} + +.xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled:hover, +.xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_disabled:hover { + color: inherit !important; + background: inherit !important; + box-shadow: inherit !important; +} + +.xdsoft_datetimepicker .xdsoft_calendar th { + font-weight: 700; + text-align: center; + color: #999; + cursor: default; +} + +.xdsoft_datetimepicker .xdsoft_copyright { + color: #ccc !important; + font-size: 10px; + clear: both; + float: none; + margin-left: 8px; +} + +.xdsoft_datetimepicker .xdsoft_copyright a { color: #eee !important } +.xdsoft_datetimepicker .xdsoft_copyright a:hover { color: #aaa !important } + +.xdsoft_time_box { + position: relative; + border: 1px solid #ccc; +} +.xdsoft_scrollbar >.xdsoft_scroller { + background: #ccc !important; + height: 20px; + border-radius: 3px; +} +.xdsoft_scrollbar { + position: absolute; + width: 7px; + right: 0; + top: 0; + bottom: 0; + cursor: pointer; +} +.xdsoft_datetimepicker.xdsoft_rtl .xdsoft_scrollbar { + left: 0; + right: auto; +} +.xdsoft_scroller_box { + position: relative; +} + +.xdsoft_datetimepicker.xdsoft_dark { + box-shadow: 0 5px 15px -5px rgba(255, 255, 255, 0.506); + background: #000; + border-bottom: 1px solid #444; + border-left: 1px solid #333; + border-right: 1px solid #333; + border-top: 1px solid #333; + color: #ccc; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box { + border-bottom: 1px solid #222; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div { + background: #0a0a0a; + border-top: 1px solid #222; + color: #999; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label { + background-color: #000; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select { + border: 1px solid #333; + background: #000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option:hover { + color: #000; + background: #007fff; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current { + background: #cc5500; + box-shadow: #b03e00 0 1px 3px 0 inset; + color: #000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label i, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_prev, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_next, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_today_button { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUExQUUzOTA0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUExQUUzOTE0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQTFBRTM4RTQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQTFBRTM4RjQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pp0VxGEAAAIASURBVHja7JrNSgMxEMebtgh+3MSLr1T1Xn2CHoSKB08+QmR8Bx9A8e7RixdB9CKCoNdexIugxFlJa7rNZneTbLIpM/CnNLsdMvNjM8l0mRCiQ9Ye61IKCAgZAUnH+mU3MMZaHYChBnJUDzWOFZdVfc5+ZFLbrWDeXPwbxIqrLLfaeS0hEBVGIRQCEiZoHQwtlGSByCCdYBl8g8egTTAWoKQMRBRBcZxYlhzhKegqMOageErsCHVkk3hXIFooDgHB1KkHIHVgzKB4ADJQ/A1jAFmAYhkQqA5TOBtocrKrgXwQA8gcFIuAIO8sQSA7hidvPwaQGZSaAYHOUWJABhWWw2EMIH9QagQERU4SArJXo0ZZL18uvaxejXt/Em8xjVBXmvFr1KVm/AJ10tRe2XnraNqaJvKE3KHuUbfK1E+VHB0q40/y3sdQSxY4FHWeKJCunP8UyDdqJZenT3ntVV5jIYCAh20vT7ioP8tpf6E2lfEMwERe+whV1MHjwZB7PBiCxcGQWwKZKD62lfGNnP/1poFAA60T7rF1UgcKd2id3KDeUS+oLWV8DfWAepOfq00CgQabi9zjcgJVYVD7PVzQUAUGAQkbNJTBICDhgwYTjDYD6XeW08ZKh+A4pYkzenOxXUbvZcWz7E8ykRMnIHGX1XPl+1m2vPYpL+2qdb8CDAARlKFEz/ZVkAAAAABJRU5ErkJggg==); +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th { + background: #0a0a0a; + border: 1px solid #222; + color: #999; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th { + background: #0e0e0e; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_today { + color: #cc5500; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_highlighted_default { + background: #ffe9d2; + box-shadow: #ffb871 0 1px 4px 0 inset; + color:#000; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_highlighted_mint { + background: #c1ffc9; + box-shadow: #00dd1c 0 1px 4px 0 inset; + color:#000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_default, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_current, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current { + background: #cc5500; + box-shadow: #b03e00 0 1px 3px 0 inset; + color: #000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td:hover, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div:hover { + color: #000 !important; + background: #007fff !important; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th { + color: #666; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright { color: #333 !important } +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a { color: #111 !important } +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a:hover { color: #555 !important } + +.xdsoft_dark .xdsoft_time_box { + border: 1px solid #333; +} + +.xdsoft_dark .xdsoft_scrollbar >.xdsoft_scroller { + background: #333 !important; +} +.xdsoft_datetimepicker .xdsoft_save_selected { + display: block; + border: 1px solid #dddddd !important; + margin-top: 5px; + width: 100%; + color: #454551; + font-size: 13px; +} +.xdsoft_datetimepicker .blue-gradient-button { + font-family: "museo-sans", "Book Antiqua", sans-serif; + font-size: 12px; + font-weight: 300; + color: #82878c; + height: 28px; + position: relative; + padding: 4px 17px 4px 33px; + border: 1px solid #d7d8da; + background: -moz-linear-gradient(top, #fff 0%, #f4f8fa 73%); + /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(73%, #f4f8fa)); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #fff 0%, #f4f8fa 73%); + /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #fff 0%, #f4f8fa 73%); + /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #fff 0%, #f4f8fa 73%); + /* IE10+ */ + background: linear-gradient(to bottom, #fff 0%, #f4f8fa 73%); + /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff', endColorstr='#f4f8fa',GradientType=0 ); +/* IE6-9 */ +} +.xdsoft_datetimepicker .blue-gradient-button:hover, .xdsoft_datetimepicker .blue-gradient-button:focus, .xdsoft_datetimepicker .blue-gradient-button:hover span, .xdsoft_datetimepicker .blue-gradient-button:focus span { + color: #454551; + background: -moz-linear-gradient(top, #f4f8fa 0%, #FFF 73%); + /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f4f8fa), color-stop(73%, #FFF)); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #f4f8fa 0%, #FFF 73%); + /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #f4f8fa 0%, #FFF 73%); + /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #f4f8fa 0%, #FFF 73%); + /* IE10+ */ + background: linear-gradient(to bottom, #f4f8fa 0%, #FFF 73%); + /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f8fa', endColorstr='#FFF',GradientType=0 ); + /* IE6-9 */ +} diff --git a/template/acp/css/style.css b/template/acp/css/style.css new file mode 100644 index 0000000..9319cc2 --- /dev/null +++ b/template/acp/css/style.css @@ -0,0 +1,644 @@ +@font-face { + font-family: 'Cuprum'; + src: local('Cuprum'), local('Cuprum-Regular'), url('../fonts/cuprum.woff2') format('woff2'), url('../fonts/cuprum.woff') format('woff'), url('../fonts/cuprum.ttf') format('truetype'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: 'Cuprum'; + src: local('Cuprum Italic'), local('Cuprum-Italic'), url('../fonts/cuprumitalic.woff2') format('woff2'), url('../fonts/cuprumitalic.woff') format('woff'), url('../fonts/cuprumitalic.ttf') format('truetype'); + font-weight: 400; + font-style: italic; +} +@font-face { + font-family: 'Cuprum'; + src: local('Cuprum Bold'), local('Cuprum-Bold'), url('../fonts/cuprumbold.woff2') format('woff2'), url('../fonts/cuprumbold.woff') format('woff'), url('../fonts/cuprumbold.ttf') format('truetype'); + font-weight: 700; + font-style: normal; +} +@font-face { + font-family: 'Cuprum'; + src: local('Cuprum Bold Italic'), local('Cuprum-BoldItalic'), url('../fonts/cuprumbolditalic.woff2') format('woff2'), url('../fonts/cuprumbolditalic.woff') format('woff'), url('../fonts/cuprumbolditalic.ttf') format('truetype'); + font-weight: 700; + font-style: italic; +} +* +{ + padding: 0; + margin: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; +} +html +{ + background-color: #252b30; +} +body, header, main, footer +{ + width: 1200px; +} +main +{ + display: flex +} +html, body, main, .content, .sidebar, .sidebar-second, .height-max +{ + height: 100%; + font: 13px Cuprum; +} +body +{ + margin: 0 auto +} +main, header +{ + margin: 0 auto; +} +main +{ + display: table-cell; + background-color: #eef0f2; +} +header +{ + height: 43px; +} +a +{ + text-decoration: underline; + color: #222; +} +a:hover +{ + text-decoration: none; +} +input::-webkit-input-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 0px; transition: text-indent 0.3s ease;} +input::-moz-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 0px; transition: text-indent 0.3s ease;} +input:-moz-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 0px; transition: text-indent 0.3s ease;} +input:-ms-input-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 0px; transition: text-indent 0.3s ease;} +input:focus::-webkit-input-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 1000px; transition: text-indent 0.3s ease;} +input:focus::-moz-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 1000px; transition: text-indent 0.3s ease;} +input:focus:-moz-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 1000px; transition: text-indent 0.3s ease;} +input:focus:-ms-input-placeholder {color: #d1d1d1; text-overflow: ellipsis; text-indent: 1000px; transition: text-indent 0.3s ease;} +textarea::-webkit-input-placeholder {color: #d1d1d1;} +textarea::-moz-placeholder {color: #d1d1d1;} +textarea:-moz-placeholder {color: #d1d1d1;} +textarea:-ms-input-placeholder {color: #d1d1d1;} + +.sidebar, .sidebar-second, .content +{ + padding: 5px; + float: left; +} +.sidebar, .sidebar-second +{ + width: 200px; +} +.content +{ + width: 1000px; +} +.content-mini +{ + width: 800px; +} +.main +{ + margin: 5px; +} +.bg-gray +{ + background-color: #2e3439; + color: #8e9ca8; +} +.bg-gray-mild +{ + background-color: #3f464c; +} +.bg-white +{ + background-color: #ffffff; +} +.bg-green +{ + background-color: #00c09e; +} +.br-gray-top +{ + border-top: 1px solid #282e33; +} +.br-gray-bot +{ + border-bottom: 1px solid #282e33; +} +.hr-gray, .hr-white +{ + margin: 15px 0; + width: 100%; + height: 1px; +} +.hr-gray +{ + background-color: #282e33; +} +.hr-white +{ + background-color: #f3f4f7; +} +.sidebar > h3 +{ + font-size: 15px; + text-align: center; + line-height: 33px; +} +.sidebar > h5, .sidebar-second > h5 +{ + padding: 5px 10px; + font-size: 11px; +} +.sidebar > ul li, .sidebar-second > ul li +{ + list-style: none; +} +.sidebar > ul li a +{ + color: #8e9ca8; + font-size: 13px; + text-decoration: none; + padding: 7px; + display: block; +} +.sidebar > ul li a:hover +{ + background-color: #293035; + color: #c1d6e3; +} +.sidebar > ul li a:active, .sidebar .active +{ + background-color: #252b30; + color: #c1d6e3; +} +.sidebar > ul li a i +{ + font-size: 14px; + width: 22px; +} +.sidebar-second > h3 +{ + color: #008067; + text-align: right; + padding: 0 10px; + font-size: 12px; + line-height: 33px; +} +.sidebar-second > h3 i +{ + font-size: 14px; + float: left; + margin-top: 8px; +} +.sidebar-second > ul li a +{ + color: #b3babf; + font-size: 13px; + text-decoration: none; + padding: 7px; + display: block; +} +.sidebar-second > ul li a:hover +{ + background-color: #fafbfc; + color: #78858f; +} +.sidebar-second > ul li a:active, .sidebar-second .active +{ + background-color: #f3f4f7; + color: #78858f; +} +.sidebar-second > ul li a i +{ + font-size: 14px; + width: 22px; +} +.sidebar-second > ul li a span +{ + float: right; + font-size: 10px; + background-color: #EEE; + padding: 2px 5px; + border-radius: 50%; +} +.sidebar-second > h5 +{ + font-size: 14px; + color: #7e8890; +} +header > .content a +{ + color: #7b8893; + background-color: #2e3439; + padding: 5px 7px; + font-size: 14px; + text-decoration: none; + border-radius: 2px; + margin-left: 5px; +} +header > .content a:hover +{ + color: #abb7bf; + background-color: #2b3135; +} +header .fl-right +{ + float: right; + margin-top: 9px; +} +header .fl-left +{ + float: left; + margin-top: 9px; +} + +.inputs input, .inputs select, .inputs textarea +{ + padding: 5px; + font-size: 12px; + color: #000; + border: 1px solid #E8EBF0; + box-sizing: border-box; + outline: 0; +} +.inputs textarea +{ + resize: vertical; + width: 100%; +} + +.inputs-max input[type="text"], .inputs-max select +{ + width: 100%; +} + +label +{ + cursor: pointer; + display: inline-block; + padding: 5px 10px; + border-radius: 10px; + border: 1px solid #EEE; + background-color: #FAFAFA; + margin-right: 5px; +} + +label input +{ + cursor: pointer; + float: left; + margin: 1px 5px; +} + +table +{ + width: 100%; + background-color: #ffffff; + box-shadow: 1px 1px 10px #e0e0e0; + border-collapse: collapse; +} + +table th +{ + background-color: #3f464c; + color: #abb7bf; + text-align: left; +} +table th span +{ + cursor: pointer; +} +table td +{ + color: #000; +} +table th, table td +{ + padding: 8px; +} + +table tr:nth-child(even) td +{ + background-color: #f7f8f8; +} + +table a +{ + color: #222; +} + +.trh tr:hover td +{ + background-color: #f9fae5; +} + +.search +{ + width: 300px; + float: right; + margin-bottom: 10px; +} +.search input +{ + padding: 5px; + width: 300px; + font-size: 12px; + color: #000; + background-color: #fff; + border: 1px solid #dedede; + outline: 0; + border-radius: 10px; +} +.search button +{ + text-align: center; + border-radius: 10px; + border: 1px solid #ececec; + background-color: #ffffff; + color: #000000; + font-size: 13px; + outline: 0; + cursor: pointer; + position: absolute; + width: 24px; + height: 24px; + margin: -25px 0 0 274px; + overflow: hidden; + line-height: 24px; + text-overflow: ellipsis; + transition: all 0.23s ease-in-out; + -moz-transition: all 0.23s ease-in-out; + -webkit-transition: all 0.23s ease-in-out; + -o-transition: all 0.23s ease-in-out; +} +.search button:hover +{ + width: 70px; + margin-left: 229px; +} + + + +.w5p +{ + width: 5% !important; +} +.w10p +{ + width: 10% !important; +} +.w15p +{ + width: 15% !important; +} +.w20p +{ + width: 20% !important; +} +.w25p +{ + width: 25% !important; +} +.w35p +{ + width: 35% !important; +} +.w50p +{ + width: 50% !important; +} + +.left +{ + float: left; +} +.right +{ + float: right; +} +.text-left +{ + text-align: left; +} +.text-center +{ + text-align: center; +} +.text-right +{ + text-align: right; +} + +.text-red +{ + color: #bd2727; +} +.text-green +{ + color: #27bd32; +} + +.vtop +{ + vertical-align: top; +} + +.space +{ + clear: both; + margin-top: 15px; +} + +.informer +{ + margin-bottom: 10px; + border-left: 5px solid #29a3f2; + padding: 5px; + font-size: 14px; + background-color: #ffffff; + color: #000; + text-transform: uppercase; +} + +.informer.green +{ + border-color: #28b727; +} + +.informer.red +{ + border-color: #f22929; +} + +.pages +{ + display: inline-block; + width: 100%; + text-align: right; +} +.pages > div +{ + margin-top: 10px; +} +.pages > i +{ + margin: 0 2px; +} +.pages a +{ + display: inline-block; + background-color: #3f464c; + color: #8e9ca8; + font-size: 13px; + font-family: nav; + padding: 3px 8px; + position: relative; + text-decoration: none; + text-transform: capitalize; +} +.pages a:hover, .pages a.active +{ + background-color: #252b30; + color: #c1d6e3; +} + +#search_error +{ + display: none; + width: 100%; + background-color: #dadde0; + padding: 10px; + color: #777; +} + +#loadinginfo +{ + display: none; +/* background-color: #fff; */ + height: 15px; + width: 100%; + left: 90%; + top: 0px; + position: fixed; +} + +.loader +{ + z-index: 99; + position: fixed; + top: 10px; + width: 100%; +} +.loader > span +{ + display: inline-block; + background-color: #dbdbdb; + width: 5px; + height: 5px; + border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + margin: 0px; + position: fixed; + top: 5px; + left: 90%; + transition: 2.8s all cubic-bezier(0.030, 0.615, 0.995, 0.415); + -o-transition: 2.8s all cubic-bezier(0.030, 0.615, 0.995, 0.415); + -ms-transition: 2.8s all cubic-bezier(0.030, 0.615, 0.995, 0.415); + -moz-transition: 2.8s all cubic-bezier(0.030, 0.615, 0.995, 0.415); + -webkit-transition: 2.8s all cubic-bezier(0.030, 0.615, 0.995, 0.415); + z-index: 101; +} +.loader > span.jmp +{ + transition: none !important; + -o-transition: none !important; + -ms-transition: none !important; + -moz-transition: none !important; + -webkit-transition: none !important; +} +.loader span.l-1 { background-color: #e74c3c;} +.loader span.l-2 { background-color: #e67e22;} +.loader span.l-3 { background-color: #f1c40f;} +.loader span.l-4 { background-color: #2ecc71;} +.loader span.l-5 { background-color: #3498db;} +.loader span.l-6 { background-color: #9b59b6;} + +.p_info p +{ + padding: 5px; + border-bottom: 1px dotted #EEE; +} + +.pointer +{ + cursor: pointer; +} +.none +{ + display: none; +} +.btn +{ + font-size: 12px; + padding: 5px; + background-color: #2e3439; + border: 1px solid #3f464c; + color: #7b8893; + cursor: pointer; + outline: 0; +} + +.btn:hover +{ + color: #abb7bf; + background-color: #2b3135; +} + +.btn-green +{ + background-color: #41d192; + border: 1px solid #55ac5e; + color: #ffffff; +} +.btn-green:hover +{ + background-color: #37da92; + border: 1px solid #55ac5e; + color: #ffffff; +} + +.btn-red +{ + background-color: #d14141; + border: 1px solid #ac5555; + color: #ffffff; +} +.btn-red:hover +{ + background-color: #da1010; + border: 1px solid #ac5555; + color: #ffffff; +} + +.double-color td +{ + background-color: #ffffff !important; +} + +.double-color tr:nth-child(2n) td +{ + border-bottom: 2px solid #3f464c; +} \ No newline at end of file diff --git a/template/acp/favicon.ico b/template/acp/favicon.ico new file mode 100644 index 0000000..500901c Binary files /dev/null and b/template/acp/favicon.ico differ diff --git a/template/acp/fonts/FontAwesome.otf b/template/acp/fonts/FontAwesome.otf new file mode 100644 index 0000000..401ec0f Binary files /dev/null and b/template/acp/fonts/FontAwesome.otf differ diff --git a/template/acp/fonts/cuprum.ttf b/template/acp/fonts/cuprum.ttf new file mode 100644 index 0000000..36580b6 Binary files /dev/null and b/template/acp/fonts/cuprum.ttf differ diff --git a/template/acp/fonts/cuprum.woff b/template/acp/fonts/cuprum.woff new file mode 100644 index 0000000..3c47d52 Binary files /dev/null and b/template/acp/fonts/cuprum.woff differ diff --git a/template/acp/fonts/cuprum.woff2 b/template/acp/fonts/cuprum.woff2 new file mode 100644 index 0000000..b9dd7fe Binary files /dev/null and b/template/acp/fonts/cuprum.woff2 differ diff --git a/template/acp/fonts/cuprumbold.ttf b/template/acp/fonts/cuprumbold.ttf new file mode 100644 index 0000000..68dbf3c Binary files /dev/null and b/template/acp/fonts/cuprumbold.ttf differ diff --git a/template/acp/fonts/cuprumbold.woff b/template/acp/fonts/cuprumbold.woff new file mode 100644 index 0000000..8f69fab Binary files /dev/null and b/template/acp/fonts/cuprumbold.woff differ diff --git a/template/acp/fonts/cuprumbold.woff2 b/template/acp/fonts/cuprumbold.woff2 new file mode 100644 index 0000000..21f5c56 Binary files /dev/null and b/template/acp/fonts/cuprumbold.woff2 differ diff --git a/template/acp/fonts/cuprumbolditalic.ttf b/template/acp/fonts/cuprumbolditalic.ttf new file mode 100644 index 0000000..f8027a2 Binary files /dev/null and b/template/acp/fonts/cuprumbolditalic.ttf differ diff --git a/template/acp/fonts/cuprumbolditalic.woff b/template/acp/fonts/cuprumbolditalic.woff new file mode 100644 index 0000000..09a4bb0 Binary files /dev/null and b/template/acp/fonts/cuprumbolditalic.woff differ diff --git a/template/acp/fonts/cuprumbolditalic.woff2 b/template/acp/fonts/cuprumbolditalic.woff2 new file mode 100644 index 0000000..8c8a25d Binary files /dev/null and b/template/acp/fonts/cuprumbolditalic.woff2 differ diff --git a/template/acp/fonts/cuprumitalic.ttf b/template/acp/fonts/cuprumitalic.ttf new file mode 100644 index 0000000..e72f033 Binary files /dev/null and b/template/acp/fonts/cuprumitalic.ttf differ diff --git a/template/acp/fonts/cuprumitalic.woff b/template/acp/fonts/cuprumitalic.woff new file mode 100644 index 0000000..f3c0677 Binary files /dev/null and b/template/acp/fonts/cuprumitalic.woff differ diff --git a/template/acp/fonts/cuprumitalic.woff2 b/template/acp/fonts/cuprumitalic.woff2 new file mode 100644 index 0000000..56a1a8c Binary files /dev/null and b/template/acp/fonts/cuprumitalic.woff2 differ diff --git a/template/acp/fonts/fontawesome-webfont.eot b/template/acp/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/template/acp/fonts/fontawesome-webfont.eot differ diff --git a/template/acp/fonts/fontawesome-webfont.svg b/template/acp/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/template/acp/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/acp/fonts/fontawesome-webfont.ttf b/template/acp/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/template/acp/fonts/fontawesome-webfont.ttf differ diff --git a/template/acp/fonts/fontawesome-webfont.woff b/template/acp/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/template/acp/fonts/fontawesome-webfont.woff differ diff --git a/template/acp/fonts/fontawesome-webfont.woff2 b/template/acp/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/template/acp/fonts/fontawesome-webfont.woff2 differ diff --git a/template/acp/images/.htaccess b/template/acp/images/.htaccess new file mode 100644 index 0000000..e69de29 diff --git a/template/acp/js/addons.js b/template/acp/js/addons.js new file mode 100644 index 0000000..4a0921a --- /dev/null +++ b/template/acp/js/addons.js @@ -0,0 +1,329 @@ +$('#addons').ajaxForm({ + dataType: 'json', + success: function(data) + { + $.each(data, function(i, val) + { + if(i == 'e') + bootbox.dialog('

    Ошибка

    '+val, + [{ + "label" : "Продолжить" + }] + ); + + if(i == 's') + location.reload(); + }); + + loading(0) + } +}); + +function maps_reset_game() +{ + $('#game').prop('selectedIndex', 0); +} + +function maps_list() +{ + $.get(home+'addons/section/updmp/get/list/unit/'+$('#unit').val()+'/game/'+$('#game').val(), + function(data) + { + $('#maps').val(data); + }); + + return false; +} + +function maps_update() +{ + loading(1); + + $.get(home+'addons/section/updmp/unit/'+$('#unit').val()+'/game/'+$('#game').val()+'/go', + function(data) + { + location.reload(); + }); + + return false; +} + +function plugins_category() +{ + $.get(home+'addons/section/addpl/get/cat/game/'+$('#game').val(), + function(data) + { + $('#category').html(''+data); + }); + + return false; +} + +function plugins_update_del(id) +{ + bootbox.dialog('

    Внимание

    Вы уверены, что хотите удалить обновление плагина?', + [{ + "label" : "Удалить", + callback : function(){plugins_update_del_go(id)} + },{ + "label" : "Отмена", + }] + ); + + return false; +} + +function plugins_update_del_go(id) +{ + $.get(home+'addons/section/delete/type/update/id/'+id, + function(data) + { + location.reload(); + }); +} + +function cats_delete(id) +{ + $.get(home+'addons/section/delete/type/cat/id/'+id, + function(data) + { + location.reload(); + }); + + return false; +} + +function plugins_sort(sort) +{ + switch(sort) + { + case 'id': + if(sort_id == 'asc') + sort_id = 'desc'; + else + sort_id = 'asc'; + + sorting = sort_id; + + break; + + case 'cat': + sort_cat = sort_cat == 'asc' ? 'desc' : 'asc'; + sorting = sort_cat; + + break; + + case 'game': + sort_game = sort_game == 'asc' ? 'desc' : 'asc'; + sorting = sort_game; + + } + + location.href=home+'addons/sort/'+sort+'/sorting/'+sorting; +} + +function plugins_search(go) +{ + if($('#search').val() == '') + { + $('#search_error').css('display', 'none'); + + return; + } + + loading(1); + + if(go) go = '/go'; else go = ''; + + $.ajax({ + type: 'POST', + url: home+'addons/subsection/search'+go, + data: 'text='+$('#search').val(), + dataType: 'json', + success: function(data) + { + $.each(data, function(i, val) + { + if(i == 'e') + { + if(val != '') + { + $('#search_error').css('display', 'inline-block'); + $('#search_error').html(val); + }else + $('#search_error').css('display', 'none'); + } + + if(i == 's') + { + $('#search_error').css('display', 'none'); + $('#search_result').html(val); + } + }); + + loading(0); + } + }); +} + +function plugins_delete(id) +{ + bootbox.dialog('

    Внимание

    Вы уверены, что хотите удалить плагин?', + [{ + "label" : "Удалить", + callback : function(){plugins_delete_go(id)} + },{ + "label" : "Отмена", + }] + ); + + return false; +} + +function plugins_delete_go(id) +{ + loading(1); + + $.ajax({ + type: 'POST', + url: home+'addons/section/delete/type/plugin/id/'+id, + dataType: 'json', + success: function(data) + { + $.each(data, function(i, val) + { + if(i == 'e') + bootbox.dialog('

    Ошибка

    '+val, + [{ + "label" : "Продолжить" + }] + ); + + if(i == 's') + location.reload() + }); + + loading(0); + } + }); +} + +function add_plugin_type() +{ + if($("#update").val() == 0) + { + $('#new_plugin').css('display', 'table-row'); + $('#upd_plugin').css('display', 'none'); + }else{ + $('#new_plugin').css('display', 'none'); + $('#upd_plugin').css('display', 'table-row'); + } +} + +function config_files_form() +{ + if(!$("#cfa").prop('checked')) + $('#config_files_form').css('display', 'table'); + else{ + $('#config_files_form').css('display', 'none'); + $('#config_files_all').html(''); + } +} + +var cf = 999999; +var cc = 999999; +var cw = 999999; +var cwe = 999999; +var fd = 999999; + +function config_files_add() +{ + cf += 1; + + $('#config_files_all').append('' + +'' + +'' + +'Удалить' + +''); +} + +function config_clear_add() +{ + cc += 1; + + $('#config_clear_all').append('' + +'' + +'' + +'' + +'Удалить' + +''); +} + +function config_write_add() +{ + cw += 1; + + $('#config_write_all').append('' + +'' + +'' + +'' + +'Удалить' + +''); +} + +function config_write_del_add() +{ + cwe += 1; + + $('#config_write_del_all').append('' + +'' + +'' + +'' + +'Удалить' + +''); +} + +function files_delete_add() +{ + fd += 1; + + $('#files_delete_all').append('' + +'' + +'Удалить' + +''); +} + +function config_files_del(id) +{ + $('#cf_'+id).empty(); + + return false; +} + +function config_clear_del(id) +{ + $('#cc_'+id).empty(); + + return false; +} + +function config_write_del(id) +{ + $('#cw_'+id).empty(); + + return false; +} + +function config_write_del_del(id) +{ + $('#cwe_'+id).empty(); + + return false; +} + +function files_delete_del(id) +{ + $('#fd_'+id).empty(); + + return false; +} \ No newline at end of file diff --git a/template/acp/js/bootbox.js b/template/acp/js/bootbox.js new file mode 100644 index 0000000..e78f8d7 --- /dev/null +++ b/template/acp/js/bootbox.js @@ -0,0 +1,6 @@ +/** + * bootbox.js v3.3.0 + * + * http://bootboxjs.com/license.txt + */ +var bootbox=window.bootbox||function(a,b){function c(a,b){return"undefined"==typeof b&&(b=d),"string"==typeof m[b][a]?m[b][a]:b!=e?c(a,e):a}var d="en",e="en",f=!0,g="static",h="javascript:;",i="",j={},k={},l={};l.setLocale=function(a){for(var b in m)if(b==a)return d=a,void 0;throw new Error("Invalid locale: "+a)},l.addLocale=function(a,b){"undefined"==typeof m[a]&&(m[a]={});for(var c in b)m[a][c]=b[c]},l.setIcons=function(a){k=a,("object"!=typeof k||null===k)&&(k={})},l.setBtnClasses=function(a){j=a,("object"!=typeof j||null===j)&&(j={})},l.alert=function(){var a="",b=c("OK"),d=null;switch(arguments.length){case 1:a=arguments[0];break;case 2:a=arguments[0],"function"==typeof arguments[1]?d=arguments[1]:b=arguments[1];break;case 3:a=arguments[0],b=arguments[1],d=arguments[2];break;default:throw new Error("Incorrect number of arguments: expected 1-3")}return l.dialog(a,{label:b,icon:k.OK,"class":j.OK,callback:d},{onEscape:d||!0})},l.confirm=function(){var a="",b=c("CANCEL"),d=c("CONFIRM"),e=null;switch(arguments.length){case 1:a=arguments[0];break;case 2:a=arguments[0],"function"==typeof arguments[1]?e=arguments[1]:b=arguments[1];break;case 3:a=arguments[0],b=arguments[1],"function"==typeof arguments[2]?e=arguments[2]:d=arguments[2];break;case 4:a=arguments[0],b=arguments[1],d=arguments[2],e=arguments[3];break;default:throw new Error("Incorrect number of arguments: expected 1-4")}var f=function(){return"function"==typeof e?e(!1):void 0},g=function(){return"function"==typeof e?e(!0):void 0};return l.dialog(a,[{label:b,icon:k.CANCEL,"class":j.CANCEL,callback:f},{label:d,icon:k.CONFIRM,"class":j.CONFIRM,callback:g}],{onEscape:f})},l.prompt=function(){var a="",d=c("CANCEL"),e=c("CONFIRM"),f=null,g="";switch(arguments.length){case 1:a=arguments[0];break;case 2:a=arguments[0],"function"==typeof arguments[1]?f=arguments[1]:d=arguments[1];break;case 3:a=arguments[0],d=arguments[1],"function"==typeof arguments[2]?f=arguments[2]:e=arguments[2];break;case 4:a=arguments[0],d=arguments[1],e=arguments[2],f=arguments[3];break;case 5:a=arguments[0],d=arguments[1],e=arguments[2],f=arguments[3],g=arguments[4];break;default:throw new Error("Incorrect number of arguments: expected 1-5")}var h=a,i=b("
    ");i.append("");var m=function(){return"function"==typeof f?f(null):void 0},n=function(){return"function"==typeof f?f(i.find("input[type=text]").val()):void 0},o=l.dialog(i,[{label:d,icon:k.CANCEL,"class":j.CANCEL,callback:m},{label:e,icon:k.CONFIRM,"class":j.CONFIRM,callback:n}],{header:h,show:!1,onEscape:m});return o.on("shown",function(){i.find("input[type=text]").focus(),i.on("submit",function(a){a.preventDefault(),o.find(".btn-primary").click()})}),o.modal("show"),o},l.dialog=function(c,d,e){function j(){var a=null;"function"==typeof e.onEscape&&(a=e.onEscape()),a!==!1&&x.modal("hide")}var k="",l=[];e||(e={}),"undefined"==typeof d?d=[]:"undefined"==typeof d.length&&(d=[d]);for(var m=d.length;m--;){var n=null,o=null,p=null,q="",r=null;if("undefined"==typeof d[m].label&&"undefined"==typeof d[m]["class"]&&"undefined"==typeof d[m].callback){var s=0,t=null;for(var u in d[m])if(t=u,++s>1)break;1==s&&"function"==typeof d[m][u]&&(d[m].label=t,d[m].callback=d[m][u])}"function"==typeof d[m].callback&&(r=d[m].callback),d[m]["class"]?p=d[m]["class"]:m==d.length-1&&d.length<=2&&(p="btn-primary"),d[m].link!==!0&&(p="btn "+p),n=d[m].label?d[m].label:"Option "+(m+1),d[m].icon&&(q=" "),o=d[m].href?d[m].href:h,k=""+q+n+""+k,l[m]=r}var v=["");var x=b(v.join("\n")),y="undefined"==typeof e.animate?f:e.animate;y&&x.addClass("fade");var z="undefined"==typeof e.classes?i:e.classes;return z&&x.addClass(z),x.find(".modal-body").html(c),x.on("keyup.dismiss.modal",function(a){27===a.which&&e.onEscape&&j("escape")}),x.on("click","a.close",function(a){a.preventDefault(),j("close")}),x.on("shown",function(){x.find("a.btn-primary:first").focus()}),x.on("hidden",function(a){a.target===this&&x.remove()}),x.on("click",".modal-footer a",function(a){var c=b(this).data("handler"),e=l[c],f=null;("undefined"==typeof c||"undefined"==typeof d[c].href)&&(a.preventDefault(),"function"==typeof e&&(f=e(a)),f!==!1&&x.modal("hide"))}),b("body").append(x),x.modal({backdrop:"undefined"==typeof e.backdrop?g:e.backdrop,keyboard:!1,show:!1}),x.on("show",function(){b(a).off("focusin.modal")}),("undefined"==typeof e.show||e.show===!0)&&x.modal("show"),x},l.modal=function(){var a,c,d,e={onEscape:null,keyboard:!0,backdrop:g};switch(arguments.length){case 1:a=arguments[0];break;case 2:a=arguments[0],"object"==typeof arguments[1]?d=arguments[1]:c=arguments[1];break;case 3:a=arguments[0],c=arguments[1],d=arguments[2];break;default:throw new Error("Incorrect number of arguments: expected 1-3")}return e.header=c,d="object"==typeof d?b.extend(e,d):e,l.dialog(a,[],d)},l.hideAll=function(){b(".bootbox").modal("hide")},l.animate=function(a){f=a},l.backdrop=function(a){g=a},l.classes=function(a){i=a};var m={br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return l}(document,window.jQuery);window.bootbox=bootbox; \ No newline at end of file diff --git a/template/acp/js/bootstrap.js b/template/acp/js/bootstrap.js new file mode 100644 index 0000000..f9cbdae --- /dev/null +++ b/template/acp/js/bootstrap.js @@ -0,0 +1,6 @@ +/*! +* Bootstrap.js by @fat & @mdo +* Copyright 2012 Twitter, Inc. +* http://www.apache.org/licenses/LICENSE-2.0.txt +*/ +!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(".dropdown-backdrop").remove(),e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||("ontouchstart"in document.documentElement&&e('