Merge branch 'develop' into develop

This commit is contained in:
Tim 2020-08-12 21:25:59 +02:00 committed by GitHub
commit 2f3a870451
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1595 additions and 619 deletions

View File

@ -6,6 +6,18 @@ Not yet released
---------------- ----------------
\- \-
v3.5.2 (released August 12, 2020)
-----------------------------
* Fixed missing version numbers.
* See https://github.com/phpservermon/phpservermon/compare/v3.5.1...v3.5.2
v3.5.1 (released August 12, 2020)
-----------------------------
* Security update regaring jQuery, see #972.
* See https://github.com/phpservermon/phpservermon/compare/v3.5.0...v3.5.1
v3.5.0 (released May 1, 2020) v3.5.0 (released May 1, 2020)
----------------------------- -----------------------------

View File

@ -5,7 +5,7 @@ PHP Server Monitor
:alt: Join the chat at https://gitter.im/erickrf/nlpnet :alt: Join the chat at https://gitter.im/erickrf/nlpnet
:target: https://gitter.im/phpservermon/phpservermon :target: https://gitter.im/phpservermon/phpservermon
Version 3.5.0 Version 3.5.2
PHP Server Monitor is a script that checks whether your websites and servers are up and running. PHP Server Monitor is a script that checks whether your websites and servers are up and running.
It comes with a web based user interface where you can manage your services and websites, It comes with a web based user interface where you can manage your services and websites,
@ -60,6 +60,8 @@ The following SMS gateways are currently available:
* SolutionsInfini - <https://solutionsinfini.com/> * SolutionsInfini - <https://solutionsinfini.com/>
* Plivo - <https://www.plivo.com/> * Plivo - <https://www.plivo.com/>
* Callr - <https://www.callr.com/> * Callr - <https://www.callr.com/>
* SMSAPI - <https://www.smsapi.com/en>
* OVH SMS PRO - <https://www.ovhtelecom.fr/sms/>
@ -77,12 +79,21 @@ Requirements
* Web server * Web server
* MySQL database * MySQL database
* For PHP5: 5.6.0+ * For PHP5: 5.5.9+
* For PHP7: 7.0.8+ * For PHP7: 7.0.8+
* PHP cURL package * PHP Extensions (modules)
* PHP PDO mysql driver
* PHP-XML
* ext-curl
* ext-ctype
* ext-filter
* ext-hash
* ext-json
* ext-libxml
* ext-openssl
* ext-pdo
* ext-pcre
* ext-sockets
* ext-xml
Install Install
------- -------

View File

@ -6,6 +6,7 @@
"require": { "require": {
"php": "^5.5.9|>=7.0.8", "php": "^5.5.9|>=7.0.8",
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-xml": "*", "ext-xml": "*",
"phpmailer/phpmailer": ">=6.0.6 ~6.0", "phpmailer/phpmailer": ">=6.0.6 ~6.0",

10
composer.lock generated
View File

@ -160,16 +160,16 @@
}, },
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
"version": "v6.1.3", "version": "v6.1.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git", "url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a25ae38e03de4ee4031725498a600012364787c7" "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a25ae38e03de4ee4031725498a600012364787c7", "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3",
"reference": "a25ae38e03de4ee4031725498a600012364787c7", "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -218,7 +218,7 @@
} }
], ],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP", "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"time": "2019-11-21T09:37:46+00:00" "time": "2020-05-27T12:24:03+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",

View File

@ -51,9 +51,9 @@ copyright = u'2008-2017, Pepijn Over'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '3.5.0' version = '3.5'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '3.5.0' release = '3.5.2'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -85,6 +85,10 @@ The following people have contributed to the development of PHP Server Monitor:
* Nexmo SMS gateway * Nexmo SMS gateway
* Mateusz Małek - https://github.com/mateuszmalek
* SMSAPI gateway
Translators Translators
+++++++++++ +++++++++++
@ -192,3 +196,4 @@ The following libraries are being used by PHP Server Monitor:
* PHP-Pushover - https://github.com/kryap/php-pushover * PHP-Pushover - https://github.com/kryap/php-pushover
* Symfony - https://symfony.com * Symfony - https://symfony.com
* Random_compat - https://github.com/paragonie/random_compat * Random_compat - https://github.com/paragonie/random_compat
* Hammer.js - https://github.com/hammerjs/hammer.js

View File

@ -51,7 +51,7 @@ The other way is to parse the access logs created by your webserver software, wh
When using tools such as Google Analytics, the monitor requests will not show up in your statistics, because the monitor does not execute any Javascript. When using tools such as Google Analytics, the monitor requests will not show up in your statistics, because the monitor does not execute any Javascript.
Tools that parse your raw access logs like Awstats, will include the requests made by the monitor. Tools that parse your raw access logs like Awstats, will include the requests made by the monitor.
To make sure these requests can be identified, the monitor uses a custom user agent, which you can usually filter out. The user agent of the monitor looks like:: To make sure these requests can be identified, the monitor uses a custom user agent, which you can usually filter out. The user agent can be modified in the config section, but bij default looks like::
Mozilla/5.0 (compatible; phpservermon/3.0.1; +http://www.phpservermonitor.org) Mozilla/5.0 (compatible; phpservermon/3.0.1; +http://www.phpservermonitor.org)

View File

@ -5,7 +5,7 @@ Requirements
* Web server * Web server
* MySQL database * MySQL database
* For PHP5: 5.6.0+ * For PHP5: 5.5.9+
* For PHP7: 7.0.8+ * For PHP7: 7.0.8+
* PHP cURL package * PHP cURL package
* PHP PDO mysql driver * PHP PDO mysql driver

View File

@ -34,21 +34,21 @@ namespace {
# #
############################################### ###############################################
/** /**
* Retrieve language settings from the selected language file * Retrieve language settings from the selected language file
* Return false if arg is not found * Return false if arg is not found
* *
* @return string|bool * @return string|bool
* @see psm_load_lang() * @see psm_load_lang()
*/ */
function psm_get_lang() function psm_get_lang()
{ {
$args = func_get_args(); $args = func_get_args();
if (empty($args)) { if (empty($args)) {
return isset($GLOBALS['sm_lang']) ? $GLOBALS['sm_lang'] : $GLOBALS['sm_lang_default']; return isset($GLOBALS['sm_lang']) ? $GLOBALS['sm_lang'] : $GLOBALS['sm_lang_default'];
} }
if (isset($GLOBALS['sm_lang'])) { if (isset($GLOBALS['sm_lang'])) {
$lang = $GLOBALS['sm_lang']; $lang = $GLOBALS['sm_lang'];
$not_found = false; $not_found = false;
@ -72,13 +72,13 @@ namespace {
return $lang; return $lang;
} }
/** /**
* Load default language from the English (en_US) language file to the $GLOBALS['sm_lang_default'] variable * Load default language from the English (en_US) language file to the $GLOBALS['sm_lang_default'] variable
* Load language from the language file to the $GLOBALS['sm_lang'] variable if language is different from default * Load language from the language file to the $GLOBALS['sm_lang'] variable if language is different from default
* *
* @param string $lang language * @param string $lang language
* @see psm_get_lang() * @see psm_get_lang()
*/ */
function psm_load_lang($lang) function psm_load_lang($lang)
{ {
// load default language - English (en_US) // load default language - English (en_US)
@ -86,29 +86,29 @@ namespace {
$default_lang_file = PSM_PATH_LANG . 'en_US.lang.php'; $default_lang_file = PSM_PATH_LANG . 'en_US.lang.php';
file_exists($default_lang_file) ? require $default_lang_file : file_exists($default_lang_file) ? require $default_lang_file :
trigger_error("English translation needs to be installed at all time!", E_USER_ERROR); trigger_error("English translation needs to be installed at all time!", E_USER_ERROR);
isset($sm_lang) ? $GLOBALS['sm_lang_default'] = $sm_lang : isset($sm_lang) ? $GLOBALS['sm_lang_default'] = $sm_lang :
trigger_error("\$sm_lang not found in English translation!", E_USER_ERROR); trigger_error("\$sm_lang not found in English translation!", E_USER_ERROR);
unset($sm_lang); unset($sm_lang);
// load translation is the selected language is not English (en_US) // load translation is the selected language is not English (en_US)
if ($lang != "en_US") { if ($lang != "en_US") {
$lang_file = PSM_PATH_LANG . $lang . '.lang.php'; $lang_file = PSM_PATH_LANG . $lang . '.lang.php';
file_exists($lang_file) ? require $lang_file : file_exists($lang_file) ? require $lang_file :
trigger_error("Translation file could not be found! Default language will be used.", E_USER_WARNING); trigger_error("Translation file could not be found! Default language will be used.", E_USER_WARNING);
isset($sm_lang) ? $GLOBALS['sm_lang'] = $sm_lang : isset($sm_lang) ? $GLOBALS['sm_lang'] = $sm_lang :
trigger_error("\$sm_lang not found in translation file! Default language will be used.", E_USER_WARNING); trigger_error("\$sm_lang not found in translation file! Default language will be used.", E_USER_WARNING);
isset($sm_lang['locale']) ? setlocale(LC_TIME, $sm_lang['locale']) : isset($sm_lang['locale']) ? setlocale(LC_TIME, $sm_lang['locale']) :
trigger_error("locale could not ben found in translation file.", E_USER_WARNING); trigger_error("locale could not ben found in translation file.", E_USER_WARNING);
} }
} }
/** /**
* Retrieve a list with keys of the available languages * Retrieve a list with keys of the available languages
* *
* @return array * @return array
* @see psm_load_lang() * @see psm_load_lang()
*/ */
function psm_get_langs() function psm_get_langs()
{ {
$fn_ext = '.lang.php'; $fn_ext = '.lang.php';
@ -133,11 +133,11 @@ namespace {
return $langs; return $langs;
} }
/** /**
* Retrieve a list with available sms gateways * Retrieve a list with available sms gateways
* *
* @return array * @return array
*/ */
function psm_get_sms_gateways() function psm_get_sms_gateways()
{ {
$sms_gateway_files = glob(PSM_PATH_SMS_GATEWAY . '*.php'); $sms_gateway_files = glob(PSM_PATH_SMS_GATEWAY . '*.php');
@ -155,14 +155,14 @@ namespace {
return $sms_gateways; return $sms_gateways;
} }
/** /**
* Get a setting from the config. * Get a setting from the config.
* *
* @param string $key * @param string $key
* @param mixed $alt if not set, return this alternative * @param mixed $alt if not set, return this alternative
* @return string * @return string
* @see psm_load_conf() * @see psm_load_conf()
*/ */
function psm_get_conf($key, $alt = null) function psm_get_conf($key, $alt = null)
{ {
if (!isset($GLOBALS['sm_config'])) { if (!isset($GLOBALS['sm_config'])) {
@ -173,13 +173,13 @@ namespace {
return $result; return $result;
} }
/** /**
* Load config from the database to the $GLOBALS['sm_config'] variable * Load config from the database to the $GLOBALS['sm_config'] variable
* *
* @global object $db * @return boolean
* @return boolean * @global object $db
* @see psm_get_conf() * @see psm_get_conf()
*/ */
function psm_load_conf() function psm_load_conf()
{ {
global $db; global $db;
@ -204,14 +204,14 @@ namespace {
} }
} }
/** /**
* Update a config setting. * Update a config setting.
* *
* If the key does not exist yet it will be created. * If the key does not exist yet it will be created.
* @global \psm\Service\Database $db * @param string $key
* @param string $key * @param string $value
* @param string $value * @global \psm\Service\Database $db
*/ */
function psm_update_conf($key, $value) function psm_update_conf($key, $value)
{ {
global $db; global $db;
@ -223,8 +223,8 @@ namespace {
$db->save( $db->save(
PSM_DB_PREFIX . 'config', PSM_DB_PREFIX . 'config',
array( array(
'key' => $key, 'key' => $key,
'value' => $value, 'value' => $value,
) )
); );
} else { } else {
@ -243,16 +243,16 @@ namespace {
# #
############################################### ###############################################
/** /**
* This function merely adds the message to the log table. It does not perform any checks, * This function merely adds the message to the log table. It does not perform any checks,
* everything should have been handled when calling this function * everything should have been handled when calling this function
* *
* @param string $server_id * @param string $server_id
* @param string $type * @param string $type
* @param string $message * @param string $message
* *
* @return int log_id * @return int log_id
*/ */
function psm_add_log($server_id, $type, $message) function psm_add_log($server_id, $type, $message)
{ {
global $db; global $db;
@ -260,19 +260,19 @@ namespace {
return $db->save( return $db->save(
PSM_DB_PREFIX . 'log', PSM_DB_PREFIX . 'log',
array( array(
'server_id' => $server_id, 'server_id' => $server_id,
'type' => $type, 'type' => $type,
'message' => $message, 'message' => $message,
) )
); );
} }
/** /**
* This function just adds a user to the log_users table. * This function just adds a user to the log_users table.
* *
* @param $log_id * @param $log_id
* @param $user_id * @param $user_id
*/ */
function psm_add_log_user($log_id, $user_id) function psm_add_log_user($log_id, $user_id)
{ {
global $db; global $db;
@ -280,19 +280,19 @@ namespace {
$db->save( $db->save(
PSM_DB_PREFIX . 'log_users', PSM_DB_PREFIX . 'log_users',
array( array(
'log_id' => $log_id, 'log_id' => $log_id,
'user_id' => $user_id, 'user_id' => $user_id,
) )
); );
} }
/** /**
* This function adds the result of a check to the uptime table for logging purposes. * This function adds the result of a check to the uptime table for logging purposes.
* *
* @param int $server_id * @param int $server_id
* @param int $status * @param int $status
* @param string $latency * @param string $latency
*/ */
function psm_log_uptime($server_id, $status, $latency) function psm_log_uptime($server_id, $status, $latency)
{ {
global $db; global $db;
@ -300,62 +300,62 @@ namespace {
$db->save( $db->save(
PSM_DB_PREFIX . 'servers_uptime', PSM_DB_PREFIX . 'servers_uptime',
array( array(
'server_id' => $server_id, 'server_id' => $server_id,
'date' => date('Y-m-d H:i:s'), 'date' => date('Y-m-d H:i:s'),
'status' => $status, 'status' => $status,
'latency' => $latency, 'latency' => $latency,
) )
); );
} }
/** /**
* Converts an interval into a string * Converts an interval into a string
* *
* @param DateInterval $interval * @param DateInterval $interval
* @return string * @return string
*/ */
function psm_format_interval(DateInterval $interval) function psm_format_interval(DateInterval $interval)
{ {
$result = ""; $result = "";
if ($interval->y) { if ($interval->y) {
$result .= $interval->format("%y ") . (($interval->y == 1) ? $result .= $interval->format("%y ") . (($interval->y == 1) ?
psm_get_lang('system', 'year') : psm_get_lang('system', 'years')) . " "; psm_get_lang('system', 'year') : psm_get_lang('system', 'years')) . " ";
} }
if ($interval->m) { if ($interval->m) {
$result .= $interval->format("%m ") . (($interval->m == 1) ? $result .= $interval->format("%m ") . (($interval->m == 1) ?
psm_get_lang('system', 'month') : psm_get_lang('system', 'months')) . " "; psm_get_lang('system', 'month') : psm_get_lang('system', 'months')) . " ";
} }
if ($interval->d) { if ($interval->d) {
$result .= $interval->format("%d ") . (($interval->d == 1) ? $result .= $interval->format("%d ") . (($interval->d == 1) ?
psm_get_lang('system', 'day') : psm_get_lang('system', 'days')) . " "; psm_get_lang('system', 'day') : psm_get_lang('system', 'days')) . " ";
} }
if ($interval->h) { if ($interval->h) {
$result .= $interval->format("%h ") . (($interval->h == 1) ? $result .= $interval->format("%h ") . (($interval->h == 1) ?
psm_get_lang('system', 'hour') : psm_get_lang('system', 'hours')) . " "; psm_get_lang('system', 'hour') : psm_get_lang('system', 'hours')) . " ";
} }
if ($interval->i) { if ($interval->i) {
$result .= $interval->format("%i ") . (($interval->i == 1) ? $result .= $interval->format("%i ") . (($interval->i == 1) ?
psm_get_lang('system', 'minute') : psm_get_lang('system', 'minutes')) . " "; psm_get_lang('system', 'minute') : psm_get_lang('system', 'minutes')) . " ";
} }
if ($interval->s) { if ($interval->s) {
$result .= $interval->format("%s ") . (($interval->s == 1) ? $result .= $interval->format("%s ") . (($interval->s == 1) ?
psm_get_lang('system', 'second') : psm_get_lang('system', 'seconds')) . " "; psm_get_lang('system', 'second') : psm_get_lang('system', 'seconds')) . " ";
} }
return $result; return $result;
} }
/** /**
* Parses a string from the language file with the correct variables replaced in the message * Parses a string from the language file with the correct variables replaced in the message
* *
* @param boolean|null $status * @param boolean|null $status
* @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message' or 'telegram_message' * @param string $type is either 'sms', 'email', 'pushover_title', 'pushover_message', 'webhook_title', 'webhook_message' or 'telegram_message'
* @param array $vars server information about the server which may be placed in a message: * @param array $vars server information about the server which may be placed in a message:
* %KEY% will be replaced by your value * %KEY% will be replaced by your value
* @param boolean $combi parse other message if notifications need to be send combined * @param boolean $combi parse other message if notifications need to be send combined
* @return string parsed message * @return string parsed message
*/ */
function psm_parse_msg($status, $type, $vars, $combi = false) function psm_parse_msg($status, $type, $vars, $combi = false)
{ {
if (is_bool($status)) { if (is_bool($status)) {
@ -378,20 +378,20 @@ namespace {
return $message; return $message;
} }
/** /**
* Shortcut to curl_init(), curl_exec and curl_close() * Shortcut to curl_init(), curl_exec and curl_close()
* *
* @param string $href * @param string $href
* @param boolean $header return headers? * @param boolean $header return headers?
* @param boolean $body return body? * @param boolean $body return body?
* @param int|null $timeout connection timeout in seconds. defaults to PSM_CURL_TIMEOUT (10 secs). * @param int|null $timeout connection timeout in seconds. defaults to PSM_CURL_TIMEOUT (10 secs).
* @param boolean $add_agent add user agent? * @param boolean $add_agent add user agent?
* @param string|bool $website_username Username website * @param string|bool $website_username Username website
* @param string|bool $website_password Password website * @param string|bool $website_password Password website
* @param string|null $request_method Request method like GET, POST etc. * @param string|null $request_method Request method like GET, POST etc.
* @param string|null $post_field POST data * @param string|null $post_field POST data
* @return array cURL result * @return array cURL result
*/ */
function psm_curl_get( function psm_curl_get(
$href, $href,
$header = false, $header = false,
@ -419,7 +419,7 @@ namespace {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_ENCODING, ''); curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_CERTINFO, 1); curl_setopt($ch, CURLOPT_CERTINFO, 1);
if (!empty($request_method)) { if (!empty($request_method)) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method);
} }
@ -452,33 +452,33 @@ namespace {
} }
if ($add_agent) { if ($add_agent) {
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; phpservermon/' . curl_setopt($ch, CURLOPT_USERAGENT, psm_get_conf('user_agent', 'Mozilla/5.0 (compatible; phpservermon/' .
PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)'); PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)'));
} }
$result['exec'] = curl_exec($ch); $result['exec'] = curl_exec($ch);
$result['info'] = curl_getinfo($ch); $result['info'] = curl_getinfo($ch);
curl_close($ch); curl_close($ch);
if (defined('PSM_DEBUG') && PSM_DEBUG === true && psm_is_cli()) { if (defined('PSM_DEBUG') && PSM_DEBUG === true && psm_is_cli()) {
echo PHP_EOL . echo PHP_EOL .
'==============cURL Result for: ' . $href . '===========================================' . PHP_EOL; '==============cURL Result for: ' . $href . '===========================================' . PHP_EOL;
print_r($result); print_r($result);
echo PHP_EOL . echo PHP_EOL .
'==============END cURL Resul for: ' . $href . '===========================================' . PHP_EOL; '==============END cURL Resul for: ' . $href . '===========================================' . PHP_EOL;
} }
return $result; return $result;
} }
/** /**
* Get a "nice" timespan message * Get a "nice" timespan message
* *
* Source: http://www.interactivetools.com/forum/forum-posts.php?postNum=2208966 * Source: http://www.interactivetools.com/forum/forum-posts.php?postNum=2208966
* @param string $time * @param string $time
* @return string * @return string
*/ */
function psm_timespan($time) function psm_timespan($time)
{ {
if (empty($time) || $time == '0000-00-00 00:00:00') { if (empty($time) || $time == '0000-00-00 00:00:00') {
@ -489,7 +489,7 @@ namespace {
} }
if ($time < strtotime(date('Y-m-d 00:00:00')) - 60 * 60 * 24 * 3) { if ($time < strtotime(date('Y-m-d 00:00:00')) - 60 * 60 * 24 * 3) {
$format = psm_get_lang('system', (date('Y') !== date('Y', $time)) ? $format = psm_get_lang('system', (date('Y') !== date('Y', $time)) ?
'long_day_format' : 'short_day_format'); 'long_day_format' : 'short_day_format');
// Check for Windows to find and replace the %e // Check for Windows to find and replace the %e
// modifier correctly // modifier correctly
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
@ -500,7 +500,7 @@ namespace {
$d = time() - $time; $d = time() - $time;
if ($d >= 60 * 60 * 24) { if ($d >= 60 * 60 * 24) {
$format = psm_get_lang('system', (date('l', time() - 60 * 60 * 24) == date('l', $time)) ? $format = psm_get_lang('system', (date('l', time() - 60 * 60 * 24) == date('l', $time)) ?
'yesterday_format' : 'other_day_format'); 'yesterday_format' : 'other_day_format');
return strftime($format, $time); return strftime($format, $time);
} }
if ($d >= 60 * 60 * 2) { if ($d >= 60 * 60 * 2) {
@ -522,11 +522,11 @@ namespace {
return psm_get_lang('system', 'a_second_ago'); return psm_get_lang('system', 'a_second_ago');
} }
/** /**
* Get a localised date from MySQL date format * Get a localised date from MySQL date format
* @param string $time * @param string $time
* @return string * @return string
*/ */
function psm_date($time) function psm_date($time)
{ {
if (empty($time) || $time == '0000-00-00 00:00:00') { if (empty($time) || $time == '0000-00-00 00:00:00') {
@ -535,12 +535,12 @@ namespace {
return strftime('%x %X', strtotime($time)); return strftime('%x %X', strtotime($time));
} }
/** /**
* Check if an update is available for PHP Server Monitor. * Check if an update is available for PHP Server Monitor.
* *
* Will only check for new version if user turned updates on in config. * Will only check for new version if user turned updates on in config.
* @return boolean * @return boolean
*/ */
function psm_update_available() function psm_update_available()
{ {
if (!psm_get_conf('show_update')) { if (!psm_get_conf('show_update')) {
@ -582,14 +582,14 @@ namespace {
return version_compare($latestVersion, $current, '>'); return version_compare($latestVersion, $current, '>');
} }
/** /**
* Prepare a new phpmailer instance. * Prepare a new phpmailer instance.
* *
* If the from name and email are left blank they will be prefilled from the config. * If the from name and email are left blank they will be prefilled from the config.
* @param string $from_name * @param string $from_name
* @param string $from_email * @param string $from_email
* @return \PHPMailer\PHPMailer\PHPMailer * @return \PHPMailer\PHPMailer\PHPMailer
*/ */
function psm_build_mail($from_name = null, $from_email = null) function psm_build_mail($from_name = null, $from_email = null)
{ {
$phpmailer = new \PHPMailer\PHPMailer\PHPMailer(); $phpmailer = new \PHPMailer\PHPMailer\PHPMailer();
@ -600,7 +600,7 @@ namespace {
if (psm_get_conf('email_smtp') == '1') { if (psm_get_conf('email_smtp') == '1') {
$phpmailer->IsSMTP(); $phpmailer->IsSMTP();
$phpmailer->Host = psm_get_conf('email_smtp_host'); $phpmailer->Host = psm_get_conf('email_smtp_host');
$phpmailer->Port = (int) psm_get_conf('email_smtp_port'); $phpmailer->Port = (int)psm_get_conf('email_smtp_port');
$phpmailer->SMTPSecure = psm_get_conf('email_smtp_security'); $phpmailer->SMTPSecure = psm_get_conf('email_smtp_security');
$smtp_user = psm_get_conf('email_smtp_username'); $smtp_user = psm_get_conf('email_smtp_username');
@ -628,11 +628,11 @@ namespace {
return $phpmailer; return $phpmailer;
} }
/** /**
* Prepare a new Pushover util. * Prepare a new Pushover util.
* *
* @return \Pushover * @return \Pushover
*/ */
function psm_build_pushover() function psm_build_pushover()
{ {
$pushover = new \Pushover(); $pushover = new \Pushover();
@ -641,10 +641,22 @@ namespace {
return $pushover; return $pushover;
} }
/** /**
* * Prepare a new Webhook util.
* @return \Telegram *
*/ * @return Webhook
*/
function psm_build_webhook()
{
$webhook = new Webhook();
return $webhook;
}
/**
*
* @return \Telegram
*/
function psm_build_telegram() function psm_build_telegram()
{ {
$telegram = new \Telegram(); $telegram = new \Telegram();
@ -656,12 +668,12 @@ namespace {
/** /**
* Send message via XMPP. * Send message via XMPP.
* *
* @param string $host * @param string $host
* @param string $username * @param string $username
* @param string $password * @param string $password
* @param array $receivers * @param array $receivers
* @param string $message * @param string $message
* @param int|null $port * @param int|null $port
* @param string|null $domain * @param string|null $domain
*/ */
function psm_jabber_send_message($host, $username, $password, $receivers, $message, $port = null, $domain = null) function psm_jabber_send_message($host, $username, $password, $receivers, $message, $port = null, $domain = null)
@ -689,7 +701,7 @@ namespace {
$client->add_cb('on_auth_success', function () use ($client, $receivers, $message) { $client->add_cb('on_auth_success', function () use ($client, $receivers, $message) {
JAXLLogger::info('got on_auth_success cb'); JAXLLogger::info('got on_auth_success cb');
foreach ($receivers as $receiver) { foreach ($receivers as $receiver) {
$client->send_chat_msg($receiver, $message); $client->send_chat_msg($receiver, $message);
} }
$client->send_end_stream(); $client->send_end_stream();
}); });
@ -707,11 +719,11 @@ namespace {
} }
} }
/** /**
* Prepare a new SMS util. * Prepare a new SMS util.
* *
* @return \psm\Txtmsg\TxtmsgInterface * @return \psm\Txtmsg\TxtmsgInterface
*/ */
function psm_build_sms() function psm_build_sms()
{ {
$sms = null; $sms = null;
@ -758,6 +770,9 @@ namespace {
case 'octopush': case 'octopush':
$sms = new \psm\Txtmsg\Octopush(); $sms = new \psm\Txtmsg\Octopush();
break; break;
case 'ovhsms':
$sms = new \psm\Txtmsg\OVHsms();
break;
case 'smsgw': case 'smsgw':
$sms = new \psm\Txtmsg\Smsgw(); $sms = new \psm\Txtmsg\Smsgw();
break; break;
@ -781,6 +796,8 @@ namespace {
break; break;
case 'ysmal': case 'ysmal':
$sms = new \psm\Txtmsg\Ysmal(); $sms = new \psm\Txtmsg\Ysmal();
case 'smsapi':
$sms = new \psm\Txtmsg\SMSAPI();
break; break;
} }
@ -793,20 +810,20 @@ namespace {
return $sms; return $sms;
} }
/** /**
* Generate a new link to the current monitor * Generate a new link to the current monitor
* @param array|string $params key value pairs or pre-formatted string * @param array|string $params key value pairs or pre-formatted string
* @param boolean $urlencode urlencode all params? * @param boolean $urlencode urlencode all params?
* @param boolean $htmlentities use entities in url? * @param boolean $htmlentities use entities in url?
* @return string * @return string
*/ */
function psm_build_url($params = array(), $urlencode = true, $htmlentities = true) function psm_build_url($params = array(), $urlencode = true, $htmlentities = true)
{ {
if (defined('PSM_BASE_URL') && PSM_BASE_URL !== null) { if (defined('PSM_BASE_URL') && PSM_BASE_URL !== null) {
$url = PSM_BASE_URL; $url = PSM_BASE_URL;
} else { } else {
$url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $url = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ||
$_SERVER['SERVER_PORT'] == 443 ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; $_SERVER['SERVER_PORT'] == 443 ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
// on Windows, dirname() adds both back- and forward slashes (http://php.net/dirname). // on Windows, dirname() adds both back- and forward slashes (http://php.net/dirname).
// for urls, we only want the forward slashes. // for urls, we only want the forward slashes.
$url .= dirname($_SERVER['SCRIPT_NAME']); $url .= dirname($_SERVER['SCRIPT_NAME']);
@ -833,12 +850,12 @@ namespace {
return $url; return $url;
} }
/** /**
* Try existence of a GET var, if not return the alternative * Try existence of a GET var, if not return the alternative
* @param string $key * @param string $key
* @param string $alt * @param string $alt
* @return mixed * @return mixed
*/ */
function psm_GET($key, $alt = null) function psm_GET($key, $alt = null)
{ {
if (isset($_GET[$key])) { if (isset($_GET[$key])) {
@ -848,12 +865,12 @@ namespace {
} }
} }
/** /**
* Try existence of a POST var, if not return the alternative * Try existence of a POST var, if not return the alternative
* @param string $key * @param string $key
* @param string|array|bool $alt * @param string|array|bool $alt
* @return mixed * @return mixed
*/ */
function psm_POST($key, $alt = null) function psm_POST($key, $alt = null)
{ {
if (isset($_POST[$key])) { if (isset($_POST[$key])) {
@ -863,12 +880,12 @@ namespace {
} }
} }
/** /**
* Check if we are in CLI mode * Check if we are in CLI mode
* *
* Note, php_sapi cannot be used because cgi-fcgi returns both for web and cli. * Note, php_sapi cannot be used because cgi-fcgi returns both for web and cli.
* @return boolean * @return boolean
*/ */
function psm_is_cli() function psm_is_cli()
{ {
return (!isset($_SERVER['SERVER_SOFTWARE']) || php_sapi_name() == 'cli'); return (!isset($_SERVER['SERVER_SOFTWARE']) || php_sapi_name() == 'cli');
@ -880,11 +897,11 @@ namespace {
# #
############################################### ###############################################
/** /**
* Only used for debugging and testing * Only used for debugging and testing
* *
* @param mixed $arr * @param mixed $arr
*/ */
function pre($arr = null) function pre($arr = null)
{ {
echo "<pre>"; echo "<pre>";
@ -895,9 +912,9 @@ namespace {
echo "</pre>"; echo "</pre>";
} }
/** /**
* Send headers to the browser to avoid caching * Send headers to the browser to avoid caching
*/ */
function psm_no_cache() function psm_no_cache()
{ {
header("Expires: Mon, 20 Dec 1998 01:00:00 GMT"); header("Expires: Mon, 20 Dec 1998 01:00:00 GMT");
@ -906,14 +923,14 @@ namespace {
header("Pragma: no-cache"); header("Pragma: no-cache");
} }
/** /**
* Encrypts the password for storage in the database * Encrypts the password for storage in the database
* *
* @param string $key * @param string $key
* @param string $password * @param string $password
* @return string * @return string
* @author Pavel Laupe Dvorak <pavel@pavel-dvorak.cz> * @author Pavel Laupe Dvorak <pavel@pavel-dvorak.cz>
*/ */
function psm_password_encrypt($key, $password) function psm_password_encrypt($key, $password)
{ {
if (empty($password)) { if (empty($password)) {
@ -942,14 +959,14 @@ namespace {
return $encrypted; return $encrypted;
} }
/** /**
* Decrypts password stored in the database for future use * Decrypts password stored in the database for future use
* *
* @param string $key * @param string $key
* @param string $encryptedString * @param string $encryptedString
* @return string * @return string
* @author Pavel Laupe Dvorak <pavel@pavel-dvorak.cz> * @author Pavel Laupe Dvorak <pavel@pavel-dvorak.cz>
*/ */
function psm_password_decrypt($key, $encryptedString) function psm_password_decrypt($key, $encryptedString)
{ {
if (empty($encryptedString)) { if (empty($encryptedString)) {
@ -957,7 +974,7 @@ namespace {
} }
if (empty($key)) { if (empty($key)) {
throw new \InvalidArgumentException('invalid_encryption_key'); throw new \InvalidArgumentException('invalid_encryption_key');
} }
// using open ssl // using open ssl
@ -972,16 +989,16 @@ namespace {
OPENSSL_RAW_DATA, OPENSSL_RAW_DATA,
$iv $iv
); );
return $decrypted; return $decrypted;
} }
/** /**
* Send notification to Telegram * Send notification to Telegram
* *
* @return string * @return string
* @author Tim Zandbergen <tim@xervion.nl> * @author Tim Zandbergen <tim@xervion.nl>
*/ */
class Telegram class Telegram
{ {
private $token; private $token;
@ -991,12 +1008,14 @@ namespace {
public function setToken($token) public function setToken($token)
{ {
$this->token = (string) $token; $this->token = (string)$token;
} }
public function setUser($user) public function setUser($user)
{ {
$this->user = (string) $user; $this->user = (string)$user;
} }
public function setMessage($message) public function setMessage($message)
{ {
$message = str_replace("<ul>", "", $message); $message = str_replace("<ul>", "", $message);
@ -1005,8 +1024,9 @@ namespace {
$message = str_replace("</li>", "\n", $message); $message = str_replace("</li>", "\n", $message);
$message = str_replace("<br>", "\n", $message); $message = str_replace("<br>", "\n", $message);
$message = str_replace("<br/>", "\n", $message); $message = str_replace("<br/>", "\n", $message);
$this->message = (string) $message; $this->message = (string)$message;
} }
public function sendurl() public function sendurl()
{ {
$con = curl_init($this->url); $con = curl_init($this->url);
@ -1017,15 +1037,17 @@ namespace {
$response = json_decode($response, true); $response = json_decode($response, true);
return $response; return $response;
} }
public function send() public function send()
{ {
if (!empty($this->token) && !empty($this->user) && !empty($this->message)) { if (!empty($this->token) && !empty($this->user) && !empty($this->message)) {
$this->url = 'https://api.telegram.org/bot' . urlencode($this->token) . $this->url = 'https://api.telegram.org/bot' . urlencode($this->token) .
'/sendMessage?chat_id=' . urlencode($this->user) . '&text=' . '/sendMessage?chat_id=' . urlencode($this->user) . '&text=' .
urlencode($this->message) . '&parse_mode=HTML&disable_web_page_preview=True'; urlencode($this->message) . '&parse_mode=HTML&disable_web_page_preview=True';
} }
return $this->sendurl(); return $this->sendurl();
} }
// Get the bots username // Get the bots username
public function getBotUsername() public function getBotUsername()
{ {
@ -1035,4 +1057,121 @@ namespace {
return $this->sendurl(); return $this->sendurl();
} }
} }
/**
* Send notification via webhooks
*
* @return string
* @author Malte Grosse
*/
class Webhook
{
protected $url;
protected $json;
protected $message;
/**
* Send Webhook
*
* @return bool|string
* @var string $message
*
*/
public function sendWebhook($message)
{
$error = "";
$success = 1;
$this->setMessage($message);
$jsonMessage = strtr($this->json, array('#message' => $this->message));
$curl = curl_init($this->url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonMessage);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$err = curl_errno($curl);
if ($err != 0 || $httpcode < 200 || $httpcode >= 300) {
$success = 0;
$error = "HTTP_code: " . $httpcode . ".\ncURL error (" . $err . "): " . $err . ". \nResult: " . $result;
}
curl_close($curl);
if ($success) {
return 1;
}
return $error;
}
/**
* setUrl
*
* @var string $url
*
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* getUrl
*
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* setJson
*
* @var string $json
*
*/
public function setJson($json)
{
$this->json = $json;
}
/**
* getJson
*
* @return string
*/
public function getJson()
{
return $this->json;
}
/**
* Set message
*
* @return string
* @var string $message
*
*/
public function setMessage($message)
{
$message = str_replace("<ul>", "", $message);
$message = str_replace("</ul>", "\n", $message);
$message = str_replace("<li>", "- ", $message);
$message = str_replace("</li>", "\n", $message);
$message = str_replace("<br>", "\n", $message);
$message = str_replace("<br/>", "\n", $message);
$message = str_replace("<b>", "", $message);
$message = str_replace("<b/>", "", $message);
$message = strip_tags($message);
$this->message = (string)$message;
}
}
} }

View File

@ -30,7 +30,7 @@
/** /**
* Current PSM version * Current PSM version
*/ */
define('PSM_VERSION', '3.5.0'); define('PSM_VERSION', '3.6.0.beta1');
/** /**
* URL to check for updates. Will not be checked if turned off on config page. * URL to check for updates. Will not be checked if turned off on config page.

View File

@ -66,6 +66,7 @@ $sm_lang = array(
'a_minute_ago' => 'преди минута', 'a_minute_ago' => 'преди минута',
'seconds_ago' => 'преди %d секунди', 'seconds_ago' => 'преди %d секунди',
'a_second_ago' => 'преди секунда', 'a_second_ago' => 'преди секунда',
'seconds' => 'секунди',
), ),
'menu' => array( 'menu' => array(
'config' => 'Настройки', 'config' => 'Настройки',
@ -219,8 +220,6 @@ $sm_lang = array(
'email_smtp' => 'Активиране на SMTP', 'email_smtp' => 'Активиране на SMTP',
'email_smtp_host' => 'SMTP сървър', 'email_smtp_host' => 'SMTP сървър',
'email_smtp_port' => 'SMTP порт', 'email_smtp_port' => 'SMTP порт',
'email_smtp_security' => 'SMTP security',
'email_smtp_security_none' => 'None',
'email_smtp_username' => 'SMTP потребителско име', 'email_smtp_username' => 'SMTP потребителско име',
'email_smtp_password' => 'SMTP парола', 'email_smtp_password' => 'SMTP парола',
'email_smtp_noauth' => 'Оставете празно за "без аутентикация"', 'email_smtp_noauth' => 'Оставете празно за "без аутентикация"',
@ -267,7 +266,6 @@ $sm_lang = array(
системата', системата',
'log_sms' => 'Да се пази ли лог на изпратените SMS съобщения от 'log_sms' => 'Да се пази ли лог на изпратените SMS съобщения от
системата', системата',
'log_pushover' => 'Log pushover messages sent by the script',
'updated' => 'Настройките са обновени успешно.', 'updated' => 'Настройките са обновени успешно.',
'tab_email' => 'Имейл', 'tab_email' => 'Имейл',
'tab_sms' => 'SMS', 'tab_sms' => 'SMS',

View File

@ -347,7 +347,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-recàrrega', 'auto_refresh' => 'Auto-recàrrega',
'auto_refresh_description' => 'Recarregar automàticament la plana Servidors.<br/><span class="small">Temps en 'auto_refresh_description' => 'Recarregar automàticament la plana Servidors.<br/><span class="small">Temps en
segons, si poseu ZERO la plana no s\'auto-recarregarà.</span>', segons, si poseu ZERO la plana no s\'auto-recarregarà.</span>',
'seconds' => 'segons',
'test' => 'Provar', 'test' => 'Provar',
'test_email' => 'S\'enviarà un correu a l\'adreça que teniu al vostre perfil d\'usuari.', 'test_email' => 'S\'enviarà un correu a l\'adreça que teniu al vostre perfil d\'usuari.',
'test_sms' => 'S\'enviarà un SMS al telèfon que teniu al vostre perfil d\'usuari.', 'test_sms' => 'S\'enviarà un SMS al telèfon que teniu al vostre perfil d\'usuari.',

View File

@ -68,6 +68,7 @@ $sm_lang = array(
'a_minute_ago' => 'cca před minutou', 'a_minute_ago' => 'cca před minutou',
'seconds_ago' => 'před %d vteřinami', 'seconds_ago' => 'před %d vteřinami',
'a_second_ago' => 'před chvílí', 'a_second_ago' => 'před chvílí',
'seconds' => 'sekunder',
), ),
'menu' => array( 'menu' => array(
'config' => 'Konfigurace', 'config' => 'Konfigurace',
@ -260,7 +261,6 @@ $sm_lang = array(
'auto_refresh' => 'Automaticky obnovit', 'auto_refresh' => 'Automaticky obnovit',
'auto_refresh_description' => 'Automaticky obnovit stránku Servery.<br><span class="small">Čas v sekundách, 'auto_refresh_description' => 'Automaticky obnovit stránku Servery.<br><span class="small">Čas v sekundách,
0 pro vypnutí automatického obnovení.</span>', 0 pro vypnutí automatického obnovení.</span>',
'seconds' => 'sekund',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'E-mail bude odeslán na adresu uvedenou v uživatelském profilu.', 'test_email' => 'E-mail bude odeslán na adresu uvedenou v uživatelském profilu.',
'test_sms' => 'SMS bude odeslána na telefonní číslo uvedené v uživatelském profilu.', 'test_sms' => 'SMS bude odeslána na telefonní číslo uvedené v uživatelském profilu.',

View File

@ -65,6 +65,7 @@ $sm_lang = array(
'a_minute_ago' => 'omkring et minut siden', 'a_minute_ago' => 'omkring et minut siden',
'seconds_ago' => '%d sekunder siden', 'seconds_ago' => '%d sekunder siden',
'a_second_ago' => 'et sekund siden', 'a_second_ago' => 'et sekund siden',
'seconds' => 'sekunder',
), ),
'menu' => array( 'menu' => array(
'config' => 'Indstillinger', 'config' => 'Indstillinger',
@ -245,7 +246,6 @@ $sm_lang = array(
'auto_refresh' => 'Genopfrisk automatisk', 'auto_refresh' => 'Genopfrisk automatisk',
'auto_refresh_description' => 'Genopfrisk automatisk serversider.<br><span class="small">Tid i sekunder. Hvis 'auto_refresh_description' => 'Genopfrisk automatisk serversider.<br><span class="small">Tid i sekunder. Hvis
0 vil siden ikke genopfriske automatisk</span>', 0 vil siden ikke genopfriske automatisk</span>',
'seconds' => 'sekunder',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'En e-mail vil blive sendt til den adresse, der er angivet i din brugerprofil.', 'test_email' => 'En e-mail vil blive sendt til den adresse, der er angivet i din brugerprofil.',
'test_sms' => 'En SMS vil blive sendt til det nummer, der er angivet i din brugerprofil.', 'test_sms' => 'En SMS vil blive sendt til det nummer, der er angivet i din brugerprofil.',

View File

@ -66,6 +66,7 @@ $sm_lang = array(
'a_minute_ago' => 'vor über einer Minute', 'a_minute_ago' => 'vor über einer Minute',
'seconds_ago' => 'vor %d Sekunden', 'seconds_ago' => 'vor %d Sekunden',
'a_second_ago' => 'vor über einer Sekunde', 'a_second_ago' => 'vor über einer Sekunde',
'seconds' => 'Sekunden',
), ),
'menu' => array( 'menu' => array(
'config' => 'Einstellungen', 'config' => 'Einstellungen',
@ -249,7 +250,6 @@ $sm_lang = array(
'auto_refresh_description' => 'Automatische Aktualisierung der Server-Übersichtsseite<br><span 'auto_refresh_description' => 'Automatische Aktualisierung der Server-Übersichtsseite<br><span
class="small">Zeit in Sekunden - die Ziffer \'0\' deaktiviert die automatische class="small">Zeit in Sekunden - die Ziffer \'0\' deaktiviert die automatische
Aktualisierung.</span>', Aktualisierung.</span>',
'seconds' => 'Sekunden',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Eine E-Mail wird an die E-Mail-Adresse gesendet, die in Ihrem Profil hinterlegt ist.', 'test_email' => 'Eine E-Mail wird an die E-Mail-Adresse gesendet, die in Ihrem Profil hinterlegt ist.',
'test_sms' => 'Eine SMS wird an die Telefonnummer gesendet, die in Ihrem Profil hinterlegt ist.', 'test_sms' => 'Eine SMS wird an die Telefonnummer gesendet, die in Ihrem Profil hinterlegt ist.',

View File

@ -83,6 +83,8 @@ $sm_lang = array(
'minutes' => 'minutes', 'minutes' => 'minutes',
'second' => 'second', 'second' => 'second',
'seconds' => 'seconds', 'seconds' => 'seconds',
'millisecond' => 'millisecond',
'milliseconds' => 'milliseconds',
'current' => 'current', 'current' => 'current',
'settings' => 'Settings', 'settings' => 'Settings',
'search' => 'Search', 'search' => 'Search',
@ -136,6 +138,13 @@ $sm_lang = array(
'jabber' => 'Jabber', 'jabber' => 'Jabber',
'jabber_label' => 'Jabber', 'jabber_label' => 'Jabber',
'jabber_description' => 'You Jabber account', 'jabber_description' => 'You Jabber account',
'webhook' => 'Webhook',
'webhook_description' => 'Send a json webhook to a certain endpoint. <br/> The json can be customized, e.g. {
"text":"servermon: #message"}',
'webhook_url' => 'Webhook Url',
'webhook_url_description' => 'Webhook public endpoint url, should start with https://.',
'webhook_json' => 'Webhook JSON',
'webhook_json_description' => 'Define a custom json, use #message as message variable.',
'delete_title' => 'Delete User', 'delete_title' => 'Delete User',
'delete_message' => 'Are you sure you want to delete user \'%1\'?', 'delete_message' => 'Are you sure you want to delete user \'%1\'?',
'deleted' => 'User deleted.', 'deleted' => 'User deleted.',
@ -162,6 +171,7 @@ $sm_lang = array(
'email' => 'Email', 'email' => 'Email',
'sms' => 'SMS', 'sms' => 'SMS',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'webhook' => 'Webhook',
'telegram' => 'Telegram', 'telegram' => 'Telegram',
'jabber' => 'Jabber', 'jabber' => 'Jabber',
'no_logs' => 'No logs', 'no_logs' => 'No logs',
@ -227,6 +237,8 @@ $sm_lang = array(
'send_email' => 'Send Email', 'send_email' => 'Send Email',
'sms' => 'SMS', 'sms' => 'SMS',
'send_sms' => 'Send SMS', 'send_sms' => 'Send SMS',
'webhook' => 'Webhook',
'send_webhook' => 'Send Webhook notification',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'send_pushover' => 'Send Pushover notification', 'send_pushover' => 'Send Pushover notification',
'telegram' => 'Telegram', 'telegram' => 'Telegram',
@ -266,6 +278,7 @@ $sm_lang = array(
'chart_short_time_format' => '%H:%M', 'chart_short_time_format' => '%H:%M',
'warning_notifications_disabled_sms' => 'SMS notifications are disabled.', 'warning_notifications_disabled_sms' => 'SMS notifications are disabled.',
'warning_notifications_disabled_email' => 'Email notifications are disabled.', 'warning_notifications_disabled_email' => 'Email notifications are disabled.',
'warning_notifications_disabled_webhook' => 'Webhook notifications are disabled.',
'warning_notifications_disabled_pushover' => 'Pushover notifications are disabled.', 'warning_notifications_disabled_pushover' => 'Pushover notifications are disabled.',
'warning_notifications_disabled_telegram' => 'Telegram notifications are disabled.', 'warning_notifications_disabled_telegram' => 'Telegram notifications are disabled.',
'warning_notifications_disabled_jabber' => 'Jabber notifications are disabled.', 'warning_notifications_disabled_jabber' => 'Jabber notifications are disabled.',
@ -281,6 +294,7 @@ $sm_lang = array(
), ),
'config' => array( 'config' => array(
'general' => 'General', 'general' => 'General',
'site_title' => 'Site title',
'language' => 'Language', 'language' => 'Language',
'show_update' => 'Check for updates?', 'show_update' => 'Check for updates?',
'password_encrypt_key' => 'The encryption key password', 'password_encrypt_key' => 'The encryption key password',
@ -306,6 +320,12 @@ $sm_lang = array(
'sms_gateway_username' => 'Gateway username', 'sms_gateway_username' => 'Gateway username',
'sms_gateway_password' => 'Gateway password', 'sms_gateway_password' => 'Gateway password',
'sms_from' => 'Sender\'s phone number', 'sms_from' => 'Sender\'s phone number',
'webhook_status' => 'Allow sending webhooks',
'webhook_description' => 'Allow sending webhooks to services like slack. The message payload end endpoint are defined in the profile settings.',
'webhook_url' => 'Webhook Url',
'webhook_url_description' => 'Url to webhook endpoint',
'webhook_json' => 'Webhook Json',
'webhook_json_description' => 'Customized Json, use #message as message variable.',
'pushover_status' => 'Allow sending Pushover messages', 'pushover_status' => 'Allow sending Pushover messages',
'pushover_description' => 'Pushover is a service that makes it easy to get real-time notifications. See <a 'pushover_description' => 'Pushover is a service that makes it easy to get real-time notifications. See <a
href="https://pushover.net/" target="_blank">their website</a> for more info.', href="https://pushover.net/" target="_blank">their website</a> for more info.',
@ -360,17 +380,20 @@ $sm_lang = array(
'log_email' => 'Log emails sent by the script', 'log_email' => 'Log emails sent by the script',
'log_sms' => 'Log text messages sent by the script', 'log_sms' => 'Log text messages sent by the script',
'log_pushover' => 'Log pushover messages sent by the script', 'log_pushover' => 'Log pushover messages sent by the script',
'log_webhook' => 'Log webhook messages sent by the script',
'log_telegram' => 'Log Telegram messages sent by the script', 'log_telegram' => 'Log Telegram messages sent by the script',
'log_jabber' => 'Log Jabber messages sent by the script', 'log_jabber' => 'Log Jabber messages sent by the script',
'updated' => 'The configuration has been updated.', 'updated' => 'The configuration has been updated.',
'tab_email' => 'Email', 'tab_email' => 'Email',
'tab_sms' => 'SMS', 'tab_sms' => 'SMS',
'tab_pushover' => 'Pushover', 'tab_pushover' => 'Pushover',
'tab_webhook' => 'Webhook',
'tab_telegram' => 'Telegram', 'tab_telegram' => 'Telegram',
'tab_jabber' => 'Jabber', 'tab_jabber' => 'Jabber',
'settings_email' => 'Email settings', 'settings_email' => 'Email settings',
'settings_sms' => 'Text message settings', 'settings_sms' => 'Text message settings',
'settings_pushover' => 'Pushover settings', 'settings_pushover' => 'Pushover settings',
'settings_webhook' => 'Webhook settings',
'settings_telegram' => 'Telegram settings', 'settings_telegram' => 'Telegram settings',
'settings_jabber' => 'Jabber settings', 'settings_jabber' => 'Jabber settings',
'settings_notification' => 'Notification settings', 'settings_notification' => 'Notification settings',
@ -379,12 +402,12 @@ $sm_lang = array(
'auto_refresh' => 'Auto-refresh', 'auto_refresh' => 'Auto-refresh',
'auto_refresh_description' => 'Auto-refresh servers page.<br><span class="small">Time in seconds, if 0 the 'auto_refresh_description' => 'Auto-refresh servers page.<br><span class="small">Time in seconds, if 0 the
page won\'t refresh.</span>', page won\'t refresh.</span>',
'seconds' => 'seconds',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'An email will be sent to the address specified in your user profile.', 'test_email' => 'An email will be sent to the address specified in your user profile.',
'test_sms' => 'An SMS will be sent to the phone number specified in your user profile.', 'test_sms' => 'An SMS will be sent to the phone number specified in your user profile.',
'test_pushover' => 'A Pushover notification will be sent to the user key/device specified in your user 'test_pushover' => 'A Pushover notification will be sent to the user key/device specified in your user
profile.', profile.',
'test_webhook' => 'A webhook notification will be sent to the given url endpoint.',
'test_telegram' => 'A Telegram notification will be sent to the chat id specified in your user profile.', 'test_telegram' => 'A Telegram notification will be sent to the chat id specified in your user profile.',
'test_jabber' => 'A Jabber notification will be sent to the jabber account specified in your user profile.', 'test_jabber' => 'A Jabber notification will be sent to the jabber account specified in your user profile.',
'send' => 'Send', 'send' => 'Send',
@ -395,6 +418,10 @@ $sm_lang = array(
'sms_sent' => 'SMS sent', 'sms_sent' => 'SMS sent',
'sms_error' => 'An error has occurred while sending the SMS: %s', 'sms_error' => 'An error has occurred while sending the SMS: %s',
'sms_error_nomobile' => 'Unable to send test SMS: no valid phone number found in your profile.', 'sms_error_nomobile' => 'Unable to send test SMS: no valid phone number found in your profile.',
'webhook_sent' => 'Webhook notification sent',
'webhook_error' => 'An error has occurred while sending the webhook notification: %s',
'webhook_error_nourl' => 'Unable to send test notification: no url found in user profile.',
'webhook_error_nojson' => 'Unable to send test notification: no json found in user profile.',
'pushover_sent' => 'Pushover notification sent', 'pushover_sent' => 'Pushover notification sent',
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s', 'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global 'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global
@ -414,12 +441,17 @@ $sm_lang = array(
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server 'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server
uptime. Enter 0 to disable log cleanup.', uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days', 'log_retention_days' => 'days',
'user_agent' => 'User Agent',
'user_agent_key_note' => 'Custom user agent used by monitor within communication with external services.',
), ),
'notifications' => array( 'notifications' => array(
'off_sms' => 'Server \'%LABEL%\' is DOWN: ip=%IP%, port=%PORT%. Error=%ERROR%', 'off_sms' => 'Server \'%LABEL%\' is DOWN: ip=%IP%, port=%PORT%. Error=%ERROR%',
'off_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is DOWN', 'off_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is DOWN',
'off_email_body' => 'Failed to connect to the following server:<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: 'off_email_body' => 'Failed to connect to the following server:<br><br>Server: %LABEL%<br>IP: %IP%<br>Port:
%PORT%<br>Error: %ERROR%<br>Date: %DATE%', %PORT%<br>Error: %ERROR%<br>Date: %DATE%',
'off_webhook_title' => 'Server \'%LABEL%\' is DOWN',
'off_webhook_message' => 'Failed to connect to the following server:<br><br>Server: %LABEL%<br>IP:
%IP%<br>Port: %PORT%<br>Error: %ERROR%<br>Date: %DATE%',
'off_pushover_title' => 'Server \'%LABEL%\' is DOWN', 'off_pushover_title' => 'Server \'%LABEL%\' is DOWN',
'off_pushover_message' => 'Failed to connect to the following server:<br><br>Server: %LABEL%<br>IP: 'off_pushover_message' => 'Failed to connect to the following server:<br><br>Server: %LABEL%<br>IP:
%IP%<br>Port: %PORT%<br>Error: %ERROR%<br>Date: %DATE%', %IP%<br>Port: %PORT%<br>Error: %ERROR%<br>Date: %DATE%',
@ -431,6 +463,10 @@ $sm_lang = array(
'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING', 'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING',
'on_email_body' => 'Server \'%LABEL%\' is running again, it was down for 'on_email_body' => 'Server \'%LABEL%\' is running again, it was down for
%LAST_OFFLINE_DURATION%:<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: %PORT%<br>Date: %LAST_OFFLINE_DURATION%:<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: %PORT%<br>Date:
%DATE%',
'on_webhook_title' => 'Server \'%LABEL%\' is RUNNING',
'on_webhook_message' => 'Server \'%LABEL%\' is running again, it was down for
%LAST_OFFLINE_DURATION%:<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: %PORT%<br>Date:
%DATE%', %DATE%',
'on_pushover_title' => 'Server \'%LABEL%\' is RUNNING', 'on_pushover_title' => 'Server \'%LABEL%\' is RUNNING',
'on_pushover_message' => 'Server \'%LABEL%\' is running again, it was down for 'on_pushover_message' => 'Server \'%LABEL%\' is running again, it was down for
@ -443,6 +479,8 @@ $sm_lang = array(
%LAST_OFFLINE_DURATION%<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: %PORT%<br>Date: %LAST_OFFLINE_DURATION%<br><br>Server: %LABEL%<br>IP: %IP%<br>Port: %PORT%<br>Date:
%DATE%', %DATE%',
'combi_off_email_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error: 'combi_off_email_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error:
%ERROR%</li><li>Date: %DATE%</li></ul>',
'combi_off_webhook_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error:
%ERROR%</li><li>Date: %DATE%</li></ul>', %ERROR%</li><li>Date: %DATE%</li></ul>',
'combi_off_pushover_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error: 'combi_off_pushover_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Error:
%ERROR%</li><li>Date: %DATE%</li></ul>', %ERROR%</li><li>Date: %DATE%</li></ul>',
@ -452,6 +490,9 @@ $sm_lang = array(
Date: %DATE%<br><br>', Date: %DATE%<br><br>',
'combi_on_email_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Downtime: 'combi_on_email_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: %PORT%</li><li>Downtime:
%LAST_OFFLINE_DURATION%</li><li>Date: %DATE%</li></ul>', %LAST_OFFLINE_DURATION%</li><li>Date: %DATE%</li></ul>',
'combi_on_webhook_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port:
%PORT%</li><li>Downtime: %LAST_OFFLINE_DURATION%</li><li>Date:
%DATE%</li></ul>',
'combi_on_pushover_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port: 'combi_on_pushover_message' => '<ul><li>Server: %LABEL%</li><li>IP: %IP%</li><li>Port:
%PORT%</li><li>Downtime: %LAST_OFFLINE_DURATION%</li><li>Date: %PORT%</li><li>Downtime: %LAST_OFFLINE_DURATION%</li><li>Date:
%DATE%</li></ul>', %DATE%</li></ul>',
@ -460,8 +501,11 @@ $sm_lang = array(
'combi_on_jabber_message' => '- Server: %LABEL%<br>- IP: %IP%<br>- Port: %PORT%<br>- Downtime: 'combi_on_jabber_message' => '- Server: %LABEL%<br>- IP: %IP%<br>- Port: %PORT%<br>- Downtime:
%LAST_OFFLINE_DURATION%<br>- Date: %DATE%<br><br>', %LAST_OFFLINE_DURATION%<br>- Date: %DATE%<br><br>',
'combi_email_subject' => 'IMPORTANT: \'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', 'combi_email_subject' => 'IMPORTANT: \'%UP%\' servers UP again, \'%DOWN%\' servers DOWN',
'combi_webhook_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN',
'combi_pushover_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', 'combi_pushover_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN',
'combi_email_message' => '<b>The following servers went down:</b><br>%DOWN_SERVERS%<br><b>The following 'combi_email_message' => '<b>The following servers went down:</b><br>%DOWN_SERVERS%<br><b>The following
servers are up again:</b><br>%UP_SERVERS%',
'combi_webhook_message' => '<b>The following servers went down:</b><br>%DOWN_SERVERS%<br><b>The following
servers are up again:</b><br>%UP_SERVERS%', servers are up again:</b><br>%UP_SERVERS%',
'combi_pushover_message' => '<b>The following servers went down:</b><br>%DOWN_SERVERS%<br><b>The following 'combi_pushover_message' => '<b>The following servers went down:</b><br>%DOWN_SERVERS%<br><b>The following
servers are up again:</b><br>%UP_SERVERS%', servers are up again:</b><br>%UP_SERVERS%',

View File

@ -354,7 +354,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-actualizar', 'auto_refresh' => 'Auto-actualizar',
'auto_refresh_description' => 'Auto-actualizar la página de servidores.<br><span class="small">Tiempo en 'auto_refresh_description' => 'Auto-actualizar la página de servidores.<br><span class="small">Tiempo en
segundos, si se utiliza 0 la página no se actualizará.</span>', segundos, si se utiliza 0 la página no se actualizará.</span>',
'seconds' => 'segundos',
'test' => 'Prueba', 'test' => 'Prueba',
'test_email' => 'Un correo electrónico será enviado a la dirección especificada en su perfil de usuario.', 'test_email' => 'Un correo electrónico será enviado a la dirección especificada en su perfil de usuario.',
'test_sms' => 'Un SMS se enviará al número de teléfono especificado en su perfil de usuario.', 'test_sms' => 'Un SMS se enviará al número de teléfono especificado en su perfil de usuario.',

View File

@ -66,6 +66,7 @@ $sm_lang = array(
'a_minute_ago' => 'umbes minut aega tagasi', 'a_minute_ago' => 'umbes minut aega tagasi',
'seconds_ago' => '%d sekundit tagasi', 'seconds_ago' => '%d sekundit tagasi',
'a_second_ago' => 'üks sekund tagasi', 'a_second_ago' => 'üks sekund tagasi',
'seconds' => 'sekundit',
), ),
'menu' => array( 'menu' => array(
'config' => 'Konfiguratsioon', 'config' => 'Konfiguratsioon',
@ -244,7 +245,6 @@ $sm_lang = array(
'auto_refresh' => 'Automaatne värskendamine', 'auto_refresh' => 'Automaatne värskendamine',
'auto_refresh_description' => 'Värskenda lehte automaatselt.<br><span class="small">Aeg sekundites, kui 0 'auto_refresh_description' => 'Värskenda lehte automaatselt.<br><span class="small">Aeg sekundites, kui 0
siis lehte ei värskendata.</span>', siis lehte ei värskendata.</span>',
'seconds' => 'sekundit',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Email saadetakse profiilil märgitud aadressile.', 'test_email' => 'Email saadetakse profiilil märgitud aadressile.',
'test_sms' => 'SMS saadetakse profiilil märgitud numbrile.', 'test_sms' => 'SMS saadetakse profiilil märgitud numbrile.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'حدود یک دقیقه پیش', 'a_minute_ago' => 'حدود یک دقیقه پیش',
'seconds_ago' => '%d ثانیه پیش', 'seconds_ago' => '%d ثانیه پیش',
'a_second_ago' => 'یک ثانیه پیش', 'a_second_ago' => 'یک ثانیه پیش',
'seconds' => 'ثانیه',
), ),
'menu' => array( 'menu' => array(
'config' => 'تنظیم', 'config' => 'تنظیم',
@ -263,7 +264,6 @@ $sm_lang = array(
'auto_refresh' => 'رفرش خودکار', 'auto_refresh' => 'رفرش خودکار',
'auto_refresh_description' => 'رفرش خودکار صفحه سرورها.<br><span class="small">زمان 'auto_refresh_description' => 'رفرش خودکار صفحه سرورها.<br><span class="small">زمان
به ثنیه, اگر 0 باشد صفحه رفرش نخواهد شد.</span>', به ثنیه, اگر 0 باشد صفحه رفرش نخواهد شد.</span>',
'seconds' => 'ثانیه',
'test' => 'تست', 'test' => 'تست',
'test_email' => 'یک ایمیل به آدرس تعیین شده در پروفایل شما ارسال 'test_email' => 'یک ایمیل به آدرس تعیین شده در پروفایل شما ارسال
خواهد شد.', خواهد شد.',

View File

@ -244,7 +244,6 @@ $sm_lang = array(
'auto_refresh' => 'Automaattipäivitys', 'auto_refresh' => 'Automaattipäivitys',
'auto_refresh_description' => 'Päivittää automaattisesti palvelimet-sivun.<br><span class="small">Aika 'auto_refresh_description' => 'Päivittää automaattisesti palvelimet-sivun.<br><span class="small">Aika
sekunteina, jos 0, sivu ei päivity automaattisesti.</span>', sekunteina, jos 0, sivu ei päivity automaattisesti.</span>',
'seconds' => 'sekuntia',
'test' => 'Testi', 'test' => 'Testi',
'test_email' => 'Testisähköposti lähetetään profiilisi sähköpostiosoitteeseen.', 'test_email' => 'Testisähköposti lähetetään profiilisi sähköpostiosoitteeseen.',
'test_sms' => 'Testitekstiviesti lähetetään profiilisi numeroon.', 'test_sms' => 'Testitekstiviesti lähetetään profiilisi numeroon.',

View File

@ -361,7 +361,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-rachaîchissement', 'auto_refresh' => 'Auto-rachaîchissement',
'auto_refresh_description' => 'Auto-rachaîchissement de la page serveurs.<br><span class="small">Temps en 'auto_refresh_description' => 'Auto-rachaîchissement de la page serveurs.<br><span class="small">Temps en
secondes. Si 0, la page n\'est pas rafraîchie.</span>', secondes. Si 0, la page n\'est pas rafraîchie.</span>',
'seconds' => 'secondes',
'test' => 'Tester', 'test' => 'Tester',
'test_email' => 'Un email va vous être envoyé à l\'adresse définie dans votre profil utilisateur.', 'test_email' => 'Un email va vous être envoyé à l\'adresse définie dans votre profil utilisateur.',
'test_sms' => 'Un SMS va vous être envoyé au numéro défini dans votre profil utilisateur.', 'test_sms' => 'Un SMS va vous être envoyé au numéro défini dans votre profil utilisateur.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'circa un minuto fa', 'a_minute_ago' => 'circa un minuto fa',
'seconds_ago' => '%d secondi fa', 'seconds_ago' => '%d secondi fa',
'a_second_ago' => 'un secondo fa', 'a_second_ago' => 'un secondo fa',
'seconds' => 'secondi',
), ),
'menu' => array( 'menu' => array(
'config' => 'Configurazione', 'config' => 'Configurazione',
@ -247,7 +248,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-Aggiornamento', 'auto_refresh' => 'Auto-Aggiornamento',
'auto_refresh_description' => 'Auto-Aggiornamento pagina servers.<br><span class="small">Tempo in secondi, se 'auto_refresh_description' => 'Auto-Aggiornamento pagina servers.<br><span class="small">Tempo in secondi, se
impostato a 0 la pagina non si aggiornerà.</span>', impostato a 0 la pagina non si aggiornerà.</span>',
'seconds' => 'secondi',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Un Email verrà inviata all\'indirizzo specificato nel tuo profilo.', 'test_email' => 'Un Email verrà inviata all\'indirizzo specificato nel tuo profilo.',
'test_sms' => 'Un SMS verrà inviato al numero di telefono specificato nel tuo profilo.', 'test_sms' => 'Un SMS verrà inviato al numero di telefono specificato nel tuo profilo.',

View File

@ -345,7 +345,6 @@ $sm_lang = array(
'auto_refresh' => '自動更新', 'auto_refresh' => '自動更新',
'auto_refresh_description' => 'サーバーページを自動更新します。<br><span 'auto_refresh_description' => 'サーバーページを自動更新します。<br><span
class="small">時間を秒で指定し、0に設定すると更新しません。</span>', class="small">時間を秒で指定し、0に設定すると更新しません。</span>',
'seconds' => '秒',
'test' => 'テスト', 'test' => 'テスト',
'test_email' => 'あなたのユーザープロフィールで指定されたアドレスに電子メールが送信されます。', 'test_email' => 'あなたのユーザープロフィールで指定されたアドレスに電子メールが送信されます。',
'test_sms' => 'あなたのユーザープロフィールで指定された電話番号にSMSが送信されます。', 'test_sms' => 'あなたのユーザープロフィールで指定された電話番号にSMSが送信されます。',

View File

@ -81,6 +81,8 @@ $sm_lang = array(
'minutes' => 'minuten', 'minutes' => 'minuten',
'second' => 'seconde', 'second' => 'seconde',
'seconds' => 'seconden', 'seconds' => 'seconden',
'millisecond' => 'milliseconde',
'milliseconds' => 'milliseconden',
'current' => 'huidig', 'current' => 'huidig',
'settings' => 'Instellingen', 'settings' => 'Instellingen',
), ),
@ -110,8 +112,8 @@ $sm_lang = array(
'email' => 'Email', 'email' => 'Email',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'pushover_description' => 'Pushover is een dienst die het gemakkelijk maakt om real-time notificaties te 'pushover_description' => 'Pushover is een dienst die het gemakkelijk maakt om real-time notificaties te
ontvangen. Zie <a href="https://pushover.net/" target="_blank">hun website</a> voor meer ontvangen. Zie <a href="https://pushover.net/" target="_blank">hun website</a> voor
informatie.', meer informatie.',
'pushover_key' => 'Pushover Key', 'pushover_key' => 'Pushover Key',
'pushover_device' => 'Pushover Device', 'pushover_device' => 'Pushover Device',
'pushover_device_description' => 'Apparaat waar de berichten naar toe gaan. Laat leeg voor alle apparaten.', 'pushover_device_description' => 'Apparaat waar de berichten naar toe gaan. Laat leeg voor alle apparaten.',
@ -244,6 +246,7 @@ $sm_lang = array(
), ),
'config' => array( 'config' => array(
'general' => 'Algemeen', 'general' => 'Algemeen',
'site_title' => 'Website titel',
'language' => 'Taal', 'language' => 'Taal',
'show_update' => 'Controleer wekelijks voor updates?', 'show_update' => 'Controleer wekelijks voor updates?',
'email_status' => 'Sta email berichten toe?', 'email_status' => 'Sta email berichten toe?',
@ -264,8 +267,8 @@ $sm_lang = array(
'sms_from' => 'Telefoonnummer afzender', 'sms_from' => 'Telefoonnummer afzender',
'pushover_status' => 'Sta Pushover berichten toe?', 'pushover_status' => 'Sta Pushover berichten toe?',
'pushover_description' => 'Pushover is een dienst die het gemakkelijk maakt om real-time notificaties te 'pushover_description' => 'Pushover is een dienst die het gemakkelijk maakt om real-time notificaties te
ontvangen. Zie <a href="https://pushover.net/" target="_blank">hun website</a> voor meer ontvangen. Zie <a href="https://pushover.net/" target="_blank">hun website</a> voor
informatie.', meer informatie.',
'pushover_clone_app' => 'Klik hier om je Pushover app te maken', 'pushover_clone_app' => 'Klik hier om je Pushover app te maken',
'pushover_api_token' => 'Pushover App API Token', 'pushover_api_token' => 'Pushover App API Token',
'pushover_api_token_description' => 'Voordat je Pushover kunt gebruiken moet je een <a href="%1$s" 'pushover_api_token_description' => 'Voordat je Pushover kunt gebruiken moet je een <a href="%1$s"
@ -308,7 +311,6 @@ $sm_lang = array(
'auto_refresh' => 'Herlaad automatisch', 'auto_refresh' => 'Herlaad automatisch',
'auto_refresh_description' => 'Auto-herladen servers pagina.<br><span class="small">Tijd in seconden, als de 'auto_refresh_description' => 'Auto-herladen servers pagina.<br><span class="small">Tijd in seconden, als de
tijd 0 is wordt de pagina niet ververst.</span>', tijd 0 is wordt de pagina niet ververst.</span>',
'seconds' => 'seconden',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Er zal een email verstuurd worden naar het email adres in je profiel.', 'test_email' => 'Er zal een email verstuurd worden naar het email adres in je profiel.',
'test_sms' => 'Er zal een SMS verstuurd worden naar het telefoonnummer in je profiel.', 'test_sms' => 'Er zal een SMS verstuurd worden naar het telefoonnummer in je profiel.',
@ -336,6 +338,9 @@ $sm_lang = array(
'log_retention_period_description' => 'Aantal dagen dat logs van notificaties en archieven van server uptime 'log_retention_period_description' => 'Aantal dagen dat logs van notificaties en archieven van server uptime
worden bewaard. Vul 0 in om log opruiming uit te zetten.', worden bewaard. Vul 0 in om log opruiming uit te zetten.',
'log_retention_days' => 'dagen', 'log_retention_days' => 'dagen',
'user_agent' => 'User Agent',
'user_agent_key_note' => 'Aangepaste user agent wordt door de monitor gebruikt bij de communicatie met externe
services.',
), ),
'notifications' => array( 'notifications' => array(
'off_sms' => 'Server %LABEL% is DOWN: ip=%IP%, poort=%PORT%. Fout=%ERROR%', 'off_sms' => 'Server %LABEL% is DOWN: ip=%IP%, poort=%PORT%. Fout=%ERROR%',

View File

@ -326,7 +326,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-refresh', 'auto_refresh' => 'Auto-refresh',
'auto_refresh_description' => 'Auto-refresh server side.<br><span class="small">Tid i sekunder, hvis 0 siden 'auto_refresh_description' => 'Auto-refresh server side.<br><span class="small">Tid i sekunder, hvis 0 siden
ikke blir oppdatert.</span>', ikke blir oppdatert.</span>',
'seconds' => 'sekunder',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'En e-post vil bli sendt til adressen spesifisert i brukerprofilen din.', 'test_email' => 'En e-post vil bli sendt til adressen spesifisert i brukerprofilen din.',
'test_sms' => 'En tekstmelding vil bli sendt til telefonnummeret som er angitt i brukerprofilen din.', 'test_sms' => 'En tekstmelding vil bli sendt til telefonnummeret som er angitt i brukerprofilen din.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'minutę temu', 'a_minute_ago' => 'minutę temu',
'seconds_ago' => '%d sekund temu', 'seconds_ago' => '%d sekund temu',
'a_second_ago' => 'sekundę temu', 'a_second_ago' => 'sekundę temu',
'seconds' => 'sekund',
), ),
'menu' => array( 'menu' => array(
'config' => 'Konfiguracja', 'config' => 'Konfiguracja',
@ -191,6 +192,7 @@ $sm_lang = array(
), ),
'config' => array( 'config' => array(
'general' => 'Ogólne', 'general' => 'Ogólne',
'site_title' => 'Tytuł strony',
'language' => 'Język', 'language' => 'Język',
'show_update' => 'Sprawdzić aktualizacje?', 'show_update' => 'Sprawdzić aktualizacje?',
'email_status' => 'Pozwól na wysyłkę email', 'email_status' => 'Pozwól na wysyłkę email',
@ -211,8 +213,8 @@ $sm_lang = array(
'sms_from' => 'Numer nadawcy', 'sms_from' => 'Numer nadawcy',
'pushover_status' => 'Pozwól na wysyłkę notyfikacji Pushover', 'pushover_status' => 'Pozwól na wysyłkę notyfikacji Pushover',
'pushover_description' => 'Pushover jest usługą ułatwiającą otrzymywanie powiadomień w czasie 'pushover_description' => 'Pushover jest usługą ułatwiającą otrzymywanie powiadomień w czasie
rzeczywistym. Sprawdź <a href="https://pushover.net/" target="_blank">ich stronę</a> aby uzyskać rzeczywistym. Sprawdź <a href="https://pushover.net/" target="_blank">ich
więcej informacji.', stronę</a> aby uzyskać więcej informacji.',
'pushover_clone_app' => 'Kliknij tutaj aby stworzyć aplikację korzystającą z Pushover', 'pushover_clone_app' => 'Kliknij tutaj aby stworzyć aplikację korzystającą z Pushover',
'pushover_api_token' => 'Pushover App API Token', 'pushover_api_token' => 'Pushover App API Token',
'pushover_api_token_description' => 'Zanim zaczniesz używać Pushover, musisz <a href="%1$s" target="_blank" 'pushover_api_token_description' => 'Zanim zaczniesz używać Pushover, musisz <a href="%1$s" target="_blank"
@ -247,7 +249,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-odświeżanie', 'auto_refresh' => 'Auto-odświeżanie',
'auto_refresh_description' => 'Auto-odświeżanie strony serwera.<br><span class="small">Czas w sekundach, dla 'auto_refresh_description' => 'Auto-odświeżanie strony serwera.<br><span class="small">Czas w sekundach, dla
czasu 0 strona nie będzie odświeżana.</span>', czasu 0 strona nie będzie odświeżana.</span>',
'seconds' => 'sekund',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Email zostanie wysłany na adres podany w Twoim profilu.', 'test_email' => 'Email zostanie wysłany na adres podany w Twoim profilu.',
'test_sms' => 'SMS zostanie wysłany na numer podany w Twoim profilu.', 'test_sms' => 'SMS zostanie wysłany na numer podany w Twoim profilu.',
@ -272,6 +273,8 @@ $sm_lang = array(
archiwizować uptime serwera. Wpisz 0 aby wyłączyć czyszczenie archiwizować uptime serwera. Wpisz 0 aby wyłączyć czyszczenie
logów.', logów.',
'log_retention_days' => 'dni', 'log_retention_days' => 'dni',
'user_agent' => 'User Agent',
'user_agent_key_note' => 'Nazwa używana przez monitoring do identyfikacji ze sprawdzaną usługą.',
), ),
'notifications' => array( 'notifications' => array(
'off_sms' => 'Serwer \'%LABEL%\' przestał odpowiadać: ip=%IP%, port=%PORT%. Błąd=%ERROR%', 'off_sms' => 'Serwer \'%LABEL%\' przestał odpowiadać: ip=%IP%, port=%PORT%. Błąd=%ERROR%',

View File

@ -66,6 +66,7 @@ $sm_lang = array(
'a_minute_ago' => 'cerca de um minuto atrás', 'a_minute_ago' => 'cerca de um minuto atrás',
'seconds_ago' => '%d segundos atrás', 'seconds_ago' => '%d segundos atrás',
'a_second_ago' => 'um segundo atrás', 'a_second_ago' => 'um segundo atrás',
'seconds' => 'segundos',
), ),
'menu' => array( 'menu' => array(
'config' => 'Configuração', 'config' => 'Configuração',
@ -245,7 +246,6 @@ $sm_lang = array(
'auto_refresh' => 'Atualizar automaticamente', 'auto_refresh' => 'Atualizar automaticamente',
'auto_refresh_description' => 'Atualizar automaticamente a página de servidores.<br><span class="small">Tempo 'auto_refresh_description' => 'Atualizar automaticamente a página de servidores.<br><span class="small">Tempo
em segundos, Se 0 a página não será atualizada.</span>', em segundos, Se 0 a página não será atualizada.</span>',
'seconds' => 'segundos',
'test' => 'Teste', 'test' => 'Teste',
'test_email' => 'Um e-mail será enviado para o endereço especificado em seu perfil de usuário.', 'test_email' => 'Um e-mail será enviado para o endereço especificado em seu perfil de usuário.',
'test_sms' => 'Um SMS será enviado para o número de telefone especificado em seu perfil de usuário.', 'test_sms' => 'Um SMS será enviado para o número de telefone especificado em seu perfil de usuário.',

View File

@ -121,12 +121,12 @@ $sm_lang = array(
пустым, что бы отправлять уведомления на пустым, что бы отправлять уведомления на
все устройства.', все устройства.',
'telegram' => 'Telegram', 'telegram' => 'Telegram',
'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> удобный мессенджер 'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> удобный
для получения уведомлений в реальном мессенджер для получения уведомлений в
времени. Посетите <a реальном времени. Посетите <a
href="http://docs.phpservermonitor.org/" target="_blank">раздел документации</a> href="http://docs.phpservermonitor.org/" target="_blank">раздел
для получения доп. информации и инструкций по документации</a> для получения доп. информации
установке.', и инструкций по установке.',
'telegram_chat_id' => 'Telegram chat id', 'telegram_chat_id' => 'Telegram chat id',
'telegram_chat_id_description' => 'Сообщения будут отправляться на 'telegram_chat_id_description' => 'Сообщения будут отправляться на
указанный идентификатор чата.', указанный идентификатор чата.',
@ -313,12 +313,12 @@ $sm_lang = array(
rel="noopener">"App"</a> на их веб-сайте и ввести "App rel="noopener">"App"</a> на их веб-сайте и ввести "App
API Token" сюда.', API Token" сюда.',
'telegram_status' => 'Разрешить отправку уведомлений в Telegram', 'telegram_status' => 'Разрешить отправку уведомлений в Telegram',
'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> удобный мессенджер 'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> удобный
для получения уведомлений в реальном мессенджер для получения уведомлений в
времени. Посетите <a реальном времени. Посетите <a
href="http://docs.phpservermonitor.org/" target="_blank">раздел документации</a> href="http://docs.phpservermonitor.org/" target="_blank">раздел
для получения доп. информации и инструкций по документации</a> для получения доп. информации
установке.', и инструкций по установке.',
'telegram_api_token' => 'Telegram API Token', 'telegram_api_token' => 'Telegram API Token',
'telegram_api_token_description' => 'Прежде чем вы сможете начать 'telegram_api_token_description' => 'Прежде чем вы сможете начать
пользоваться Telegram, вам необходимо пользоваться Telegram, вам необходимо
@ -371,7 +371,6 @@ $sm_lang = array(
серверов.<br><span class="small">Время в секундах. серверов.<br><span class="small">Время в секундах.
Если указано 0, то страница не будет Если указано 0, то страница не будет
обновляться.</span>', обновляться.</span>',
'seconds' => 'секунд',
'test' => 'Проверка', 'test' => 'Проверка',
'test_email' => 'Сообщение будет отправлено на адрес указаный в 'test_email' => 'Сообщение будет отправлено на адрес указаный в
профиле пользователя.', профиле пользователя.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'cca pred minútou', 'a_minute_ago' => 'cca pred minútou',
'seconds_ago' => 'pred %d sekundami', 'seconds_ago' => 'pred %d sekundami',
'a_second_ago' => 'pred chvíľou', 'a_second_ago' => 'pred chvíľou',
'seconds' => 'sekúnd',
), ),
'menu' => array( 'menu' => array(
'config' => 'Konfigurácia', 'config' => 'Konfigurácia',
@ -259,7 +260,6 @@ $sm_lang = array(
'auto_refresh' => 'Automaticky obnoviť', 'auto_refresh' => 'Automaticky obnoviť',
'auto_refresh_description' => 'Automaticky obnoviť stránku Servery.<br><span class="small">Čas v 'auto_refresh_description' => 'Automaticky obnoviť stránku Servery.<br><span class="small">Čas v
sekundách, 0 pre vypnutie automatického obnovenia.</span>', sekundách, 0 pre vypnutie automatického obnovenia.</span>',
'seconds' => 'sekúnd',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'E-mail bude odoslaný na adresu uvedenú v užívateľskom profile.', 'test_email' => 'E-mail bude odoslaný na adresu uvedenú v užívateľskom profile.',
'test_sms' => 'SMS bude odoslaná na telefónne číslo uvedené v užívateľskom profile.', 'test_sms' => 'SMS bude odoslaná na telefónne číslo uvedené v užívateľskom profile.',

View File

@ -65,6 +65,7 @@ $sm_lang = array(
'a_minute_ago' => 'pred približno minuto', 'a_minute_ago' => 'pred približno minuto',
'seconds_ago' => 'pred %d sekundami', 'seconds_ago' => 'pred %d sekundami',
'a_second_ago' => 'pred sekundo', 'a_second_ago' => 'pred sekundo',
'seconds' => 'sekund',
), ),
'menu' => array( 'menu' => array(
'config' => 'Nastavitve', 'config' => 'Nastavitve',
@ -92,8 +93,8 @@ $sm_lang = array(
'email' => 'E-pošta', 'email' => 'E-pošta',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'pushover_description' => 'Pushover je storitev, ki omogoča enostavno prejemanje obvestil v realnem času. 'pushover_description' => 'Pushover je storitev, ki omogoča enostavno prejemanje obvestil v realnem času.
Več informacij je na voljo <a href="https://pushover.net/" target="_blank">na njihovi spletni Več informacij je na voljo <a href="https://pushover.net/" target="_blank">na
strani</a>.', njihovi spletni strani</a>.',
'pushover_key' => 'Pushover ključ', 'pushover_key' => 'Pushover ključ',
'pushover_device' => 'Pushover naprava', 'pushover_device' => 'Pushover naprava',
'pushover_device_description' => 'Ime naprave na katero naj se pošlje obvestilo. Če želite obvestilo 'pushover_device_description' => 'Ime naprave na katero naj se pošlje obvestilo. Če želite obvestilo
@ -209,8 +210,8 @@ $sm_lang = array(
'sms_from' => 'Telefonska številka pošiljatelja', 'sms_from' => 'Telefonska številka pošiljatelja',
'pushover_status' => 'Dovolim pošiljanje Pushover sporočil', 'pushover_status' => 'Dovolim pošiljanje Pushover sporočil',
'pushover_description' => 'Pushover je storitev, ki omogoča enostavno prejemanje obvestil v realnem času. 'pushover_description' => 'Pushover je storitev, ki omogoča enostavno prejemanje obvestil v realnem času.
Več informacij je na voljo <a href="https://pushover.net/" target="_blank">na njihovi spletni Več informacij je na voljo <a href="https://pushover.net/" target="_blank">na
strani</a>.', njihovi spletni strani</a>.',
'pushover_clone_app' => 'Kliknite za ustvarjanje vaše Pushover aplikacije', 'pushover_clone_app' => 'Kliknite za ustvarjanje vaše Pushover aplikacije',
'pushover_api_token' => 'Pushover API žeton', 'pushover_api_token' => 'Pushover API žeton',
'pushover_api_token_description' => 'Pred uporabo storitve Pushover, morate na njihovi spletni strani <a 'pushover_api_token_description' => 'Pred uporabo storitve Pushover, morate na njihovi spletni strani <a
@ -247,7 +248,6 @@ $sm_lang = array(
'auto_refresh_description' => 'Samodejno posodabljanje pregleda statusa strežnikov.<br><span 'auto_refresh_description' => 'Samodejno posodabljanje pregleda statusa strežnikov.<br><span
class="small">Čas v sekundah. Če je vrednost 0 se stran ne bo samodejno class="small">Čas v sekundah. Če je vrednost 0 se stran ne bo samodejno
posodabljala.</span>', posodabljala.</span>',
'seconds' => 'sekund',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Na naslov, ki ste ga določili v vašem profilu, bo poslano e-sporočilo.', 'test_email' => 'Na naslov, ki ste ga določili v vašem profilu, bo poslano e-sporočilo.',
'test_sms' => 'Na telefonsko številko, ki ste jo določili v vašem profilu, bo poslan SMS.', 'test_sms' => 'Na telefonsko številko, ki ste jo določili v vašem profilu, bo poslan SMS.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'ungefär en minut sen', 'a_minute_ago' => 'ungefär en minut sen',
'seconds_ago' => '%d sekunder sedan', 'seconds_ago' => '%d sekunder sedan',
'a_second_ago' => 'en sekund sedan', 'a_second_ago' => 'en sekund sedan',
'seconds' => 'sekunder',
), ),
'menu' => array( 'menu' => array(
'config' => 'Inställningar', 'config' => 'Inställningar',
@ -94,7 +95,8 @@ $sm_lang = array(
'email' => 'Email', 'email' => 'Email',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'pushover_description' => 'Pushover är en tjänst som skickar meddelande i realtid. Se <a 'pushover_description' => 'Pushover är en tjänst som skickar meddelande i realtid. Se <a
href="https://pushover.net/" target="_blank">deras webbsida</a> för mer information.', href="https://pushover.net/" target="_blank">deras webbsida</a> för mer
information.',
'pushover_key' => 'Pushover Key', 'pushover_key' => 'Pushover Key',
'pushover_device' => 'Pushover Device', 'pushover_device' => 'Pushover Device',
'pushover_device_description' => 'Enhetsnman att skicka meddelande till. Lämna tomt för att skicka till alla 'pushover_device_description' => 'Enhetsnman att skicka meddelande till. Lämna tomt för att skicka till alla
@ -245,7 +247,6 @@ $sm_lang = array(
'auto_refresh' => 'Auto-uppdatera', 'auto_refresh' => 'Auto-uppdatera',
'auto_refresh_description' => 'Auto-uppdatera status-sidan.<br><span class="small">Tid i sekunder, om "0" 'auto_refresh_description' => 'Auto-uppdatera status-sidan.<br><span class="small">Tid i sekunder, om "0"
uppdateras sidan inte automatiskt.</span>', uppdateras sidan inte automatiskt.</span>',
'seconds' => 'sekunder',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Ett emial kommer skickas till adressen i din profil.', 'test_email' => 'Ett emial kommer skickas till adressen i din profil.',
'test_sms' => 'Ett SMS kommer skickas till mobilnumret i din profil.', 'test_sms' => 'Ett SMS kommer skickas till mobilnumret i din profil.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => 'yaklaşık bir dakika önce', 'a_minute_ago' => 'yaklaşık bir dakika önce',
'seconds_ago' => '%d saniye önce', 'seconds_ago' => '%d saniye önce',
'a_second_ago' => 'bir saniye önce', 'a_second_ago' => 'bir saniye önce',
'seconds' => 'saniye',
), ),
'menu' => array( 'menu' => array(
'config' => 'Ayarlar', 'config' => 'Ayarlar',
@ -248,7 +249,6 @@ $sm_lang = array(
'auto_refresh' => 'Otomatik Yenileme', 'auto_refresh' => 'Otomatik Yenileme',
'auto_refresh_description' => 'Otomatik yenileme sunucu sayfası<br><span class="small">Eğer sayfa yenilenmez 'auto_refresh_description' => 'Otomatik yenileme sunucu sayfası<br><span class="small">Eğer sayfa yenilenmez
ise.</span>', ise.</span>',
'seconds' => 'saniye',
'test' => 'Test', 'test' => 'Test',
'test_email' => 'Profilinizde tanımladığınız e-posta adresinize bir e-posta gönderilecek.', 'test_email' => 'Profilinizde tanımladığınız e-posta adresinize bir e-posta gönderilecek.',
'test_sms' => 'Profilinizde tanımladığınız numaranıza bir SMS mesajı gönderilecek.', 'test_sms' => 'Profilinizde tanımladığınız numaranıza bir SMS mesajı gönderilecek.',

View File

@ -124,11 +124,12 @@ $sm_lang = array(
повідомлення. Залиште пустим, щоб повідомлення. Залиште пустим, щоб
надсилати на всі пристрої.', надсилати на всі пристрої.',
'telegram' => 'Telegram', 'telegram' => 'Telegram',
'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> чат-застосунок, що 'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a>
дозволяє легко отримувати сповіщення у чат-застосунок, що дозволяє легко отримувати
реальному часі. За деталями й інструкцією зі сповіщення у реальному часі. За деталями й
встановлення зверніться до <a інструкцією зі встановлення зверніться до <a
href="http://docs.phpservermonitor.org/" target="_blank">документації</a>.', href="http://docs.phpservermonitor.org/"
target="_blank">документації</a>.',
'telegram_chat_id' => 'Ідентифікатор чату Telegram', 'telegram_chat_id' => 'Ідентифікатор чату Telegram',
'telegram_chat_id_description' => 'Повідомлення буде надіслане у 'telegram_chat_id_description' => 'Повідомлення буде надіслане у
відповідний чат.', відповідний чат.',
@ -330,8 +331,8 @@ $sm_lang = array(
'pushover_status' => 'Дозволити надсилання Pushover-повідомлень', 'pushover_status' => 'Дозволити надсилання Pushover-повідомлень',
'pushover_description' => 'Pushover сервіс, що дозволяє легко отримувати 'pushover_description' => 'Pushover сервіс, що дозволяє легко отримувати
сповіщення у реальному часі. За детальнішою сповіщення у реальному часі. За детальнішою
інформацію перейдіть на <a інформацію перейдіть на <a href="https://pushover.net/"
href="https://pushover.net/" target="_blank">їхній вебсайт</a>.', target="_blank">їхній вебсайт</a>.',
'pushover_clone_app' => 'Натисніть тут, щоб створити ваш Pushover-додаток', 'pushover_clone_app' => 'Натисніть тут, щоб створити ваш Pushover-додаток',
'pushover_api_token' => 'Токен API Pushover-додатку', 'pushover_api_token' => 'Токен API Pushover-додатку',
'pushover_api_token_description' => 'Перед використанням Pushover ви маєте <a 'pushover_api_token_description' => 'Перед використанням Pushover ви маєте <a
@ -339,16 +340,17 @@ $sm_lang = array(
Додаток</a> на їхньому вебсайті та ввести Додаток</a> на їхньому вебсайті та ввести
токен API Додатку тут.', токен API Додатку тут.',
'telegram_status' => 'Дозволити надсилання Telegram-повідомлень', 'telegram_status' => 'Дозволити надсилання Telegram-повідомлень',
'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a> чат-застосунок, що 'telegram_description' => '<a href="https://telegram.org/" target="_blank">Telegram</a>
дозволяє легко отримувати сповіщення у чат-застосунок, що дозволяє легко отримувати
реальному часі. Детальніша інформація та сповіщення у реальному часі. Детальніша
інструкція зі встановлення доступні у <a інформація та інструкція зі встановлення
href="http://docs.phpservermonitor.org/" target="_blank">документації</a>.', доступні у <a href="http://docs.phpservermonitor.org/"
target="_blank">документації</a>.',
'telegram_api_token' => 'Токен Telegram API', 'telegram_api_token' => 'Токен Telegram API',
'telegram_api_token_description' => 'Перед використанням Telegram ви маєте 'telegram_api_token_description' => 'Перед використанням Telegram ви маєте
отримати токен API. За довідкою отримати токен API. За довідкою
зверніться до <a зверніться до <a href="http://docs.phpservermonitor.org/"
href="http://docs.phpservermonitor.org/" target="_blank">документації</a>.', target="_blank">документації</a>.',
'alert_type' => 'Виберіть, коли б вам хотілося отримувати 'alert_type' => 'Виберіть, коли б вам хотілося отримувати
сповіщення.', сповіщення.',
'alert_type_description' => '<b>Зміна статусу:</b> Ви отримуватимете 'alert_type_description' => '<b>Зміна статусу:</b> Ви отримуватимете
@ -404,7 +406,6 @@ $sm_lang = array(
'auto_refresh_description' => 'Сторінка автооновлення серверів.<br><span 'auto_refresh_description' => 'Сторінка автооновлення серверів.<br><span
class="small">Час у секундах; якщо 0, сторінка не class="small">Час у секундах; якщо 0, сторінка не
оновлюватиметься.</span>', оновлюватиметься.</span>',
'seconds' => 'секунд',
'test' => 'Тест', 'test' => 'Тест',
'test_email' => 'Електронний лист буде надісланий на адресу, 'test_email' => 'Електронний лист буде надісланий на адресу,
вказану у вашому профілі користувача.', вказану у вашому профілі користувача.',

View File

@ -64,6 +64,7 @@ $sm_lang = array(
'a_minute_ago' => 'khoảng một phút trước', 'a_minute_ago' => 'khoảng một phút trước',
'seconds_ago' => '%d giây trước', 'seconds_ago' => '%d giây trước',
'a_second_ago' => 'một giây trước', 'a_second_ago' => 'một giây trước',
'seconds' => 'giây',
), ),
'menu' => array( 'menu' => array(
'config' => 'Cấu hình', 'config' => 'Cấu hình',
@ -91,8 +92,8 @@ $sm_lang = array(
'email' => 'Email', 'email' => 'Email',
'pushover' => 'Pushover', 'pushover' => 'Pushover',
'pushover_description' => 'Pushover một dịch vụ dễ dàng nhận các thông báo theo thời gian 'pushover_description' => 'Pushover một dịch vụ dễ dàng nhận các thông báo theo thời gian
thực. Xem <a href="https://pushover.net/" target="_blank">website của họ</a> để biết thực. Xem <a href="https://pushover.net/" target="_blank">website của họ</a>
thêm thông tin.', để biết thêm thông tin.',
'pushover_key' => 'Pushover Key', 'pushover_key' => 'Pushover Key',
'pushover_device' => 'Pushover Device', 'pushover_device' => 'Pushover Device',
'pushover_device_description' => 'Tên thiết bị để gửi tin nhắn đến. Để trống để gửi 'pushover_device_description' => 'Tên thiết bị để gửi tin nhắn đến. Để trống để gửi
@ -208,8 +209,8 @@ $sm_lang = array(
'sms_from' => 'Số điện thoại của người gửi', 'sms_from' => 'Số điện thoại của người gửi',
'pushover_status' => 'Cho phép gửi tin nhắn bằng Pushover', 'pushover_status' => 'Cho phép gửi tin nhắn bằng Pushover',
'pushover_description' => 'Pushover một dịch vụ dễ dàng nhận các thông báo theo thời gian 'pushover_description' => 'Pushover một dịch vụ dễ dàng nhận các thông báo theo thời gian
thực. Xem <a href="https://pushover.net/" target="_blank">website của họ</a> để biết thực. Xem <a href="https://pushover.net/" target="_blank">website của họ</a>
thêm thông tin.', để biết thêm thông tin.',
'pushover_clone_app' => 'Nhấn vào đây để tạo ứng dụng Pushover của bạn', 'pushover_clone_app' => 'Nhấn vào đây để tạo ứng dụng Pushover của bạn',
'pushover_api_token' => 'Pushover App API Token', 'pushover_api_token' => 'Pushover App API Token',
'pushover_api_token_description' => 'Trước khi bạn thể sử dụng Pushover, bạn cần phải <a 'pushover_api_token_description' => 'Trước khi bạn thể sử dụng Pushover, bạn cần phải <a
@ -246,7 +247,6 @@ $sm_lang = array(
'auto_refresh' => 'Tự động làm mới', 'auto_refresh' => 'Tự động làm mới',
'auto_refresh_description' => 'Tự động làm mới servers page.<br><span class="small">Trong vài giây, 'auto_refresh_description' => 'Tự động làm mới servers page.<br><span class="small">Trong vài giây,
nếu 0 trang sẽ không làm mới.</span>', nếu 0 trang sẽ không làm mới.</span>',
'seconds' => 'giây',
'test' => 'Thử', 'test' => 'Thử',
'test_email' => 'Một email sẽ được gửi đến địa chỉ được xác định trong hồ 'test_email' => 'Một email sẽ được gửi đến địa chỉ được xác định trong hồ
người dùng của bạn.', người dùng của bạn.',

View File

@ -67,6 +67,7 @@ $sm_lang = array(
'a_minute_ago' => '1分钟前', 'a_minute_ago' => '1分钟前',
'seconds_ago' => '%d 秒前', 'seconds_ago' => '%d 秒前',
'a_second_ago' => '刚刚', 'a_second_ago' => '刚刚',
'seconds' => '秒',
), ),
'menu' => array( 'menu' => array(
'config' => '设置', 'config' => '设置',
@ -259,7 +260,6 @@ $sm_lang = array(
'auto_refresh' => '自动刷新', 'auto_refresh' => '自动刷新',
'auto_refresh_description' => '自动刷新服务器页.<br><span class="small">单位为秒, 设置为 0 'auto_refresh_description' => '自动刷新服务器页.<br><span class="small">单位为秒, 设置为 0
则不自动刷新.</span>', 则不自动刷新.</span>',
'seconds' => '秒',
'test' => '测试', 'test' => '测试',
'test_email' => '将发送一封邮件到您账户设置的邮件地址.', 'test_email' => '将发送一封邮件到您账户设置的邮件地址.',
'test_sms' => '将发送一封短信到您账户设置的手机号码.', 'test_sms' => '将发送一封短信到您账户设置的手机号码.',

View File

@ -258,7 +258,8 @@ $sm_lang = array(
'sms_from' => '發送人電話號碼', 'sms_from' => '發送人電話號碼',
'pushover_status' => '啟用Pushover通知', 'pushover_status' => '啟用Pushover通知',
'pushover_description' => 'Pushover是線上服務讓您可以方便的收到即時通知請參考 <a 'pushover_description' => 'Pushover是線上服務讓您可以方便的收到即時通知請參考 <a
href="https://pushover.net/" target="_blank"> 網站</a> 可以得到更詳細的資訊。</a> ', href="https://pushover.net/" target="_blank"> 網站</a>
可以得到更詳細的資訊。</a> ',
'pushover_clone_app' => '點選這裡可快速建立Pushover App', 'pushover_clone_app' => '點選這裡可快速建立Pushover App',
'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡-><a href="%1$s" 'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡-><a href="%1$s"
target="_blank" rel="noopener">註冊Pushover App帳號</a> target="_blank" rel="noopener">註冊Pushover App帳號</a>
@ -269,7 +270,8 @@ $sm_lang = array(
<a href="http://docs.phpservermonitor.org/" target="_blank">文件庫</a> <a href="http://docs.phpservermonitor.org/" target="_blank">文件庫</a>
可以取得更多資訊與安裝說明。', 可以取得更多資訊與安裝說明。',
'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 <a 'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 <a
href="http://docs.phpservermonitor.org/" target="_blank">文件庫</a> 取得說明。', href="http://docs.phpservermonitor.org/" target="_blank">文件庫</a>
取得說明。',
'alert_type' => '需要提醒的類別', 'alert_type' => '需要提醒的類別',
'alert_type_description' => '<b>狀態改變:</b> 伺服器 連線 -> 離線或連線 -> 'alert_type_description' => '<b>狀態改變:</b> 伺服器 連線 -> 離線或連線 ->
連線的狀態變化將會收到提醒通知。<br/><br /><b>離線:</b> 連線的狀態變化將會收到提醒通知。<br/><br /><b>離線:</b>
@ -298,7 +300,6 @@ $sm_lang = array(
'settings_log' => '記錄設定', 'settings_log' => '記錄設定',
'settings_proxy' => 'Proxy 設定', 'settings_proxy' => 'Proxy 設定',
'auto_refresh' => '自動更新', 'auto_refresh' => '自動更新',
'seconds' => '秒',
'test' => '測試', 'test' => '測試',
'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。', 'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。',
'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。', 'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。',

View File

@ -217,7 +217,7 @@ abstract class AbstractController implements ControllerInterface
if (!$this->xhr) { if (!$this->xhr) {
// in XHR mode, we will not add the main template // in XHR mode, we will not add the main template
$tpl_data = array( $tpl_data = array(
'title' => strtoupper(psm_get_lang('system', 'title')), 'title' => psm_get_conf('site_title', strtoupper(psm_get_lang('system', 'title'))),
'label_back_to_top' => psm_get_lang('system', 'back_to_top'), 'label_back_to_top' => psm_get_lang('system', 'back_to_top'),
'add_footer' => $this->add_footer, 'add_footer' => $this->add_footer,
'version' => 'v' . PSM_VERSION, 'version' => 'v' . PSM_VERSION,

View File

@ -44,12 +44,14 @@ class ConfigController extends AbstractController
'email_smtp', 'email_smtp',
'sms_status', 'sms_status',
'pushover_status', 'pushover_status',
'webhook_status',
'telegram_status', 'telegram_status',
'jabber_status', 'jabber_status',
'log_status', 'log_status',
'log_email', 'log_email',
'log_sms', 'log_sms',
'log_pushover', 'log_pushover',
'log_webhook',
'log_telegram', 'log_telegram',
'log_jabber', 'log_jabber',
'show_update', 'show_update',
@ -72,12 +74,16 @@ class ConfigController extends AbstractController
'sms_gateway_username', 'sms_gateway_username',
'sms_gateway_password', 'sms_gateway_password',
'sms_from', 'sms_from',
'webhook_url',
'webhook_json',
'pushover_api_token', 'pushover_api_token',
'telegram_api_token', 'telegram_api_token',
'jabber_host', 'jabber_host',
'jabber_port', 'jabber_port',
'jabber_username', 'jabber_username',
'jabber_domain' 'jabber_domain',
'user_agent',
'site_title'
); );
/** /**
@ -86,7 +92,7 @@ class ConfigController extends AbstractController
*/ */
protected $encryptedFields = [ protected $encryptedFields = [
'email_smtp_password', 'email_smtp_password',
'jabber_password' 'jabber_password'
]; ];
private $default_tab = 'general'; private $default_tab = 'general';
@ -191,6 +197,14 @@ class ConfigController extends AbstractController
foreach ($this->fields as $input_key) { foreach ($this->fields as $input_key) {
$tpl_data[$input_key] = (isset($config[$input_key])) ? $config[$input_key] : ''; $tpl_data[$input_key] = (isset($config[$input_key])) ? $config[$input_key] : '';
} }
$tpl_data['user_agent'] = empty($tpl_data['user_agent']) ?
'Mozilla/5.0 (compatible; phpservermon/' .
PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)' : $tpl_data['user_agent'];
$tpl_data['site_title'] = empty($tpl_data['site_title']) ?
strtoupper(psm_get_lang('system', 'title')) : $tpl_data['site_title'];
// encrypted fields // encrypted fields
foreach ($this->encryptedFields as $encryptedField) { foreach ($this->encryptedFields as $encryptedField) {
$tpl_data[$encryptedField] = ''; $tpl_data[$encryptedField] = '';
@ -198,7 +212,7 @@ class ConfigController extends AbstractController
$tpl_data[$this->default_tab . '_active'] = 'active'; $tpl_data[$this->default_tab . '_active'] = 'active';
$testmodals = array('email', 'sms', 'pushover', 'telegram', 'jabber'); $testmodals = array('email', 'sms', 'pushover','webhook', 'telegram', 'jabber');
foreach ($testmodals as $modal_id) { foreach ($testmodals as $modal_id) {
$modal = new \psm\Util\Module\Modal( $modal = new \psm\Util\Module\Modal(
$this->twig, $this->twig,
@ -221,9 +235,10 @@ class ConfigController extends AbstractController
protected function executeSave() protected function executeSave()
{ {
if (!empty($_POST)) { if (!empty($_POST)) {
// save new config // save new config
$clean = array( $clean = array(
'language' => $_POST['language'], 'language' => $_POST['language'],
'site_title' => $_POST['site_title'],
'sms_gateway' => $_POST['sms_gateway'], 'sms_gateway' => $_POST['sms_gateway'],
'alert_type' => $_POST['alert_type'], 'alert_type' => $_POST['alert_type'],
'email_smtp_security' => 'email_smtp_security' =>
@ -234,7 +249,7 @@ class ConfigController extends AbstractController
'log_retention_period' => intval(psm_POST('log_retention_period', 365)), 'log_retention_period' => intval(psm_POST('log_retention_period', 365)),
'password_encrypt_key' => psm_POST('password_encrypt_key', sha1(microtime())) 'password_encrypt_key' => psm_POST('password_encrypt_key', sha1(microtime()))
); );
foreach ($this->checkboxes as $input_key) { foreach ($this->checkboxes as $input_key) {
$clean[$input_key] = (isset($_POST[$input_key])) ? '1' : '0'; $clean[$input_key] = (isset($_POST[$input_key])) ? '1' : '0';
} }
foreach ($this->fields as $input_key) { foreach ($this->fields as $input_key) {
@ -261,10 +276,12 @@ class ConfigController extends AbstractController
$this->testSMS(); $this->testSMS();
} elseif (!empty($_POST['test_pushover'])) { } elseif (!empty($_POST['test_pushover'])) {
$this->testPushover(); $this->testPushover();
}elseif (!empty($_POST['test_webhook'])) {
$this->testWebhook();
} elseif (!empty($_POST['test_telegram'])) { } elseif (!empty($_POST['test_telegram'])) {
$this->testTelegram(); $this->testTelegram();
} elseif (!empty($_POST['test_jabber'])) { } elseif (!empty($_POST['test_jabber'])) {
$this->testJabber(); $this->testJabber();
} }
if ($language_refresh) { if ($language_refresh) {
@ -280,10 +297,12 @@ class ConfigController extends AbstractController
$this->default_tab = 'sms'; $this->default_tab = 'sms';
} elseif (isset($_POST['pushover_submit']) || !empty($_POST['test_pushover'])) { } elseif (isset($_POST['pushover_submit']) || !empty($_POST['test_pushover'])) {
$this->default_tab = 'pushover'; $this->default_tab = 'pushover';
} elseif (isset($_POST['webhook_submit']) || !empty($_POST['test_webhook'])) {
$this->default_tab = 'webhook';
} elseif (isset($_POST['telegram_submit']) || !empty($_POST['test_telegram'])) { } elseif (isset($_POST['telegram_submit']) || !empty($_POST['test_telegram'])) {
$this->default_tab = 'telegram'; $this->default_tab = 'telegram';
} elseif (isset($_POST['jabber_submit']) || !empty($_POST['test_jabber'])) { } elseif (isset($_POST['jabber_submit']) || !empty($_POST['test_jabber'])) {
$this->default_tab = 'jabber'; $this->default_tab = 'jabber';
} }
} }
return $this->runAction('index'); return $this->runAction('index');
@ -335,6 +354,34 @@ class ConfigController extends AbstractController
} }
} }
/**
* Execute webhook test
*
* @todo move test to separate class
*/
protected function testWebhook()
{
$user = $this->getUser()->getUser();
if (empty($user->webhook_url)) {
$this->addMessage(psm_get_lang('config', 'webhook_error_nourl'), 'error');
} elseif (empty($user->webhook_json)) {
$this->addMessage(psm_get_lang('config', 'webhook_error_nojson'), 'error');
} else {
$webhook = psm_build_webhook();
$webhook->setUrl($user->webhook_url);
$webhook->setJson($user->webhook_json);
$message = (psm_get_lang('config', 'test_message'));
$result = $webhook->sendWebhook($message);
if ($result==1) {
$this->addMessage(psm_get_lang('config', 'webhook_sent'), 'success');
} else {
$this->addMessage(sprintf(psm_get_lang('config', 'webhook_error'), $result), 'error');
}
}
}
/** /**
* Execute pushover test * Execute pushover test
* *
@ -408,24 +455,24 @@ class ConfigController extends AbstractController
} }
} }
/** /**
* Test Jabber. * Test Jabber.
*/ */
protected function testJabber() protected function testJabber()
{ {
$user = $this->getUser()->getUser(); $user = $this->getUser()->getUser();
psm_jabber_send_message( psm_jabber_send_message(
psm_get_conf('jabber_host'), psm_get_conf('jabber_host'),
psm_get_conf('jabber_username'), psm_get_conf('jabber_username'),
psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')),
[$user->jabber], [$user->jabber],
psm_get_lang('config', 'test_message'), psm_get_lang('config', 'test_message'),
(trim(psm_get_conf('jabber_port')) !== '' ? (int)psm_get_conf('jabber_port') : null), (trim(psm_get_conf('jabber_port')) !== '' ? (int)psm_get_conf('jabber_port') : null),
(trim(psm_get_conf('jabber_domain')) !== '' ? psm_get_conf('jabber_domain') : null) (trim(psm_get_conf('jabber_domain')) !== '' ? psm_get_conf('jabber_domain') : null)
); );
// no message - async ... so just info // no message - async ... so just info
$this->addMessage(psm_get_lang('config', 'jabber_check'), 'info'); $this->addMessage(psm_get_lang('config', 'jabber_check'), 'info');
// @todo possible to set message via ajax with callback ... // @todo possible to set message via ajax with callback ...
} }
protected function getLabels() protected function getLabels()
@ -434,13 +481,15 @@ class ConfigController extends AbstractController
'label_tab_email' => psm_get_lang('config', 'tab_email'), 'label_tab_email' => psm_get_lang('config', 'tab_email'),
'label_tab_sms' => psm_get_lang('config', 'tab_sms'), 'label_tab_sms' => psm_get_lang('config', 'tab_sms'),
'label_tab_pushover' => psm_get_lang('config', 'tab_pushover'), 'label_tab_pushover' => psm_get_lang('config', 'tab_pushover'),
'label_tab_webhook' => psm_get_lang('config', 'tab_webhook'),
'label_tab_telegram' => psm_get_lang('config', 'tab_telegram'), 'label_tab_telegram' => psm_get_lang('config', 'tab_telegram'),
'label_tab_jabber' => psm_get_lang('config', 'tab_jabber'), 'label_tab_jabber' => psm_get_lang('config', 'tab_jabber'),
'label_settings_email' => psm_get_lang('config', 'settings_email'), 'label_settings_email' => psm_get_lang('config', 'settings_email'),
'label_settings_sms' => psm_get_lang('config', 'settings_sms'), 'label_settings_sms' => psm_get_lang('config', 'settings_sms'),
'label_settings_webhook' => psm_get_lang('config', 'settings_webhook'),
'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'), 'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'),
'label_settings_telegram' => psm_get_lang('config', 'settings_telegram'), 'label_settings_telegram' => psm_get_lang('config', 'settings_telegram'),
'label_settings_jabber' => psm_get_lang('config', 'settings_jabber'), 'label_settings_jabber' => psm_get_lang('config', 'settings_jabber'),
'label_settings_notification' => psm_get_lang('config', 'settings_notification'), 'label_settings_notification' => psm_get_lang('config', 'settings_notification'),
'label_settings_log' => psm_get_lang('config', 'settings_log'), 'label_settings_log' => psm_get_lang('config', 'settings_log'),
'label_settings_proxy' => psm_get_lang('config', 'settings_proxy'), 'label_settings_proxy' => psm_get_lang('config', 'settings_proxy'),
@ -468,6 +517,12 @@ class ConfigController extends AbstractController
'label_sms_gateway_username' => psm_get_lang('config', 'sms_gateway_username'), 'label_sms_gateway_username' => psm_get_lang('config', 'sms_gateway_username'),
'label_sms_gateway_password' => psm_get_lang('config', 'sms_gateway_password'), 'label_sms_gateway_password' => psm_get_lang('config', 'sms_gateway_password'),
'label_sms_from' => psm_get_lang('config', 'sms_from'), 'label_sms_from' => psm_get_lang('config', 'sms_from'),
'label_webhook_description' => psm_get_lang('config', 'webhook_description'),
'label_webhook_status' => psm_get_lang('config', 'webhook_status'),
'label_webhook_url' => psm_get_lang('config', 'webhook_url'),
'label_webhook_url_description' => psm_get_lang('config', 'webhook_url_description'),
'label_webhook_json' => psm_get_lang('config', 'webhook_json'),
'label_webhook_json_description' => psm_get_lang('config', 'webhook_json_description'),
'label_pushover_description' => psm_get_lang('config', 'pushover_description'), 'label_pushover_description' => psm_get_lang('config', 'pushover_description'),
'label_pushover_status' => psm_get_lang('config', 'pushover_status'), 'label_pushover_status' => psm_get_lang('config', 'pushover_status'),
'label_pushover_clone_app' => psm_get_lang('config', 'pushover_clone_app'), 'label_pushover_clone_app' => psm_get_lang('config', 'pushover_clone_app'),
@ -482,17 +537,17 @@ class ConfigController extends AbstractController
'label_telegram_api_token' => psm_get_lang('config', 'telegram_api_token'), 'label_telegram_api_token' => psm_get_lang('config', 'telegram_api_token'),
'label_telegram_api_token_description' => psm_get_lang('config', 'telegram_api_token_description'), 'label_telegram_api_token_description' => psm_get_lang('config', 'telegram_api_token_description'),
'label_jabber_status' => psm_get_lang('config', 'jabber_status'), 'label_jabber_status' => psm_get_lang('config', 'jabber_status'),
'label_jabber_description' => psm_get_lang('config', 'jabber_description'), 'label_jabber_description' => psm_get_lang('config', 'jabber_description'),
'label_jabber_host' => psm_get_lang('config', 'jabber_host'), 'label_jabber_host' => psm_get_lang('config', 'jabber_host'),
'label_jabber_host_description' => psm_get_lang('config', 'jabber_host_description'), 'label_jabber_host_description' => psm_get_lang('config', 'jabber_host_description'),
'label_jabber_port' => psm_get_lang('config', 'jabber_port'), 'label_jabber_port' => psm_get_lang('config', 'jabber_port'),
'label_jabber_port_description' => psm_get_lang('config', 'jabber_port_description'), 'label_jabber_port_description' => psm_get_lang('config', 'jabber_port_description'),
'label_jabber_username' => psm_get_lang('config', 'jabber_username'), 'label_jabber_username' => psm_get_lang('config', 'jabber_username'),
'label_jabber_username_description' => psm_get_lang('config', 'jabber_username_description'), 'label_jabber_username_description' => psm_get_lang('config', 'jabber_username_description'),
'label_jabber_domain' => psm_get_lang('config', 'jabber_domain'), 'label_jabber_domain' => psm_get_lang('config', 'jabber_domain'),
'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'), 'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'),
'label_jabber_password' => psm_get_lang('config', 'jabber_password'), 'label_jabber_password' => psm_get_lang('config', 'jabber_password'),
'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'), 'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'),
'label_alert_type' => psm_get_lang('config', 'alert_type'), 'label_alert_type' => psm_get_lang('config', 'alert_type'),
'label_alert_type_description' => psm_get_lang('config', 'alert_type_description'), 'label_alert_type_description' => psm_get_lang('config', 'alert_type_description'),
'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'), 'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'),
@ -502,13 +557,14 @@ class ConfigController extends AbstractController
'label_log_email' => psm_get_lang('config', 'log_email'), 'label_log_email' => psm_get_lang('config', 'log_email'),
'label_log_sms' => psm_get_lang('config', 'log_sms'), 'label_log_sms' => psm_get_lang('config', 'log_sms'),
'label_log_pushover' => psm_get_lang('config', 'log_pushover'), 'label_log_pushover' => psm_get_lang('config', 'log_pushover'),
'label_log_webhook' => psm_get_lang('config', 'log_webhook'),
'label_log_telegram' => psm_get_lang('config', 'log_telegram'), 'label_log_telegram' => psm_get_lang('config', 'log_telegram'),
'label_log_jabber' => psm_get_lang('config', 'log_jabber'), 'label_log_jabber' => psm_get_lang('config', 'log_jabber'),
'label_alert_proxy' => psm_get_lang('config', 'alert_proxy'), 'label_alert_proxy' => psm_get_lang('config', 'alert_proxy'),
'label_alert_proxy_url' => psm_get_lang('config', 'alert_proxy_url'), 'label_alert_proxy_url' => psm_get_lang('config', 'alert_proxy_url'),
'label_auto_refresh' => psm_get_lang('config', 'auto_refresh'), 'label_auto_refresh' => psm_get_lang('config', 'auto_refresh'),
'label_auto_refresh_description' => psm_get_lang('config', 'auto_refresh_description'), 'label_auto_refresh_description' => psm_get_lang('config', 'auto_refresh_description'),
'label_seconds' => psm_get_lang('config', 'seconds'), 'label_seconds' => psm_get_lang('system', 'seconds'),
'label_save' => psm_get_lang('system', 'save'), 'label_save' => psm_get_lang('system', 'save'),
'label_test' => psm_get_lang('config', 'test'), 'label_test' => psm_get_lang('config', 'test'),
'label_log_retention_period' => psm_get_lang('config', 'log_retention_period'), 'label_log_retention_period' => psm_get_lang('config', 'log_retention_period'),
@ -516,7 +572,9 @@ class ConfigController extends AbstractController
'label_log_retention_days' => psm_get_lang('config', 'log_retention_days'), 'label_log_retention_days' => psm_get_lang('config', 'log_retention_days'),
'label_days' => psm_get_lang('config', 'log_retention_days'), 'label_days' => psm_get_lang('config', 'log_retention_days'),
'label_leave_blank' => psm_get_lang('users', 'password_leave_blank'), 'label_leave_blank' => psm_get_lang('users', 'password_leave_blank'),
'label_user_agent' => psm_get_lang('config', 'user_agent'),
'label_user_agent_key_note' => psm_get_lang('config', 'user_agent_key_note'),
'label_site_title' => psm_get_lang('config', 'site_title'),
); );
} }
} }

View File

@ -75,11 +75,11 @@ class InstallController extends AbstractController
$phpv = phpversion(); $phpv = phpversion();
if ( if (
version_compare($phpv, '5.6.0', '<') || version_compare($phpv, '5.5.9', '<') ||
(version_compare($phpv, '7.0.8', '<') && version_compare($phpv, '7.0.0', '>=')) (version_compare($phpv, '7.0.8', '<') && version_compare($phpv, '7.0.0', '>='))
) { ) {
$errors++; $errors++;
$this->addMessage('PHP 5.6.0+ or 7.0.8+ is required to run PHP Server Monitor. You\'re using ' . $this->addMessage('PHP 5.5.9+ or 7.0.8+ is required to run PHP Server Monitor. You\'re using ' .
$phpv . '.', 'error'); $phpv . '.', 'error');
} else { } else {
$this->addMessage('PHP version: ' . $phpv, 'success'); $this->addMessage('PHP version: ' . $phpv, 'success');
@ -101,6 +101,53 @@ class InstallController extends AbstractController
if (!in_array('mysql', \PDO::getAvailableDrivers())) { if (!in_array('mysql', \PDO::getAvailableDrivers())) {
$errors++; $errors++;
$this->addMessage('The PDO MySQL driver needs to be installed.', 'error'); $this->addMessage('The PDO MySQL driver needs to be installed.', 'error');
} else {
$this->addMessage('PHP PDO MySQL driver found', 'success');
}
if (!extension_loaded('filter')) {
$this->addMessage('PHP is installed without the filter module. Please install filter.', 'warning');
} else {
$this->addMessage('PHP filter module found', 'success');
}
if (!extension_loaded('ctype')) {
$this->addMessage('PHP is installed without the ctype module. Please install ctype.', 'warning');
} else {
$this->addMessage('PHP ctype module found', 'success');
}
if (!extension_loaded('hash')) {
$this->addMessage('PHP is installed without the hash module. Please install hash.', 'warning');
} else {
$this->addMessage('PHP hash module found', 'success');
}
if (!extension_loaded('json')) {
$this->addMessage('PHP is installed without the json module. Please install json.', 'warning');
} else {
$this->addMessage('PHP json module found', 'success');
}
if (!extension_loaded('libxml')) {
$this->addMessage('PHP is installed without the libxml module. Please install libxml.', 'warning');
} else {
$this->addMessage('PHP libxml module found', 'success');
}
if (!extension_loaded('openssl')) {
$this->addMessage('PHP is installed without the openssl module. Please install openssl.', 'warning');
} else {
$this->addMessage('PHP openssl module found', 'success');
}
if (!extension_loaded('pcre')) {
$this->addMessage('PHP is installed without the pcre module. Please install pcre.', 'warning');
} else {
$this->addMessage('PHP pcre module found', 'success');
}
if (!extension_loaded('sockets')) {
$this->addMessage('PHP is installed without the sockets module. Please install sockets.', 'warning');
} else {
$this->addMessage('PHP sockets module found', 'success');
}
if (!extension_loaded('xml')) {
$this->addMessage('PHP is installed without the xml module. Please install xml.', 'warning');
} else {
$this->addMessage('PHP xml module found', 'success');
} }
if (!ini_get('date.timezone')) { if (!ini_get('date.timezone')) {
$this->addMessage( $this->addMessage(
@ -256,8 +303,10 @@ class InstallController extends AbstractController
'level' => PSM_USER_ADMIN, 'level' => PSM_USER_ADMIN,
'pushover_key' => '', 'pushover_key' => '',
'pushover_device' => '', 'pushover_device' => '',
'webhook_url' => '',
'webhook_json' => '',
'telegram_id' => '', 'telegram_id' => '',
'jabber' => '' 'jabber' => ''
); );
$validator = $this->container->get('util.user.validator'); $validator = $this->container->get('util.user.validator');

View File

@ -81,6 +81,7 @@ abstract class AbstractServerController extends AbstractController
`s`.`active`, `s`.`active`,
`s`.`email`, `s`.`email`,
`s`.`sms`, `s`.`sms`,
`s`.`webhook`,
`s`.`pushover`, `s`.`pushover`,
`s`.`telegram`, `s`.`telegram`,
`s`.`jabber`, `s`.`jabber`,
@ -114,7 +115,7 @@ abstract class AbstractServerController extends AbstractController
*/ */
protected function formatServer($server) protected function formatServer($server)
{ {
$server['rtime'] = round((float) $server['rtime'], 4); $server['rtime'] = $server['rtime'];
$server['last_online'] = psm_timespan($server['last_online']); $server['last_online'] = psm_timespan($server['last_online']);
$server['last_offline'] = psm_timespan($server['last_offline']); $server['last_offline'] = psm_timespan($server['last_offline']);
if ($server['last_offline'] != psm_get_lang('system', 'never')) { if ($server['last_offline'] != psm_get_lang('system', 'never')) {

View File

@ -56,8 +56,9 @@ class LogController extends AbstractServerController
'label_email' => psm_get_lang('log', 'email'), 'label_email' => psm_get_lang('log', 'email'),
'label_sms' => psm_get_lang('log', 'sms'), 'label_sms' => psm_get_lang('log', 'sms'),
'label_pushover' => psm_get_lang('log', 'pushover'), 'label_pushover' => psm_get_lang('log', 'pushover'),
'label_webhook' => psm_get_lang('log', 'webhook'),
'label_telegram' => psm_get_lang('log', 'telegram'), 'label_telegram' => psm_get_lang('log', 'telegram'),
'label_jabber' => psm_get_lang('log', 'jabber'), 'label_jabber' => psm_get_lang('log', 'jabber'),
'label_title' => psm_get_lang('log', 'title'), 'label_title' => psm_get_lang('log', 'title'),
'label_server' => psm_get_lang('servers', 'server'), 'label_server' => psm_get_lang('servers', 'server'),
'label_type' => psm_get_lang('log', 'type'), 'label_type' => psm_get_lang('log', 'type'),
@ -89,7 +90,7 @@ class LogController extends AbstractServerController
); );
} }
$log_types = array('status', 'email', 'sms', 'pushover', 'telegram', 'jabber'); $log_types = array('status', 'email', 'sms', 'pushover', 'webhook','telegram', 'jabber');
foreach ($log_types as $key) { foreach ($log_types as $key) {
$records = $this->getEntries($key); $records = $this->getEntries($key);
@ -161,9 +162,9 @@ class LogController extends AbstractServerController
if ($this->getUser()->getUserLevel() > PSM_USER_ADMIN) { if ($this->getUser()->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id // restrict by user_id
$sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON ( $sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON (
`us`.`user_id`={$this->getUser()->getUserId()} `us`.`user_id`={$this->getUser()->getUserId()}
AND `us`.`server_id`=`servers`.`server_id` AND `us`.`server_id`=`servers`.`server_id`
)"; )";
} }
$entries = $this->db->query( $entries = $this->db->query(
'SELECT ' . 'SELECT ' .

View File

@ -101,8 +101,9 @@ class ServerController extends AbstractServerController
'email' => 'icon-envelope', 'email' => 'icon-envelope',
'sms' => 'icon-mobile', 'sms' => 'icon-mobile',
'pushover' => 'icon-pushover', 'pushover' => 'icon-pushover',
'webhook' => 'icon-webhook',
'telegram' => 'icon-telegram', 'telegram' => 'icon-telegram',
'jabber' => 'icon-jabber' 'jabber' => 'icon-jabber'
); );
$servers = $this->getServers(); $servers = $this->getServers();
@ -130,6 +131,7 @@ class ServerController extends AbstractServerController
$tpl_data['config']['email'] = psm_get_conf('email_status'); $tpl_data['config']['email'] = psm_get_conf('email_status');
$tpl_data['config']['sms'] = psm_get_conf('sms_status'); $tpl_data['config']['sms'] = psm_get_conf('sms_status');
$tpl_data['config']['webhook'] = psm_get_conf('webhook_status');
$tpl_data['config']['pushover'] = psm_get_conf('pushover_status'); $tpl_data['config']['pushover'] = psm_get_conf('pushover_status');
$tpl_data['config']['telegram'] = psm_get_conf('telegram_status'); $tpl_data['config']['telegram'] = psm_get_conf('telegram_status');
@ -174,6 +176,13 @@ class ServerController extends AbstractServerController
$tpl_data['users'] = $this->db->select(PSM_DB_PREFIX . 'users', null, array('user_id', 'name'), '', 'name'); $tpl_data['users'] = $this->db->select(PSM_DB_PREFIX . 'users', null, array('user_id', 'name'), '', 'name');
foreach ($tpl_data['users'] as &$user) {
$user['id'] = $user['user_id'];
unset($user['user_id']);
$user['label'] = $user['name'];
unset($user['name']);
}
switch ($this->server_id) { switch ($this->server_id) {
case 0: case 0:
// insert mode // insert mode
@ -194,10 +203,6 @@ class ServerController extends AbstractServerController
$user_idc_selected = $this->getServerUsers($this->server_id); $user_idc_selected = $this->getServerUsers($this->server_id);
foreach ($tpl_data['users'] as &$user) { foreach ($tpl_data['users'] as &$user) {
$user['id'] = $user['user_id'];
unset($user['user_id']);
$user['label'] = $user['name'];
unset($user['name']);
if (in_array($user['id'], $user_idc_selected)) { if (in_array($user['id'], $user_idc_selected)) {
$user['edit_selected'] = 'selected="selected"'; $user['edit_selected'] = 'selected="selected"';
} }
@ -234,13 +239,14 @@ class ServerController extends AbstractServerController
'edit_active_selected' => $edit_server['active'], 'edit_active_selected' => $edit_server['active'],
'edit_email_selected' => $edit_server['email'], 'edit_email_selected' => $edit_server['email'],
'edit_sms_selected' => $edit_server['sms'], 'edit_sms_selected' => $edit_server['sms'],
'edit_webhook_selected' => $edit_server['webhook'],
'edit_pushover_selected' => $edit_server['pushover'], 'edit_pushover_selected' => $edit_server['pushover'],
'edit_telegram_selected' => $edit_server['telegram'], 'edit_telegram_selected' => $edit_server['telegram'],
'edit_jabber_selected' => $edit_server['jabber'], 'edit_jabber_selected' => $edit_server['jabber'],
)); ));
} }
$notifications = array('email', 'sms', 'pushover', 'telegram', 'jabber'); $notifications = array('email', 'sms', 'pushover','webhook', 'telegram', 'jabber');
foreach ($notifications as $notification) { foreach ($notifications as $notification) {
if (psm_get_conf($notification . '_status') == 0) { if (psm_get_conf($notification . '_status') == 0) {
$tpl_data['warning_' . $notification] = true; $tpl_data['warning_' . $notification] = true;
@ -309,8 +315,9 @@ class ServerController extends AbstractServerController
'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no',
'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no',
'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : 'no', 'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : 'no',
'webhook' => in_array($_POST['webhook'], array('yes', 'no')) ? $_POST['webhook'] : 'no',
'telegram' => in_array($_POST['telegram'], array('yes', 'no')) ? $_POST['telegram'] : 'no', 'telegram' => in_array($_POST['telegram'], array('yes', 'no')) ? $_POST['telegram'] : 'no',
'jabber' => in_array($_POST['jabber'], array('yes', 'no')) ? $_POST['jabber'] : 'no', 'jabber' => in_array($_POST['jabber'], array('yes', 'no')) ? $_POST['jabber'] : 'no',
); );
// make sure websites start with http:// // make sure websites start with http://
if ( if (
@ -518,6 +525,15 @@ class ServerController extends AbstractServerController
if (strlen($tpl_data['last_error_output']) > 255) { if (strlen($tpl_data['last_error_output']) > 255) {
$tpl_data['last_error_output_truncated'] = substr($tpl_data['last_error_output'], 0, 255) . '...'; $tpl_data['last_error_output_truncated'] = substr($tpl_data['last_error_output'], 0, 255) . '...';
} }
// fetch server status logs
$log_entries = $this->getServerLogs($this->server_id);
for ($x = 0; $x < count($log_entries); $x++) {
$record = &$log_entries[$x];
$record['datetime_format'] = psm_date($record['datetime']);
}
$tpl_data['log_entries'] = $log_entries;
return $this->twig->render('module/server/server/view.tpl.html', $tpl_data); return $this->twig->render('module/server/server/view.tpl.html', $tpl_data);
} }
@ -578,11 +594,13 @@ class ServerController extends AbstractServerController
'label_sms' => psm_get_lang('servers', 'sms'), 'label_sms' => psm_get_lang('servers', 'sms'),
'label_send_sms' => psm_get_lang('servers', 'send_sms'), 'label_send_sms' => psm_get_lang('servers', 'send_sms'),
'label_send_pushover' => psm_get_lang('servers', 'send_pushover'), 'label_send_pushover' => psm_get_lang('servers', 'send_pushover'),
'label_send_webhook' => psm_get_lang('servers', 'send_webhook'),
'label_telegram' => psm_get_lang('servers', 'telegram'), 'label_telegram' => psm_get_lang('servers', 'telegram'),
'label_jabber' => psm_get_lang('servers', 'jabber'), 'label_jabber' => psm_get_lang('servers', 'jabber'),
'label_webhook' => psm_get_lang('servers', 'webhook'),
'label_pushover' => psm_get_lang('servers', 'pushover'), 'label_pushover' => psm_get_lang('servers', 'pushover'),
'label_send_telegram' => psm_get_lang('servers', 'send_telegram'), 'label_send_telegram' => psm_get_lang('servers', 'send_telegram'),
'label_send_jabber' => psm_get_lang('servers', 'send_jabber'), 'label_send_jabber' => psm_get_lang('servers', 'send_jabber'),
'label_users' => psm_get_lang('servers', 'users'), 'label_users' => psm_get_lang('servers', 'users'),
'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'),
'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'),
@ -597,7 +615,8 @@ class ServerController extends AbstractServerController
'label_yes' => psm_get_lang('system', 'yes'), 'label_yes' => psm_get_lang('system', 'yes'),
'label_no' => psm_get_lang('system', 'no'), 'label_no' => psm_get_lang('system', 'no'),
'label_add_new' => psm_get_lang('system', 'add_new'), 'label_add_new' => psm_get_lang('system', 'add_new'),
'label_seconds' => psm_get_lang('config', 'seconds'), 'label_seconds' => psm_get_lang('system', 'seconds'),
'label_milliseconds' => psm_get_lang('system', 'milliseconds'),
'label_online' => psm_get_lang('servers', 'online'), 'label_online' => psm_get_lang('servers', 'online'),
'label_offline' => psm_get_lang('servers', 'offline'), 'label_offline' => psm_get_lang('servers', 'offline'),
'label_ok' => psm_get_lang('system', 'ok'), 'label_ok' => psm_get_lang('system', 'ok'),
@ -606,6 +625,10 @@ class ServerController extends AbstractServerController
'label_settings' => psm_get_lang('system', 'settings'), 'label_settings' => psm_get_lang('system', 'settings'),
'label_output' => psm_get_lang('servers', 'output'), 'label_output' => psm_get_lang('servers', 'output'),
'label_search' => psm_get_lang('system', 'search'), 'label_search' => psm_get_lang('system', 'search'),
'label_log_title' => psm_get_lang('log', 'title'),
'label_log_no_logs' => psm_get_lang('log', 'no_logs'),
'label_date' => psm_get_lang('system', 'date'),
'label_message' => psm_get_lang('system', 'message'),
); );
} }
@ -627,4 +650,42 @@ class ServerController extends AbstractServerController
} }
return $result; return $result;
} }
/**
* Get logs for a server
* @param int $server_id
* @param string $type status/email/sms
* @return \PDOStatement array
*/
protected function getServerLogs($server_id, $type = 'status')
{
$sql_join = '';
if ($this->getUser()->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id
$sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON (
`us`.`user_id`={$this->getUser()->getUserId()}
AND `us`.`server_id`=`servers`.`server_id`
)";
}
$entries = $this->db->query(
'SELECT ' .
'`servers`.`label`, ' .
'`servers`.`ip`, ' .
'`servers`.`port`, ' .
'`servers`.`type` AS server_type, ' .
'`log`.`log_id`, ' .
'`log`.`type`, ' .
'`log`.`message`, ' .
'`log`.`datetime` ' .
'FROM `' . PSM_DB_PREFIX . 'log` AS `log` ' .
'JOIN `' . PSM_DB_PREFIX . 'servers` AS `servers` ON (`servers`.`server_id`=`log`.`server_id`) ' .
$sql_join .
'WHERE `log`.`type`=\'' . $type . '\' ' .
'AND `log`.`server_id`=' . $server_id . ' ' .
'ORDER BY `datetime` DESC ' .
'LIMIT 0,20'
);
return $entries;
}
} }

View File

@ -39,7 +39,7 @@ class ProfileController extends AbstractController
* @var array $profile_fields * @var array $profile_fields
*/ */
protected $profile_fields = protected $profile_fields =
array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'jabber'); array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device','webhook_url', 'webhook_json', 'telegram_id', 'jabber');
public function __construct(Database $db, \Twig_Environment $twig) public function __construct(Database $db, \Twig_Environment $twig)
{ {
@ -78,6 +78,12 @@ class ProfileController extends AbstractController
'label_password_repeat' => psm_get_lang('users', 'password_repeat'), 'label_password_repeat' => psm_get_lang('users', 'password_repeat'),
'label_level' => psm_get_lang('users', 'level'), 'label_level' => psm_get_lang('users', 'level'),
'label_mobile' => psm_get_lang('users', 'mobile'), 'label_mobile' => psm_get_lang('users', 'mobile'),
'label_webhook' => psm_get_lang('users', 'webhook'),
'label_webhook_description' => psm_get_lang('users', 'webhook_description'),
'label_webhook_url' => psm_get_lang('users', 'webhook_url'),
'label_webhook_url_description' => psm_get_lang('users', 'webhook_url_description'),
'label_webhook_json' => psm_get_lang('users', 'webhook_json'),
'label_webhook_json_description' => psm_get_lang('users', 'webhook_json_description'),
'label_pushover' => psm_get_lang('users', 'pushover'), 'label_pushover' => psm_get_lang('users', 'pushover'),
'label_pushover_description' => psm_get_lang('users', 'pushover_description'), 'label_pushover_description' => psm_get_lang('users', 'pushover_description'),
'label_pushover_key' => psm_get_lang('users', 'pushover_key'), 'label_pushover_key' => psm_get_lang('users', 'pushover_key'),
@ -90,8 +96,8 @@ class ProfileController extends AbstractController
'label_activate_telegram' => psm_get_lang('users', 'activate_telegram'), 'label_activate_telegram' => psm_get_lang('users', 'activate_telegram'),
'label_telegram_get_chat_id' => psm_get_lang('users', 'telegram_get_chat_id'), 'label_telegram_get_chat_id' => psm_get_lang('users', 'telegram_get_chat_id'),
'telegram_get_chat_id_url' => PSM_TELEGRAM_GET_ID_URL, 'telegram_get_chat_id_url' => PSM_TELEGRAM_GET_ID_URL,
'label_jabber' => psm_get_lang('users', 'jabber'), 'label_jabber' => psm_get_lang('users', 'jabber'),
'label_jabber_description' => psm_get_lang('users', 'jabber_description'), 'label_jabber_description' => psm_get_lang('users', 'jabber_description'),
'label_email' => psm_get_lang('users', 'email'), 'label_email' => psm_get_lang('users', 'email'),
'label_save' => psm_get_lang('system', 'save'), 'label_save' => psm_get_lang('system', 'save'),
'form_action' => psm_build_url(array( 'form_action' => psm_build_url(array(

View File

@ -158,6 +158,8 @@ class UserController extends AbstractController
'name', 'name',
'user_name', 'user_name',
'mobile', 'mobile',
'webhook_url',
'webhook_json',
'pushover_key', 'pushover_key',
'pushover_device', 'pushover_device',
'telegram_id', 'telegram_id',
@ -255,6 +257,8 @@ class UserController extends AbstractController
'password_repeat', 'password_repeat',
'level', 'level',
'mobile', 'mobile',
'webhook_url',
'webhook_json',
'pushover_key', 'pushover_key',
'pushover_device', 'pushover_device',
'telegram_id', 'telegram_id',
@ -392,6 +396,12 @@ class UserController extends AbstractController
'label_level' => psm_get_lang('users', 'level'), 'label_level' => psm_get_lang('users', 'level'),
'label_level_description' => psm_get_lang('users', 'level_description'), 'label_level_description' => psm_get_lang('users', 'level_description'),
'label_mobile' => psm_get_lang('users', 'mobile'), 'label_mobile' => psm_get_lang('users', 'mobile'),
'label_webhook' => psm_get_lang('users', 'webhook'),
'label_webhook_description' => psm_get_lang('users', 'webhook_description'),
'label_webhook_url' => psm_get_lang('users', 'webhook_url'),
'label_webhook_url_description' => psm_get_lang('users', 'webhook_url_description'),
'label_webhook_json' => psm_get_lang('users', 'webhook_json'),
'label_webhook_json_description' => psm_get_lang('users', 'webhook_json_description'),
'label_pushover' => psm_get_lang('users', 'pushover'), 'label_pushover' => psm_get_lang('users', 'pushover'),
'label_pushover_description' => psm_get_lang('users', 'pushover_description'), 'label_pushover_description' => psm_get_lang('users', 'pushover_description'),
'label_pushover_key' => psm_get_lang('users', 'pushover_key'), 'label_pushover_key' => psm_get_lang('users', 'pushover_key'),

View File

@ -35,15 +35,15 @@ final class UserEvents
/** /**
* @var string * @var string
*/ */
public const USER_ADD = 'user.add'; const USER_ADD = 'user.add';
/** /**
* @var string * @var string
*/ */
public const USER_EDIT = 'user.edit'; const USER_EDIT = 'user.edit';
/** /**
* @var string * @var string
*/ */
public const USER_DELETE = 'user.delete'; const USER_DELETE = 'user.delete';
} }

View File

@ -67,10 +67,10 @@ class CMBulkSMS extends Core
protected $messageBody; protected $messageBody;
/** @var string JSON Gateway API URL */ /** @var string JSON Gateway API URL */
public const GATEWAY_URL_JSON = "https://gw.cmtelecom.com/v1.0/message"; const GATEWAY_URL_JSON = "https://gw.cmtelecom.com/v1.0/message";
/** @var string XML Gateway API URL */ /** @var string XML Gateway API URL */
public const GATEWAY_URL_XML = "https://sgw01.cm.nl/gateway.ashx"; const GATEWAY_URL_XML = "https://sgw01.cm.nl/gateway.ashx";
/** /**
* Build the message and send cURL request to the sms gateway * Build the message and send cURL request to the sms gateway

101
src/psm/Txtmsg/OVHsms.php Normal file
View File

@ -0,0 +1,101 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Alexis Urien <Alexis.urien@free.fr>
* @Author Tim Zandbergen <Tim@Xervion.nl>
* @author Ward Pieters <ward@wardpieters.nl>
* @author Alexandre ZANELLI <alexandre@les-z.org>
* @copyright Copyright (c) 2016 Alexis Urien <alexis.urien@free.fr>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 3.5
**/
namespace psm\Txtmsg;
class OVHsms extends Core {
/**
* Send sms using the OVH http2sms gateway
* Online documentation :https://docs.ovh.com/fr/sms/envoyer_des_sms_depuis_une_url_-_http2sms/
* Ovh need Account and Login, then use format login@account in username field.
*
* @var string $message
* @var string $this->username
* @var string $this->password
* @var array $this->recipients
* @var array $this->originator
*
* @var resource $curl
* @var SimpleXMLElement $xmlResults
* @var string $err
* @var string $recipient
* @var mixed $result
*
* @var int $success
* @var string $error
*
* @return bool|string
*/
public function sendSMS($message) {
$error = "";
$success = 1;
$account_login = explode('@',$this->username);
$recipients = join(',', $this->recipients);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://www.ovh.com/cgi-bin/sms/http2sms.cgi?".http_build_query(
array(
"account" => $account_login[1],
"login" => $account_login[0],
"password" => $this->password,
"from" => str_replace('+', '00', $this->originator),
"to" => $recipients,
"message" => $message,
"contentType" => "text/xml",
"noStop" => 1,
)
)
);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$xmlResults = simplexml_load_string($result);
$err = curl_errno($curl);
if ($err != 0 || $httpcode != 200 || $xmlResults === false ||($xmlResults->status != '100' && $xmlResults->status != '101')) {
$success = 0;
$error = "HTTP_code: ".$httpcode.".\ncURL error (".$err."): ".curl_strerror($err).". \nResult: ".$xmlResults->status." \n".$xmlResults->Message;
}
curl_close($curl);
if ($success) {
return 1;
}
return $error;
}
}

View File

@ -63,7 +63,7 @@ class Octopush extends Core
$recipients = join(',', $this->recipients); $recipients = join(',', $this->recipients);
$message = ($smsType == "FR") ? urlencode($message . " STOP au XXXX") : urlencode($message); $message = ($smsType == "FR") ? rawurlencode($message . " STOP au XXXXX") : rawurlencode($message);
$curl = curl_init(); $curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.octopush-dm.com/api/sms/?" . http_build_query( curl_setopt($curl, CURLOPT_URL, "http://www.octopush-dm.com/api/sms/?" . http_build_query(

149
src/psm/Txtmsg/SMSAPI.php Executable file
View File

@ -0,0 +1,149 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Mateusz Małek <tajgeer@gmail.com>
* @copyright Copyright (c) 2008-2017 Pepijn Over <pep@mailbox.org>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 3.5
**/
namespace psm\Txtmsg;
class SMSAPI extends Core
{
const VARIANT_INTERNATIONAL = 1;
const VARIANT_POLISH = 2;
/**
* SMSAPI comes with two variants - designed for polish or international customers.
*
* @var int
*/
private $variant = self::VARIANT_INTERNATIONAL;
/**
* Name of the sender. As a default the sender name is set to "Test".
* Only verified names are being accepted.
* Sender name may be set after logging into Customer Portal on Sendernames.
* @see https://www.smsapi.com/docs/#2-single-sms
*
* @var string
*/
protected $originator;
/**
* Token used to authenticate in SMSAPI system.
* @see https://www.smsapi.com/docs/#authentication
*
* @var string
*/
protected $password;
/**
* Send sms using the SMSAPI
*
* @var string $message
* @var array $this->recipients
* @var array $this->originator
* @var string $this->password
* @var array $recipients_chunk
* @var string $host
*
* @var mixed $result
* @var array $headers
*
* @var int $success
* @var string $error
*
* @return bool|string
*/
public function sendSMS($message)
{
$tld = ($this->variant === static::VARIANT_INTERNATIONAL) ? "com" : "pl";
$host = "api.smsapi.{$tld}";
$backupHost = "api2.smsapi.{$tld}";
// One user at a time.
$recipients_chunk = array_chunk($this->recipients, 1);
foreach ($recipients_chunk as $recipient) {
try {
$response = $this->processSendOperation($host, $recipient, $message);
} catch (\RuntimeException $e) {
try {
$response = $this->processSendOperation($backupHost, $recipient, $message);
} catch (\RuntimeException $e) {
return "({$recipient}) " . $e->getMessage();
}
}
if (isset($response->error)) {
return $response->message;
}
return 1;
}
}
/**
* Perform actual SMS sending operation
*
* @param $host
* @param $recipient
* @param $message
* @return object
* @throws RuntimeException
*/
private function processSendOperation($host, $recipient, $message)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://{$host}/sms.do");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
"access_token" => $this->password,
"from" => $this->originator,
"to" => $recipient,
"message" => $message,
"encoding" => "utf-8",
"normalize" => "1",
"format" => "json"
)));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$result = curl_exec($ch);
$error = false;
if (curl_errno($ch)) {
$error = curl_error($ch);
}
curl_close($ch);
if ($error !== false) {
throw new \RuntimeException($error);
}
return json_decode($result);
}
}

View File

@ -134,11 +134,11 @@ class Installer
$queries = array(); $queries = array();
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` ( $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` (
`ip`, `port`, `label`, `type`, `pattern`, `pattern_online`, `redirect_check`, `ip`, `port`, `label`, `type`, `pattern`, `pattern_online`, `redirect_check`,
`status`, `rtime`, `active`, `email`, `sms`, `pushover`, `telegram`, `jabber`) `status`, `rtime`, `active`, `email`, `sms`, `pushover`,`webhook`, `telegram`, `jabber`)
VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', '', VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', '',
'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes'), 'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes','yes', 'yes', 'yes'),
('smtp.gmail.com', 465, 'Gmail SMTP', 'service', '', ('smtp.gmail.com', 465, 'Gmail SMTP', 'service', '',
'yes', 'bad','on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes')"; 'yes', 'bad','on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes')";
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "users_servers` (`user_id`,`server_id`) VALUES (1, 1), (1, 2);"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "users_servers` (`user_id`,`server_id`) VALUES (1, 1), (1, 2);";
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE
('language', 'en_US'), ('language', 'en_US'),
@ -160,6 +160,7 @@ class Installer
('sms_gateway_username', 'username'), ('sms_gateway_username', 'username'),
('sms_gateway_password', 'password'), ('sms_gateway_password', 'password'),
('sms_from', '1234567890'), ('sms_from', '1234567890'),
('webhook_status', '0'),
('pushover_status', '0'), ('pushover_status', '0'),
('pushover_api_token', ''), ('pushover_api_token', ''),
('telegram_status', '0'), ('telegram_status', '0'),
@ -176,6 +177,7 @@ class Installer
('log_email', '1'), ('log_email', '1'),
('log_sms', '1'), ('log_sms', '1'),
('log_pushover', '1'), ('log_pushover', '1'),
('log_webhook', '1'),
('log_telegram', '1'), ('log_telegram', '1'),
('log_jabber', '1'), ('log_jabber', '1'),
('log_retention_period', '365'), ('log_retention_period', '365'),
@ -214,7 +216,9 @@ class Installer
`mobile` varchar(15) NOT NULL, `mobile` varchar(15) NOT NULL,
`pushover_key` varchar(255) NOT NULL, `pushover_key` varchar(255) NOT NULL,
`pushover_device` varchar(255) NOT NULL, `pushover_device` varchar(255) NOT NULL,
`telegram_id` varchar(255) NOT NULL, `webhook_url` varchar(255) NOT NULL,
`webhook_json` varchar(255) NOT NULL DEFAULT '{\"text\":\"servermon: #message\"}',
`telegram_id` varchar(255) NOT NULL ,
`jabber` varchar(255) NOT NULL, `jabber` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL, `email` varchar(255) NOT NULL,
PRIMARY KEY (`user_id`), PRIMARY KEY (`user_id`),
@ -235,7 +239,7 @@ class Installer
PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` ( PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` (
`log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`server_id` int(11) unsigned NOT NULL, `server_id` int(11) unsigned NOT NULL,
`type` enum('status','email','sms','pushover','telegram', 'jabber') NOT NULL, `type` enum('status','email','sms','pushover','webhook','telegram', 'jabber') NOT NULL,
`message` TEXT NOT NULL, `message` TEXT NOT NULL,
`datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`log_id`) PRIMARY KEY (`log_id`)
@ -270,6 +274,7 @@ class Installer
`email` enum('yes','no') NOT NULL default 'yes', `email` enum('yes','no') NOT NULL default 'yes',
`sms` enum('yes','no') NOT NULL default 'no', `sms` enum('yes','no') NOT NULL default 'no',
`pushover` enum('yes','no') NOT NULL default 'yes', `pushover` enum('yes','no') NOT NULL default 'yes',
`webhook` enum('yes','no') NOT NULL default 'yes',
`telegram` enum('yes','no') NOT NULL default 'yes', `telegram` enum('yes','no') NOT NULL default 'yes',
`jabber` enum('yes','no') NOT NULL default 'yes', `jabber` enum('yes','no') NOT NULL default 'yes',
`warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1', `warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1',
@ -357,6 +362,9 @@ class Installer
if (version_compare($version_from, '3.5.0', '<')) { if (version_compare($version_from, '3.5.0', '<')) {
$this->upgrade350(); $this->upgrade350();
} }
if (version_compare($version_from, '3.6.0', '<')) {
$this->upgrade360();
}
psm_update_conf('version', $version_to); psm_update_conf('version', $version_to);
} }
@ -553,7 +561,7 @@ class Installer
$this->execSQL($queries); $this->execSQL($queries);
// Create log_users table // Create log_users table
$this->execSQL("CREATE TABLE `" . PSM_DB_PREFIX . "log_users` ( $this->execSQL("CREATE TABLE `" . PSM_DB_PREFIX . "log_users` (
`log_id` int(11) UNSIGNED NOT NULL , `log_id` int(11) UNSIGNED NOT NULL ,
`user_id` int(11) UNSIGNED NOT NULL , `user_id` int(11) UNSIGNED NOT NULL ,
@ -659,7 +667,7 @@ class Installer
$this->execSQL($queries); $this->execSQL($queries);
$this->log('Combined notifications enabled. Check out the config page for more info.'); $this->log('Combined notifications enabled. Check out the config page for more info.');
} }
/** /**
* Patch for v3.4.2 release * Patch for v3.4.2 release
* Version_compare was forgotten in v3.4.1 and query failed. * Version_compare was forgotten in v3.4.1 and query failed.
@ -715,4 +723,27 @@ class Installer
$this->execSQL($queries); $this->execSQL($queries);
} }
/**
* Upgrade for v3.6.0 release
*/
protected function upgrade360()
{
$queries = array();
$queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users`
ADD `webhook_url` VARCHAR( 255 ) NOT NULL AFTER `telegram_id`;';
$queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users`
ADD `webhook_json` VARCHAR( 255 ) NOT NULL AFTER `telegram_id`;';
$queries[] = "ALTER TABLE `' . PSM_DB_PREFIX . 'log`
CHANGE `type` `type` ENUM('status','email','sms','webhook','pushover','telegram','jabber')
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;";
$queries[] = "ALTER TABLE `' . PSM_DB_PREFIX . 'servers`
ADD `webhook` ENUM( 'yes','no' ) NOT NULL DEFAULT 'yes' AFTER `telegram`;";
$queries[] = "INSERT INTO `' . PSM_DB_PREFIX . 'config` (`key`, `value`) VALUE
('webhook_status', '0'),
('log_webhook', '1')";
$this->execSQL($queries);
}
} }

View File

@ -32,9 +32,9 @@ namespace psm\Util\Module;
class Modal implements ModalInterface class Modal implements ModalInterface
{ {
public const MODAL_TYPE_OK = 0; const MODAL_TYPE_OK = 0;
public const MODAL_TYPE_OKCANCEL = 1; const MODAL_TYPE_OKCANCEL = 1;
public const MODAL_TYPE_DANGER = 2; const MODAL_TYPE_DANGER = 2;
/** /**
* prefix used for modal dialog box elements * prefix used for modal dialog box elements
@ -145,7 +145,7 @@ class Modal implements ModalInterface
$tpl = $this->twig->loadTemplate('util/module/modal.tpl.html'); $tpl = $this->twig->loadTemplate('util/module/modal.tpl.html');
$html = $tpl->render(array( $html = $tpl->render(array(
'modal_id' => $this->modal_id, 'modal_id' => $this->modal_id,
'modal_title' => !empty($this->title) ? $this->title : psm_get_lang('system', 'title'), 'modal_title' => !empty($this->title) ? $this->title : psm_get_conf('site_title', psm_get_lang('system', 'title')),
'modal_body' => $message, 'modal_body' => $message,
'has_cancel' => $has_cancel, 'has_cancel' => $has_cancel,
'label_cancel' => psm_get_lang('system', 'cancel'), 'label_cancel' => psm_get_lang('system', 'cancel'),

View File

@ -29,7 +29,10 @@
namespace psm\Util\Server; namespace psm\Util\Server;
use DateTime;
use psm\Service\Database; use psm\Service\Database;
use Twig\Error\Error;
use Twig_Environment;
/** /**
* History util, create HTML for server graphs * History util, create HTML for server graphs
@ -39,17 +42,17 @@ class HistoryGraph
/** /**
* Database service * Database service
* @var \psm\Service\Database $db; * @var Database $db;
*/ */
protected $db; protected $db;
/** /**
* Twig environment * Twig environment
* @var \Twig_Environment $twig * @var Twig_Environment $twig
*/ */
protected $twig; protected $twig;
public function __construct(Database $db, \Twig_Environment $twig) public function __construct(Database $db, Twig_Environment $twig)
{ {
$this->db = $db; $this->db = $db;
$this->twig = $twig; $this->twig = $twig;
@ -57,7 +60,9 @@ class HistoryGraph
/** /**
* Prepare the HTML for the graph * Prepare the HTML for the graph
* @return string * @param string $server_id ID of server to fetch data for
* @return string Created HTML
* @throws Error On twig error
*/ */
public function createHTML($server_id) public function createHTML($server_id)
{ {
@ -65,16 +70,16 @@ class HistoryGraph
$archive = new ArchiveManager($this->db); $archive = new ArchiveManager($this->db);
$archive->archive($server_id); $archive->archive($server_id);
$now = new \DateTime(); $now = new DateTime();
$last_week = new \DateTime('-1 week 0:0:0'); $last_week = new DateTime('-1 week 0:0:0');
$last_year = new \DateTime('-1 year -1 week 0:0:0'); $last_year = new DateTime('-1 year -1 week 0:0:0');
$graphs = array( $graphs = array(
0 => $this->generateGraphUptime($server_id, $last_week, $now), 0 => $this->generateGraphUptime($server_id, $last_week, $now),
1 => $this->generateGraphHistory($server_id, $last_year, $last_week), 1 => $this->generateGraphHistory($server_id, $last_year, $last_week),
); );
$info_fields = array( $info_fields = array(
'latency_avg' => '%01.4f', 'latency_avg' => '%01.5f',
'uptime' => '%01.3f%%', 'uptime' => '%01.3f%%',
); );
@ -101,8 +106,8 @@ class HistoryGraph
/** /**
* Generate data for uptime graph * Generate data for uptime graph
* @param int $server_id * @param int $server_id
* @param \DateTime $start_time Lowest DateTime of the graph * @param DateTime $start_time Lowest DateTime of the graph
* @param \DateTime $end_time Highest DateTime of the graph * @param DateTime $end_time Highest DateTime of the graph
* @return array * @return array
*/ */
public function generateGraphUptime($server_id, $start_time, $end_time) public function generateGraphUptime($server_id, $start_time, $end_time)
@ -112,9 +117,9 @@ class HistoryGraph
'latency' => array(), 'latency' => array(),
); );
$hour = new \DateTime('-1 hour'); $hour = new DateTime('-1 hour');
$day = new \DateTime('-1 day'); $day = new DateTime('-1 day');
$week = new \DateTime('-1 week'); $week = new DateTime('-1 week');
$records = $this->getRecords('uptime', $server_id, $start_time, $end_time); $records = $this->getRecords('uptime', $server_id, $start_time, $end_time);
@ -148,8 +153,8 @@ class HistoryGraph
/** /**
* Generate data for history graph * Generate data for history graph
* @param int $server_id * @param int $server_id
* @param \DateTime $start_time Lowest DateTime of the graph * @param DateTime $start_time Lowest DateTime of the graph
* @param \DateTime $end_time Highest DateTime of the graph * @param DateTime $end_time Highest DateTime of the graph
* @return array * @return array
*/ */
public function generateGraphHistory($server_id, $start_time, $end_time) public function generateGraphHistory($server_id, $start_time, $end_time)
@ -160,9 +165,9 @@ class HistoryGraph
'latency_max' => array(), 'latency_max' => array(),
); );
$week = new \DateTime('-2 week 0:0:0'); $week = new DateTime('-2 week 0:0:0');
$month = new \DateTime('-1 month -1 week 0:0:0'); $month = new DateTime('-1 month -1 week 0:0:0');
$year = new \DateTime('-1 year -1 week 0:0:0'); $year = new DateTime('-1 year -1 week 0:0:0');
$records = $this->getRecords('history', $server_id, $year, $end_time); $records = $this->getRecords('history', $server_id, $year, $end_time);
@ -197,8 +202,8 @@ class HistoryGraph
* Get all uptime/history records for a server * Get all uptime/history records for a server
* @param string $type * @param string $type
* @param int $server_id * @param int $server_id
* @param \DateTime $start_time Lowest DateTime of the graph * @param DateTime $start_time Lowest DateTime of the graph
* @param \DateTime $end_time Highest DateTime of the graph * @param DateTime $end_time Highest DateTime of the graph
* @return array * @return array
*/ */
protected function getRecords($type, $server_id, $start_time, $end_time) protected function getRecords($type, $server_id, $start_time, $end_time)
@ -207,17 +212,19 @@ class HistoryGraph
return array(); return array();
} }
$records = $this->db->execute( /** @noinspection SqlNoDataSourceInspection */
"SELECT * /** @noinspection SqlResolve */
/** @noinspection PhpUndefinedConstantInspection */
return $this->db->execute(
"SELECT *, UNIX_TIMESTAMP(CONVERT_TZ(`date`, '+00:00', @@session.time_zone)) AS date_ts
FROM `" . PSM_DB_PREFIX . "servers_$type` FROM `" . PSM_DB_PREFIX . "servers_$type`
WHERE `server_id` = :server_id AND `date` BETWEEN :start_time AND :end_time ORDER BY `date` ASC", WHERE `server_id` = :server_id AND `date` BETWEEN :start_time AND :end_time ORDER BY `date`",
array( array(
'server_id' => $server_id, 'server_id' => $server_id,
'start_time' => $start_time->format('Y-m-d H:i:s'), 'start_time' => $start_time->format('Y-m-d H:i:s'),
'end_time' => $end_time->format('Y-m-d H:i:s'), 'end_time' => $end_time->format('Y-m-d H:i:s'),
) )
); );
return $records;
} }
/** /**
@ -225,12 +232,9 @@ class HistoryGraph
* @param array $records All uptime records to parse, MUST BE SORTED BY DATE IN ASCENDING ORDER * @param array $records All uptime records to parse, MUST BE SORTED BY DATE IN ASCENDING ORDER
* @param array $lines Array with keys as line ids to prepare (key must be available in uptime records) * @param array $lines Array with keys as line ids to prepare (key must be available in uptime records)
* @param string $latency_avg_key which key from uptime records to use for calculating averages * @param string $latency_avg_key which key from uptime records to use for calculating averages
* @param \DateTime $start_time Lowest DateTime of the graph * @param DateTime $start_time Lowest DateTime of the graph
* @param \DateTime $end_time Highest DateTime of the graph * @param DateTime $end_time Highest DateTime of the graph
* @param boolean $add_uptime Add uptime calculation? * @param boolean $add_uptime Add uptime calculation?
* @param array $prev Previous result
* @param int $downtime Total downtime
* @param int $prev_downtime Timestamp from last offline record. 0 when last record is uptime
* @return array * @return array
*/ */
protected function generateGraphLines( protected function generateGraphLines(
@ -241,64 +245,90 @@ class HistoryGraph
$end_time, $end_time,
$add_uptime = false $add_uptime = false
) { ) {
$now = new \DateTime(); $now = new DateTime();
$data = array(); $data = array();
// PLEASE NOTE: all times are in microseconds! because of javascript. // PLEASE NOTE: all times are in microseconds! because of javascript.
$latency_avg = 0; $latency_avg = 0;
/** @var array $prev Previous record */
$prev = reset($records); $prev = reset($records);
// Timestamp from last offline record. 0 when last record is up.
$prev_downtime = 0; $prev_downtime = 0;
// Total downtime
$downtime = 0; $downtime = 0;
// The keys of the lines iterated
$line_keys = array_keys($lines);
// Determine whether to process data for the short history graph
$is_short_graph = count($line_keys) === 1 && $line_keys[0] === 'latency';
// get highest latency record for offline height
$highest_latency = 0.0;
if ($is_short_graph) {
foreach ($records as $record) {
$latency = (float) $record['latency'];
if ($latency > $highest_latency) {
$highest_latency = $latency;
}
}
// to ms
$highest_latency = round($highest_latency * 1000);
}
// Create the list of points and server down zones // Create the list of points and server down zones
foreach ($records as $record) { foreach ($records as $record) {
$time = strtotime($record['date']);
// use the first line to calculate average latency // use the first line to calculate average latency
$latency_avg += (float) $record[$latency_avg_key]; $latency_avg += (float) $record[$latency_avg_key];
foreach ($lines as $key => $value) { if ($is_short_graph) {
// add the value for each of the different lines $time = (int) $record['date_ts'];
if (isset($record[$key])) { // Timestamp in milliseconds
if (isset($record['status'])) { $time_ms = $time * 1000;
// down if (!$record['status']) {
if ($record['status'] == 0) { // down
$lines['online'][] = $prev['status'] $lines['online'][] = $prev['status']
// Previous datapoint was online // Previous datapoint was online
? '{ x: ' . ($time * 1000) . ', y: ' . $prev['latency'] . '}' ? ['x' => $time_ms, 'y' => round($prev['latency'] * 1000, 3)]
// Previous datapoint was offline // Previous datapoint was offline
: '{ x: ' . ($time * 1000) . ', y: null}'; : ['x' => $time_ms, 'y' => null];
// new outage start // new outage start
$lines['offline'][] = '{ x: ' . ($time * 1000) . ', y:0.1}'; $lines['offline'][] = ['x' => $time_ms, 'y' => $highest_latency];
$prev_downtime != 0 ?: $prev_downtime = $time; if ($prev_downtime === 0) {
} else { $prev_downtime = $time;
// up
// outage ends
$lines['offline'][] = $prev['status']
// Previous datapoint was online
? '{ x: ' . ($time * 1000) . ', y:null}'
// Previous datapoint was offline
: '{ x: ' . ($time * 1000) . ', y:0.1}';
$lines['online'][] = '{ x: ' . ($time * 1000) . ', y: ' .
round((float) $record[$key], 4) . '}';
$prev_downtime == 0 ?: $downtime += ($time - $prev_downtime);
$prev_downtime = 0;
}
} else {
$lines[$key][] = '{ x: \'' . $record['date'] . '\', y: ' . $record[$key] . '}';
} }
$prev = $record; } else {
// up
// outage ends
$lines['offline'][] = $prev['status']
// Previous datapoint was online
? ['x' => $time_ms, 'y' => null]
// Previous datapoint was offline
: ['x' => $time_ms, 'y' => $highest_latency];
$lines['online'][] = ['x' => $time_ms, 'y' => round($record['latency'] * 1000, 3)];
if ($prev_downtime !== 0) {
$downtime += ($time - $prev_downtime);
}
$prev_downtime = 0;
}
} else {
foreach ($line_keys as $key) {
// add the value for each of the different lines
$lines[$key][] = ['x' => $record['date'], 'y' => $record[$key] * 1000];
} }
} }
$prev = $record;
} }
// Was down before. // Was down before.
// Record the first and last date as a string in the down array // Record the first and last date as a string in the down array
$prev_downtime == 0 ?: $downtime += ($now->getTimestamp() - $prev_downtime); $prev_downtime == 0 ?: $downtime += ($now->getTimestamp() - $prev_downtime);
if ($add_uptime) { if ($add_uptime) {
$prev['status'] ?: $lines['offline'][] = '{ x: ' . ($now->getTimestamp() * 1000) . ', y:0.1}'; if (!$prev['status']) {
$lines['offline'][] = ['x' => $now->getTimestamp() * 1000, 'y' => $highest_latency];
}
$data['uptime'] = 100 - ($downtime / ($end_time->getTimestamp() - $start_time->getTimestamp())); $data['uptime'] = 100 - ($downtime / ($end_time->getTimestamp() - $start_time->getTimestamp()));
} }
@ -307,11 +337,12 @@ class HistoryGraph
if (empty($line_value)) { if (empty($line_value)) {
continue; continue;
} }
$lines_merged[$line_key]['value'] = implode(', ', $line_value); $lines_merged[$line_key]['value'] = json_encode($line_value);
$lines_merged[$line_key]['name'] = psm_get_lang('servers', $line_key); $lines_merged[$line_key]['name'] = psm_get_lang('servers', $line_key);
} }
$data['latency_avg'] = count($records) > 0 ? ($latency_avg / count($records)) : 0; $n_records = count($records);
$data['latency_avg'] = $n_records > 0 ? ($latency_avg / $n_records) : 0;
$data['lines'] = sizeof($lines_merged) ? $lines_merged : ''; $data['lines'] = sizeof($lines_merged) ? $lines_merged : '';
$data['end_timestamp'] = number_format($end_time->getTimestamp(), 0, '', '') * 1000; $data['end_timestamp'] = number_format($end_time->getTimestamp(), 0, '', '') * 1000;
$data['start_timestamp'] = number_format($start_time->getTimestamp(), 0, '', '') * 1000; $data['start_timestamp'] = number_format($start_time->getTimestamp(), 0, '', '') * 1000;

View File

@ -53,9 +53,9 @@ class UpdateManager implements ContainerAwareInterface
*/ */
public function run($skip_perms = false, $status = null) public function run($skip_perms = false, $status = null)
{ {
if (false === in_array($status, ['on', 'off'], true)) { if (false === in_array($status, ['on', 'off'], true)) {
$status = null; $status = null;
} }
// check if we need to restrict the servers to a certain user // check if we need to restrict the servers to a certain user
$sql_join = ''; $sql_join = '';
@ -63,17 +63,17 @@ class UpdateManager implements ContainerAwareInterface
if (!$skip_perms && $this->container->get('user')->getUserLevel() > PSM_USER_ADMIN) { if (!$skip_perms && $this->container->get('user')->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id // restrict by user_id
$sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON ( $sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON (
`us`.`user_id`={$this->container->get('user')->getUserId()} `us`.`user_id`={$this->container->get('user')->getUserId()}
AND `us`.`server_id`=`s`.`server_id` AND `us`.`server_id`=`s`.`server_id`
)"; )";
} }
$sql = "SELECT `s`.`server_id`,`s`.`ip`,`s`.`port`,`s`.`label`,`s`.`type`,`s`.`pattern`,`s`.`header_name`, $sql = "SELECT `s`.`server_id`,`s`.`ip`,`s`.`port`,`s`.`label`,`s`.`type`,`s`.`pattern`,`s`.`header_name`,
`s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`telegram`, `s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`webhook`,`s`.`telegram`,
`s`.`jabber` `s`.`jabber`
FROM `" . PSM_DB_PREFIX . "servers` AS `s` FROM `" . PSM_DB_PREFIX . "servers` AS `s`
{$sql_join} {$sql_join}
WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : ''); WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : '');
$servers = $this->container->get('db')->query($sql); $servers = $this->container->get('db')->query($sql);

View File

@ -63,16 +63,22 @@ class StatusNotifier
*/ */
protected $send_pushover = false; protected $send_pushover = false;
/**
* Send webhook notification?
* @var boolean $send_webhook
*/
protected $send_webhook = false;
/** /**
* Send telegram? * Send telegram?
* @var boolean $send_telegram * @var boolean $send_telegram
*/ */
protected $send_telegram = false; protected $send_telegram = false;
/** /**
* Send Jabber? * Send Jabber?
* @var bool * @var bool
*/ */
protected $send_jabber = false; protected $send_jabber = false;
/** /**
@ -128,6 +134,7 @@ class StatusNotifier
$this->send_emails = (bool)psm_get_conf('email_status'); $this->send_emails = (bool)psm_get_conf('email_status');
$this->send_sms = (bool)psm_get_conf('sms_status'); $this->send_sms = (bool)psm_get_conf('sms_status');
$this->send_webhook = (bool)psm_get_conf('webhook_status');
$this->send_pushover = (bool)psm_get_conf('pushover_status'); $this->send_pushover = (bool)psm_get_conf('pushover_status');
$this->send_telegram = (bool)psm_get_conf('telegram_status'); $this->send_telegram = (bool)psm_get_conf('telegram_status');
$this->send_jabber = (bool)psm_get_conf('jabber_status'); $this->send_jabber = (bool)psm_get_conf('jabber_status');
@ -149,6 +156,7 @@ class StatusNotifier
if ( if (
!$this->send_emails && !$this->send_emails &&
!$this->send_sms && !$this->send_sms &&
!$this->send_webhook &&
!$this->send_pushover && !$this->send_pushover &&
!$this->send_telegram && !$this->send_telegram &&
!$this->send_jabber && !$this->send_jabber &&
@ -175,6 +183,7 @@ class StatusNotifier
'error', 'error',
'email', 'email',
'sms', 'sms',
'webhook',
'pushover', 'pushover',
'telegram', 'telegram',
'jabber', 'jabber',
@ -245,7 +254,11 @@ class StatusNotifier
// yay lets wake those nerds up! // yay lets wake those nerds up!
$this->notifyByTxtMsg($users); $this->notifyByTxtMsg($users);
} }
// check if webhook is enabled for this server
if ($this->send_webhook && $this->server['webhook'] == 'yes') {
// yay lets wake those nerds up!
$this->combine ? $this->setCombi('webhook') : $this->notifyByWebhook($users);
}
// check if pushover is enabled for this server // check if pushover is enabled for this server
if ($this->send_pushover && $this->server['pushover'] == 'yes') { if ($this->send_pushover && $this->server['pushover'] == 'yes') {
// yay lets wake those nerds up! // yay lets wake those nerds up!
@ -258,7 +271,7 @@ class StatusNotifier
} }
if ($this->send_jabber && $this->server['jaber'] == 'yes') { if ($this->send_jabber && $this->server['jaber'] == 'yes') {
$this->combine ? $this->setCombi('jabber') : $this->notifyByJabber($users); $this->combine ? $this->setCombi('jabber') : $this->notifyByJabber($users);
} }
return $notify; return $notify;
@ -461,7 +474,7 @@ class StatusNotifier
$pushover->setTitle($title); $pushover->setTitle($title);
$pushover->setMessage(str_replace('<br/>', "\n", $message)); $pushover->setMessage(str_replace('<br/>', "\n", $message));
$pushover->setUrl(psm_build_url()); $pushover->setUrl(psm_build_url());
$pushover->setUrlTitle(psm_get_lang('system', 'title')); $pushover->setUrlTitle(psm_get_conf('site_title', psm_get_lang('system', 'title')));
// Log // Log
if (psm_get_conf('log_pushover')) { if (psm_get_conf('log_pushover')) {
@ -482,7 +495,48 @@ class StatusNotifier
$pushover->send(); $pushover->send();
} }
} }
/**
* This functions performs the webhook notifications
*
* @param \PDOStatement $users
* @param array $combi contains message and subject (optional)
* @return void
*/
protected function notifyByWebhook($users, $combi = array())
{
foreach ($users as $k => $user) {
if (trim($user['webhook_url']) == '') {
unset($users[$k]);
}
}
$webhook = psm_build_webhook();
$message = key_exists('message', $combi) ?
$combi['message'] :
psm_parse_msg($this->status_new, 'webhook_message', $this->server);
$message = str_replace('<br/>', "\n", $message);
$message = str_replace('<br>', "\n", $message);
$title = key_exists('subject', $combi) ?
$combi['subject'] :
psm_parse_msg($this->status_new, 'webhook_title', $this->server);
// Log
if (psm_get_conf('log_webhook')) {
$log_id = psm_add_log($this->server_id, 'webhook', $message);
}
// send notifications to all users
foreach ($users as $user) {
// Log
if (!empty($log_id)) {
psm_add_log_user($log_id, $user['user_id']);
}
$webhook->setUrl($user['webhook_url']);
$webhook->setJson($user['webhook_json']);
$webhook->sendWebhook($message);
}
}
/** /**
* This functions performs the text message notifications * This functions performs the text message notifications
* *
@ -562,52 +616,52 @@ class StatusNotifier
} }
} }
/** /**
* @param array $users * @param array $users
* @param array $combi * @param array $combi
*/ */
protected function notifyByJabber($users, $combi = []) protected function notifyByJabber($users, $combi = [])
{ {
// Remove users that have no jabber // Remove users that have no jabber
foreach ($users as $k => $user) { foreach ($users as $k => $user) {
if (trim($user['jabber']) === '') { if (trim($user['jabber']) === '') {
unset($users[$k]); unset($users[$k]);
} }
} }
// Validation // Validation
if (empty($users)) { if (empty($users)) {
return; return;
} }
// Message // Message
$message = key_exists('message', $combi) ? $message = key_exists('message', $combi) ?
$combi['message'] : $combi['message'] :
psm_parse_msg($this->status_new, 'jabber_message', $this->server); psm_parse_msg($this->status_new, 'jabber_message', $this->server);
// Log // Log
if (psm_get_conf('log_jabber')) { if (psm_get_conf('log_jabber')) {
$log_id = psm_add_log($this->server_id, 'jabber', $message); $log_id = psm_add_log($this->server_id, 'jabber', $message);
} }
$usersJabber = []; $usersJabber = [];
foreach ($users as $user) { foreach ($users as $user) {
// Log // Log
if (!empty($log_id)) { if (!empty($log_id)) {
psm_add_log_user($log_id, $user['user_id']); psm_add_log_user($log_id, $user['user_id']);
} }
$usersJabber[] = $user['jabber']; $usersJabber[] = $user['jabber'];
} }
// Jabber // Jabber
psm_jabber_send_message( psm_jabber_send_message(
psm_get_conf('jabber_host'), psm_get_conf('jabber_host'),
psm_get_conf('jabber_username'), psm_get_conf('jabber_username'),
psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')),
$usersJabber, $usersJabber,
$message, $message,
(trim(psm_get_conf('jabber_port')) !== '' ? (int)psm_get_conf('jabber_port') : null), (trim(psm_get_conf('jabber_port')) !== '' ? (int)psm_get_conf('jabber_port') : null),
(trim(psm_get_conf('jabber_domain')) !== '' ? psm_get_conf('jabber_domain') : null) (trim(psm_get_conf('jabber_domain')) !== '' ? psm_get_conf('jabber_domain') : null)
); );
} }
/** /**
@ -619,15 +673,15 @@ class StatusNotifier
{ {
// find all the users with this server listed // find all the users with this server listed
$users = $this->db->query(' $users = $this->db->query('
SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`, `u`.`pushover_key`, SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`, `u`.`pushover_key`, `u`.`webhook_url`,`u`.`webhook_json`,
`u`.`pushover_device`, `u`.`telegram_id`, `u`.`pushover_device`, `u`.`telegram_id`,
`u`.`jabber` `u`.`jabber`
FROM `' . PSM_DB_PREFIX . 'users` AS `u` FROM `' . PSM_DB_PREFIX . 'users` AS `u`
JOIN `' . PSM_DB_PREFIX . "users_servers` AS `us` ON ( JOIN `' . PSM_DB_PREFIX . "users_servers` AS `us` ON (
`us`.`user_id`=`u`.`user_id` `us`.`user_id`=`u`.`user_id`
AND `us`.`server_id` = {$server_id} AND `us`.`server_id` = {$server_id}
) )
"); ");
return $users; return $users;
} }
} }

View File

@ -89,7 +89,7 @@ class StatusUpdater
$this->error = ''; $this->error = '';
$this->header = ''; $this->header = '';
$this->curl_info = ''; $this->curl_info = '';
$this->rtime = ''; $this->rtime = 0;
// get server info from db // get server info from db
$this->server = $this->db->selectRow(PSM_DB_PREFIX . 'servers', array( $this->server = $this->db->selectRow(PSM_DB_PREFIX . 'servers', array(
@ -175,41 +175,14 @@ class StatusUpdater
*/ */
protected function updatePing($max_runs, $run = 1) protected function updatePing($max_runs, $run = 1)
{ {
if ($max_runs == null || $max_runs > 1) { // Settings
$max_runs = 1; $max_runs = ($max_runs == null || $max_runs > 1) ? 1 : $max_runs;
} $server_ip = escapeshellcmd($this->server['ip']);
$result = null; $os_is_windows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// Execute ping
$pingCommand = 'ping6'; $status = $os_is_windows ?
$serverIp = $this->server['ip']; $this->pingFromWindowsMachine($server_ip, $max_runs) :
if (filter_var($serverIp,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false){ $this->pingFromNonWindowsMachine($server_ip, $max_runs);
$pingCommand = 'ping';
}
$txt = exec($pingCommand . " -c " . $max_runs . " " . $serverIp . " 2>&1", $output);
// Non-greedy match on filler
$re1 = '.*?';
// Uninteresting: float
$re2 = '[+-]?\\d*\\.\\d+(?![-+0-9\\.])';
// Non-greedy match on filler
$re3 = '.*?';
// Float 1
$re4 = '([+-]?\\d*\\.\\d+)(?![-+0-9\\.])';
if (preg_match_all("/" . $re1 . $re2 . $re3 . $re4 . "/is", $txt, $matches)) {
$result = $matches[1][0];
}
if (substr($output[0],0,4) == 'PING' && strpos($output[count($output)-2],'packets transmitted')){
$result = 0;
}
if (!is_null($result)) {
$this->header = $output[0];
$status = true;
} else {
$this->header = "-";
$this->error = $output[0];
$status = false;
}
//Divide by a thousand to convert to milliseconds
$this->rtime = $result / 1000;
// check if server is available and rerun if asked. // check if server is available and rerun if asked.
if (!$status && $run < $max_runs) { if (!$status && $run < $max_runs) {
@ -233,7 +206,7 @@ class StatusUpdater
$starttime = microtime(true); $starttime = microtime(true);
$serverIp = $this->server['ip']; $serverIp = $this->server['ip'];
if (filter_var($serverIp,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false){ if (filter_var($serverIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
$serverIp = "[$serverIp]"; $serverIp = "[$serverIp]";
} }
$fp = @fsockopen($serverIp, $this->server['port'], $errno, $this->error, $timeout); $fp = @fsockopen($serverIp, $this->server['port'], $errno, $this->error, $timeout);
@ -425,7 +398,9 @@ class StatusUpdater
!empty($this->curl_info['certinfo']) && !empty($this->curl_info['certinfo']) &&
$server['ssl_cert_expiry_days'] > 0 $server['ssl_cert_expiry_days'] > 0
) { ) {
$cert_expiration_date = strtotime($this->curl_info['certinfo'][0]['Expire date']); $certinfo = reset($this->curl_info['certinfo']);
$certinfo = openssl_x509_parse($certinfo['Cert']);
$cert_expiration_date = $certinfo['validTo_time_t'];
$expiration_time = $expiration_time =
round((int)($cert_expiration_date - time()) / 86400); round((int)($cert_expiration_date - time()) / 86400);
$latest_time = time() + (86400 * $server['ssl_cert_expiry_days']); $latest_time = time() + (86400 * $server['ssl_cert_expiry_days']);
@ -449,4 +424,87 @@ class StatusUpdater
$this->db->save(PSM_DB_PREFIX . 'servers', $save, array('server_id' => $this->server_id)); $this->db->save(PSM_DB_PREFIX . 'servers', $save, array('server_id' => $this->server_id));
} }
} }
/**
* Ping from a Windows Machine
* @param string $server_id
* @param int $max_runs
* @return boolean
*/
private function pingFromWindowsMachine($server_ip, $max_runs)
{
// Windows / Linux variant: use socket on Windows, commandline on Linux
// socket ping - Code from http://stackoverflow.com/a/20467492
// save response time
$starttime = microtime(true);
// set ping payload
$package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost";
$socket = socket_create(AF_INET, SOCK_RAW, 1);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 10, 'usec' => 0));
socket_connect($socket, $server_ip, null);
socket_send($socket, $package, strLen($package), 0);
// socket_read returns a string or false
$status = socket_read($socket, 255) !== false ? true : false;
if ($status) {
$this->header = "Success.";
} else {
$this->error = "Couldn't create socket [" . $errorcode . "]: " . socket_strerror(socket_last_error());
}
$this->rtime = microtime(true) - $starttime;
socket_close($socket);
return $status;
}
/**
* Ping from a non Windows Machine
* @param string $server_id
* @param int $max_runs
* @param string $ping_command
* @return boolean
*/
private function pingFromNonWindowsMachine($server_ip, $max_runs)
{
// Choose right ping version, ping6 for IPV6, ping for IPV4
$ping_command = filter_var($server_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false ? 'ping6' : 'ping';
// execute PING
exec($ping_command . " -c " . $max_runs . " " . $server_ip . " 2>&1", $output);
// Check if output is PING and if transmitted packets is equal to received packets.
preg_match(
'/^(\d{1,3}) packets transmitted, (\d{1,3}).*$/',
$output[count($output) - 2],
$output_package_loss
);
if (
substr($output[0], 0, 4) == 'PING' &&
!empty($output_package_loss) &&
$output_package_loss[1] === $output_package_loss[2]
) {
// Gets avg from 'round-trip min/avg/max/stddev = 7.109/7.109/7.109/0.000 ms'
preg_match_all("/(\d+\.\d+)/", $output[count($output) - 1], $result);
// Converted to milliseconds
$this->rtime = floatval($result[0][1]) / 1000;
$this->header = "";
foreach ($output as $key => $value) {
$this->header .= $value . "\n";
}
return true;
}
$this->header = "-";
foreach ($output as $key => $value) {
$this->header .= $value . "\n";
}
$this->error = $output[count($output) - 2];
return false;
}
} }

View File

@ -31,31 +31,33 @@
<body> <body>
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark"> <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="index.php">{{ title }}</a> <div class="container-fluid">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" <a class="navbar-brand" href="index.php">{{ title }}</a>
aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar"
<span class="navbar-toggler-icon"></span> aria-expanded="false" aria-label="Toggle navigation">
</button> <span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar"> <div class="collapse navbar-collapse" id="navbar">
{{ html_menu|raw }} {{ html_menu|raw }}
</div> </div>
</div>
</nav> </nav>
{{ html_modal|raw }} {{ html_modal|raw }}
<main role="main" class="container"> <main role="main" class="container-fluid px-4">
<noscript> <noscript>
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
<b>Javascript is disabled!</b> PHP Server Monitor works best with JavaScript enabled! <b>Javascript is disabled!</b> PHP Server Monitor works best with JavaScript enabled!
</div> </div>
</noscript> </noscript>
{% if not user_level and subtitle %}<h1>{{ subtitle }}</h1>{% endif %} {% if not user_level and subtitle %}<h1>{{ subtitle }}</h1>{% endif %}
<div class="container">{{ header_accessories|raw }}</div> <div class="container-fluid">{{ header_accessories|raw }}</div>
{% for msg in messages %} {% for msg in messages %}
<div class="alert alert-{{ msg.class }}" role="alert"> <div class="alert alert-{{ msg.class }}" role="alert">
<i class="fas fa-{{ msg.icon }}"></i> {{ msg.message|raw }} <i class="fas fa-{{ msg.icon }}"></i> {{ msg.message|raw }}
</div> </div>
{% endfor %} {% endfor %}
<div class="container"> <div class="container-fluid">
<div class="row">{{ html_sidebar|raw }}</div> <div class="row">{{ html_sidebar|raw }}</div>
<div class="row" id="content">{{ html_content|raw }}</div> <div class="row" id="content">{{ html_content|raw }}</div>
</div> </div>
@ -74,7 +76,7 @@
</footer> </footer>
{% endblock %} {% endblock %}
{% endif %} {% endif %}
<script src="src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js"></script> <script src="src/templates/default/static/plugin/jquery/jquery-3.5.1.min.js"></script>
<script src="src/templates/default/static/plugin/popper.js/popper.min.js"></script> <script src="src/templates/default/static/plugin/popper.js/popper.min.js"></script>
<script src="src/templates/default/static/plugin/bootstrap/js/dist/index.js"></script> <script src="src/templates/default/static/plugin/bootstrap/js/dist/index.js"></script>
<script src="src/templates/default/static/plugin/bootstrap/js/dist/util.js"></script> <script src="src/templates/default/static/plugin/bootstrap/js/dist/util.js"></script>

View File

@ -30,7 +30,12 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {{ jabber_active }}" id="config-jabber-tab" data-toggle="tab" href="#config-jabber" <a class="nav-link {{ jabber_active }}" id="config-jabber-tab" data-toggle="tab" href="#config-jabber"
role="tab" aria-controls="config-jabber" aria-selected="{% if jabber_active %}true{% else %}false{% endif %}">{{ role="tab" aria-controls="config-jabber" aria-selected="{% if jabber_active %}true{% else %}false{% endif %}">{{
label_tab_jabber }}</a> label_tab_jabber }}</a>
</li>
<li class="nav-item">
<a class="nav-link {{ webhook_active }}" id="config-webhook-tab" data-toggle="tab" href="#config-webhook" role="tab"
aria-controls="config-webhook" aria-selected="{% if webhook_active %}true{% else %}false{% endif %}">{{
label_tab_webhook }}</a>
</li> </li>
</ul> </ul>
<!-- Tab panes --> <!-- Tab panes -->
@ -41,6 +46,8 @@
<legend>{{ label_general }}</legend> <legend>{{ label_general }}</legend>
<!-- Update check --> <!-- Update check -->
{{ macro.input_checkbox("show_update", "show_update[]", label_show_update, show_update_checked) }} {{ macro.input_checkbox("show_update", "show_update[]", label_show_update, show_update_checked) }}
<!-- Site title -->
{{ macro.input_field("text", "site_title", null, "site_title", label_site_title, site_title, label_site_title, "255", null, null, null, null, true) }}
<!-- Language --> <!-- Language -->
{{ macro.input_select("language", "language", label_language, languages, language_current) }} {{ macro.input_select("language", "language", label_language, languages, language_current) }}
<!-- Auto refresh --> <!-- Auto refresh -->
@ -48,6 +55,8 @@
<!-- Password encryption key --> <!-- Password encryption key -->
<!-- TODO how does the encryption function works currently? --> <!-- TODO how does the encryption function works currently? -->
{{ macro.input_field("text", "password_encrypt_key", null, "password_encrypt_key", label_password_encrypt_key, password_encrypt_key, "cab03a766...", "40", "password_encrypt_key_help", label_password_encrypt_key_note) }} {{ macro.input_field("text", "password_encrypt_key", null, "password_encrypt_key", label_password_encrypt_key, password_encrypt_key, "cab03a766...", "40", "password_encrypt_key_help", label_password_encrypt_key_note) }}
<!-- Custom user agent -->
{{ macro.input_field("text", "user_agent", null, "user_agent", label_user_agent, user_agent, "Mozilla/5.0...", "255", "user_agent_key_help", label_user_agent_key_note) }}
</fieldset> </fieldset>
<!-- Notification settings --> <!-- Notification settings -->
<fieldset> <fieldset>
@ -179,6 +188,24 @@
{{ macro.button_save("jabber_submit", label_save) }} {{ macro.button_save("jabber_submit", label_save) }}
</fieldset> </fieldset>
</div> </div>
<div class="tab-pane {{ webhook_active }}" id="config-webhook" role="tabpanel" aria-labelledby="config-webhook-tab">
<fieldset>
<legend>{{ label_settings_webhook }}</legend>
<p>{{ label_webhook_description|raw }}</p>
<!-- enable webhooks -->
{{ macro.input_checkbox("webhook_status", "webhook_status", label_webhook_status, webhook_status_checked) }}
<!-- enable webhook log -->
{{ macro.input_checkbox("log_webhook", "log_webhook", label_log_webhook, log_webhook_checked) }}
<!-- webhook url -->
<!-- {{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, webhook_url, label_webhook_url, "255", "webhook_url_help", label_webhook_url_description) }} -->
<!-- webhook json -->
<!-- {{ macro.input_field("text", "webhook_json", null, "webhook_json", label_webhook_json, webhook_json, label_webhook_json, "255", "webhook_json_help", label_webhook_json_description) }} -->
{{ macro.button_test("testWebhook", label_test) }}
{{ macro.input_hidden("test_webhook", "0") }}
{{ macro.button_save("webhook_submit", label_save) }}
</fieldset>
</div>
</div> </div>
{{ macro.input_csrf() }} {{ macro.input_csrf() }}
</form> </form>

View File

@ -1,5 +1,7 @@
<script type="text/javascript" src="src/templates/default/static/plugin/momentjs/moment.js"></script> <script type="text/javascript" src="src/templates/default/static/plugin/momentjs/moment.js"></script>
<script type="text/javascript" src="src/templates/default/static/plugin/chartjs/chart-2.7.3.min.js"></script> <script type="text/javascript" src="src/templates/default/static/plugin/chartjs/chart-2.7.3.min.js"></script>
<script type="text/javascript" src="src/templates/default/static/plugin/hammer/hammer.min.js"></script>
<script type="text/javascript" src="src/templates/default/static/plugin/chartjs/plugin-zoom.min.js"></script>
{% for graph in graphs %} {% for graph in graphs %}
<div class="chart-container col-10" style="position: relative; width:60vw"> <div class="chart-container col-10" style="position: relative; width:60vw">
<canvas id="{{ graph.id }}">Your browser does not support the canvas element.</canvas> <canvas id="{{ graph.id }}">Your browser does not support the canvas element.</canvas>
@ -20,7 +22,7 @@
<span id="needle" style="transform: rotate({{ ((graph.uptime|round/100)*180)|round }}deg);"></span> <span id="needle" style="transform: rotate({{ ((graph.uptime|round/100)*180)|round }}deg);"></span>
</div><br> </div><br>
{% endif %} {% endif %}
{{ graph.info.0.label }}: {{ graph.info.0.value }}s {{ graph.info.0.label }}: {{ graph.info.0.value * 1000 }} ms
</div> </div>
{% if graph.id == 'history_short' %} {% if graph.id == 'history_short' %}
@ -30,7 +32,7 @@
data: { data: {
datasets: [ datasets: [
{ {
data: [{{ graph.lines.offline.value }}], data: {{ graph.lines.offline.value|raw }},
label: '{{ graph.lines.offline.name }}', label: '{{ graph.lines.offline.name }}',
backgroundColor: '#dc3545', backgroundColor: '#dc3545',
borderColor: '#dc3545', borderColor: '#dc3545',
@ -41,7 +43,7 @@
spanGaps: false, spanGaps: false,
}, },
{ {
data: [{{ graph.lines.online.value }}], data: {{ graph.lines.online.value|raw }},
label: '{{graph.lines.online.name }}', label: '{{graph.lines.online.name }}',
fill: false, fill: false,
spanGaps: false, spanGaps: false,
@ -72,6 +74,25 @@
source: 'auto', source: 'auto',
} }
}] }]
},
plugins: {
zoom: {
pan: {
enabled: true,
mode: 'x',
rangeMax: {
x: new Date,
},
},
zoom: {
enabled: true,
mode: 'x',
rangeMax: {
x: new Date,
},
speed: 0.05,
}
}
} }
} }
}); });
@ -99,7 +120,7 @@
datasets: [ datasets: [
{% for key,line in graph.lines %} {% for key,line in graph.lines %}
{ {
data: [{{ line.value|raw }}], data: {{ line.value|raw }},
label: '{{ line.name }}', label: '{{ line.name }}',
backgroundColor: colors['{{key}}'], backgroundColor: colors['{{key}}'],
borderColor: colors['{{key}}'], borderColor: colors['{{key}}'],
@ -133,6 +154,25 @@
source: 'auto', source: 'auto',
} }
}] }]
},
plugins: {
zoom: {
pan: {
enabled: true,
mode: 'x',
rangeMax: {
x: new Date,
},
},
zoom: {
enabled: true,
mode: 'x',
rangeMax: {
x: new Date,
},
speed: 0.05,
}
}
} }
} }
}); });

View File

@ -9,7 +9,7 @@
<th scope="col">{{ label_domain }}</th> <th scope="col">{{ label_domain }}</th>
<th scope="col" style="width: 5%;">{{ label_port }}</th> <th scope="col" style="width: 5%;">{{ label_port }}</th>
<th scope="col" style="width: 8%;">{{ label_type }}</th> <th scope="col" style="width: 8%;">{{ label_type }}</th>
<th scope="col" style="width: 8%;">{{ label_rtime }}</th> <th scope="col" style="width: 8%;">{{ label_rtime }} (ms)</th>
<th scope="col" style="width: 10%;">{{ label_last_online }}</th> <th scope="col" style="width: 10%;">{{ label_last_online }}</th>
<th scope="col" style="width: 10%;">{{ label_last_offline }}</th> <th scope="col" style="width: 10%;">{{ label_last_offline }}</th>
<th scope="col" style="width: 10%;">{{ label_monitoring }}</th> <th scope="col" style="width: 10%;">{{ label_monitoring }}</th>
@ -41,7 +41,7 @@
<td><div class="content">{{ server.ip|raw }}</div></td> <td><div class="content">{{ server.ip|raw }}</div></td>
<td>{{ server.port }}</td> <td>{{ server.port }}</td>
<td>{{ server.type }}</td> <td>{{ server.type }}</td>
<td>{{ server.rtime }}</td> <td>{{ (server.rtime * 1000)|round(2) }}</td>
<td><div class="content">{{ server.last_online }}</div></td> <td><div class="content">{{ server.last_online }}</div></td>
<td><div class="content">{{ server.last_offline }}</div></td> <td><div class="content">{{ server.last_offline }}</div></td>
<td> <td>
@ -73,7 +73,10 @@
<i class="fas fa-circle" title="{{ label_jabber }}"></i> <i class="fas fa-circle" title="{{ label_jabber }}"></i>
<span class="fa-layers-text fa-inverse" style="font-weight:400; font-size:75%">J</span> <span class="fa-layers-text fa-inverse" style="font-weight:400; font-size:75%">J</span>
</span> </span>
{% endif %} {% endif %}
{% if server.webhook|lower == 'yes' and config.webhook|lower %}
<i class="fas fa-hashtag" title="{{ label_webhook }}"></i>
{% endif %}
</td> </td>
{% if user_level == 10 %} {% if user_level == 10 %}
<td> <td>

View File

@ -143,7 +143,9 @@
<!-- Telegram --> <!-- Telegram -->
{{ macro.input_select_monitoring("telegram", "telegram", label_send_telegram, edit_telegram_selected, label_yes, label_no, warning_telegram, label_warning_telegram) }} {{ macro.input_select_monitoring("telegram", "telegram", label_send_telegram, edit_telegram_selected, label_yes, label_no, warning_telegram, label_warning_telegram) }}
<!-- Jabber --> <!-- Jabber -->
{{ macro.input_select_monitoring("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }} {{ macro.input_select_monitoring("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }}
<!-- Webhook -->
{{ macro.input_select_monitoring("webhook", "webhook", label_send_webhook, edit_webhook_selected, label_yes, label_no, warning_webhook, label_warning_webhook) }}
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>

View File

@ -1,6 +1,6 @@
{% import 'main/macros.tpl.html' as macro %} {% import 'main/macros.tpl.html' as macro %}
{{ macro.input_csrf() }} {{ macro.input_csrf() }}
<div class="container"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="card text-white text-center col-md-2 pl-0 pr-0 mb-4 {% if status|lower == 'on' %}bg-success{% elseif status|lower == 'warning' %}bg-warning{% elseif status|lower == 'off' %}bg-danger{% endif %}"> <div class="card text-white text-center col-md-2 pl-0 pr-0 mb-4 {% if status|lower == 'on' %}bg-success{% elseif status|lower == 'warning' %}bg-warning{% elseif status|lower == 'off' %}bg-danger{% endif %}">
<div class="card-body d-flex align-items-center justify-content-center"> <div class="card-body d-flex align-items-center justify-content-center">
@ -51,7 +51,7 @@
<li class="list-group-item"> <li class="list-group-item">
<dl class="row"> <dl class="row">
<dt class="col-md-4">{{ label_rtime }}:</dt> <dt class="col-md-4">{{ label_rtime }}:</dt>
<dd class="col-md-8">{{ rtime }} {{ label_seconds }}</dd> <dd class="col-md-8">{{ (rtime * 1000)|round(2) }} {{ label_milliseconds }}</dd>
</dl> </dl>
</li> </li>
</ul> </ul>
@ -347,13 +347,55 @@
<i class="fas fa-question-circle float-right" title="Value from database should either be yes or no."></i> <i class="fas fa-question-circle float-right" title="Value from database should either be yes or no."></i>
<noscript>&#8263</noscript> <noscript>&#8263</noscript>
{% endif %} {% endif %}
</li> </li>
<li class="list-group-item">
{{ label_webhook }}:
{% if webhook|lower == 'yes' %}
<i class="fas fa-bell float-right"></i>
<noscript>&#10003</noscript>
{% elseif webhook|lower == 'no' %}
<i class="fas fa-bell-slash float-right"></i>
<noscript>&#10005</noscript>
{% else %}
<i class="fas fa-question-circle float-right" title="Value from database should either be yes or no."></i>
<noscript>&#8263</noscript>
{% endif %}
</li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
{{ html_history|raw }} {{ html_history|raw }}
</div> </div>
{% if log_entries %}
<div class="row mt-4">
<div class="card col-md-12 pl-0 pr-0">
<div class="card-header">
{{ label_log_title }}
</div>
<div class="card-body d-flex align-items-center justify-content-center">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th scope="col" style="width: 15%;">{{ label_date }}</th>
<th scope="col">{{ label_message }}</th>
</tr>
</thead>
<tbody>
{% for entry in log_entries %}
<tr>
<td><time>{{ entry.datetime_format }}</time></td>
<td class="full">{{ entry.message|raw }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
<div class="modal fade" id="modal_last_output" tabindex="-1" role="dialog" aria-labelledby="modal_last_output_label" aria-hidden="true"> <div class="modal fade" id="modal_last_output" tabindex="-1" role="dialog" aria-labelledby="modal_last_output_label" aria-hidden="true">
<div class="modal-dialog" style="width:75%;max-width: 100%" role="document"> <div class="modal-dialog" style="width:75%;max-width: 100%" role="document">

View File

@ -1,10 +1,10 @@
{% import 'main/macros.tpl.html' as macro %} {% import 'main/macros.tpl.html' as macro %}
{{ macro.input_csrf() }} {{ macro.input_csrf() }}
<div class="container"> <div class="container-fluid">
<div id="flow-layout" class="{{ block_layout_active }}" aria-labelledby="block-layout"> <div id="flow-layout" class="{{ block_layout_active }}" aria-labelledby="block-layout">
<div class="row"> <div class="row">
{% for server in servers_offline %} {% for server in servers_offline %}
<div class="col-sm-4 col-md-3"> <div class="col-sm-4 col-md-3 col-xl-2">
<div class="card text-white bg-danger mb-3" onclick="window.location.href='{{ server.url_view|raw }}'"> <div class="card text-white bg-danger mb-3" onclick="window.location.href='{{ server.url_view|raw }}'">
<div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_offline }})</span></a></div> <div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_offline }})</span></a></div>
<div class="card-body"> <div class="card-body">
@ -17,7 +17,7 @@
</div> </div>
{% endfor %} {% endfor %}
{% for server in servers_warning %} {% for server in servers_warning %}
<div class="col-sm-4 col-md-3"> <div class="col-sm-4 col-md-3 col-xl-2">
<div class="card text-white bg-warning mb-3" onclick="window.location.href='{{ server.url_view|raw }}'"> <div class="card text-white bg-warning mb-3" onclick="window.location.href='{{ server.url_view|raw }}'">
<div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_warning }})</span></a></div> <div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_warning }})</span></a></div>
<div class="card-body"> <div class="card-body">
@ -30,14 +30,14 @@
</div> </div>
{% endfor %} {% endfor %}
{% for server in servers_online %} {% for server in servers_online %}
<div class="col-sm-4 col-md-3"> <div class="col-sm-4 col-md-3 col-xl-2">
<div class="card text-white bg-success mb-3" onclick="window.location.href='{{ server.url_view|raw }}'"> <div class="card text-white bg-success mb-3" onclick="window.location.href='{{ server.url_view|raw }}'">
<div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_online }})</span></a></div> <div class="card-header"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_online }})</span></a></div>
<div class="card-body"> <div class="card-body">
<p class="card-text"> <p class="card-text">
{{ label_last_online }}: {{ server.last_online_nice }}<br> {{ label_last_online }}: {{ server.last_online_nice }}<br>
{{ label_last_offline }}: {{ server.last_offline_nice }} {{ server.last_offline_duration_nice }}<br> {{ label_last_offline }}: {{ server.last_offline_nice }} {{ server.last_offline_duration_nice }}<br>
{{ label_rtime }}: {{ server.rtime }} {{ label_rtime }}: {{ (server.rtime * 1000)|round(2) }} ms
</p> </p>
</div> </div>
</div> </div>
@ -97,7 +97,7 @@
<th class="full"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_online }})</span></a></th> <th class="full"><a href="{{ server.url_view|raw }}" class="text-white">{{ server.label }}<span class="sr-only"> ({{ label_online }})</span></a></th>
<td>{{ server.last_online_nice }}</td> <td>{{ server.last_online_nice }}</td>
<td>{{ server.last_offline_nice }} {{ server.last_offline_duration_nice }}</td> <td>{{ server.last_offline_nice }} {{ server.last_offline_duration_nice }}</td>
<td>{{ server.rtime }}s</td> <td>{{ (server.rtime * 1000)|round(2) }} ms</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -24,9 +24,9 @@
<legend>{{ label_pushover }}</legend> <legend>{{ label_pushover }}</legend>
<p>{{ label_pushover_description|raw }}</p> <p>{{ label_pushover_description|raw }}</p>
<!-- pushover key --> <!-- pushover key -->
{{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, pushover_key, label_pushover_key, "255", "pushover_key_help", pushover_key_description) }} {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, pushover_key, label_pushover_key, "255", "pushover_key_help", label_pushover_key_description) }}
<!-- pushover device --> <!-- pushover device -->
{{ macro.input_field("text", "pushover_device", null, "pushover_device", label_pushover_device, pushover_device, label_pushover_device, "255", "pushover_device_help", pushover_device_description) }} {{ macro.input_field("text", "pushover_device", null, "pushover_device", label_pushover_device, pushover_device, label_pushover_device, "255", "pushover_device_help", label_pushover_device_description) }}
</fieldset> </fieldset>
<!-- Telegram settings --> <!-- Telegram settings -->
<fieldset> <fieldset>
@ -36,7 +36,7 @@
<div class="form-group"> <div class="form-group">
<a class="btn btn-primary mb-2" href="{{ telegram_get_chat_id_url }}">{{ label_telegram_get_chat_id }}</a> <a class="btn btn-primary mb-2" href="{{ telegram_get_chat_id_url }}">{{ label_telegram_get_chat_id }}</a>
</div> </div>
{{ macro.input_field("text", "telegram_id", null, "telegram_id", label_telegram_chat_id, telegram_id, label_telegram_chat_id, "255", "telegram_id_help", telegram_id_description) }} {{ macro.input_field("text", "telegram_id", null, "telegram_id", label_telegram_chat_id, telegram_id, label_telegram_chat_id, "255", "telegram_id_help", label_telegram_id_description) }}
<button class="btn btn-primary show-modal" data-toggle="modal" data-modal-id="activateTelegram">{{ label_activate_telegram }}</button> <button class="btn btn-primary show-modal" data-toggle="modal" data-modal-id="activateTelegram">{{ label_activate_telegram }}</button>
{{ macro.input_hidden("activate_telegram", "0") }} {{ macro.input_hidden("activate_telegram", "0") }}
</fieldset> </fieldset>
@ -44,7 +44,16 @@
<fieldset> <fieldset>
<legend>{{ label_jabber }}</legend> <legend>{{ label_jabber }}</legend>
<!-- jabber --> <!-- jabber -->
{{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", jabber_description) }} {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", label_jabber_description) }}
</fieldset> </fieldset>
<!-- Webhook settings -->
<fieldset>
<legend>{{ label_webhook }}</legend>
<p>{{ label_webhook_description|raw }}</p>
<!-- webhook url -->
{{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, webhook_url, "https://test.com/api/abcde", "255", "webhook_url_help", label_webhook_url_description) }}
<!-- webhook json -->
{{ macro.input_field("text", "webhook_json", null, "webhook_json", label_webhook_json, webhook_json, "{\"text\":\"servermon: #message\"}", "255", "webhook_json_help", label_webhook_json_description) }}
</fieldset>
{{ macro.button_save(null, label_save) }} {{ macro.button_save(null, label_save) }}
</form> </form>

View File

@ -17,6 +17,10 @@
{{ macro.input_field("email", "email", null, "email", label_email, edit_value_email, null, "255") }} {{ macro.input_field("email", "email", null, "email", label_email, edit_value_email, null, "255") }}
<!-- Mobile --> <!-- Mobile -->
{{ macro.input_field("tel", "mobile", null, "mobile", label_mobile, edit_value_mobile, null, "20") }} {{ macro.input_field("tel", "mobile", null, "mobile", label_mobile, edit_value_mobile, null, "20") }}
<!-- Webhook_url -->
{{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, edit_value_webhook_url, null, "255") }}
<!-- Webhook_json -->
{{ macro.input_field("text", "webhook_json", null, "webhook_json", label_webhook_json, edit_value_webhook_json, null, "255") }}
<!-- Pushover_key --> <!-- Pushover_key -->
{{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, edit_value_pushover_key, null, "255") }} {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, edit_value_pushover_key, null, "255") }}
<!-- Pushover_device --> <!-- Pushover_device -->

View File

@ -1,2 +1,2 @@
html{position:relative;min-height:100%}html[dir='rtl'] #auto_refresh_description,html[dir='rtl'] #log_retention_period_help{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}html[dir='ltr'] #auto_refresh_description,html[dir='ltr'] #log_retention_period_help{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}body{padding-top:4.5rem;margin-bottom:80px}.footer{position:absolute;bottom:0;width:100%;height:60px;line-height:60px;background-color:#f5f5f5}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,0.64)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,0.85)}dl,dt,dd{margin-bottom:0}footer .text-muted{color:#4C5557 !important}a,button,.nav-link{min-height:44px !important;min-width:44px !important}a.icon{text-decoration:none;cursor:pointer;padding-left:10px}form.form-signin input[type="text"],form.form-reset input[type="text"]{border-bottom-left-radius:0;border-bottom-right-radius:0}form.form-signin input[type="password"]{border-top-left-radius:0;border-top-right-radius:0}form.form-reset input#input-password{border-radius:0}form.form-reset input#input-password-repeat{border-top-left-radius:0;border-top-right-radius:0}form.form-signin,form.form-forgot,form.form-reset{margin:auto}table{table-layout:fixed}th,td{max-width:1px}.content{word-wrap:break-word;overflow-wrap:break-word}table tr[visible='false'],.no-result{display:none}table tr[visible='true']{display:table-row}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:unset}#meter{border-radius:200px 200px 0 0;height:100px;margin:50px auto 0;overflow:hidden;position:relative;width:200px}#meter:before{background:#fbfbfb;border-radius:200px 200px 0 0;-webkit-box-shadow:3px 1px 8px rgba(0,0,0,0.15) inset;box-shadow:3px 1px 8px rgba(0,0,0,0.15) inset;content:"";height:100px;position:absolute;width:200px}#meter:after{background:#fff;border-radius:140px 140px 0 0;bottom:0;-webkit-box-shadow:3px 1px 8px rgba(0,0,0,0.15);box-shadow:3px 1px 8px rgba(0,0,0,0.15);content:"\a" attr(data-value) "%\a" attr(translation);font-size:1.5em;font-weight:100;height:80px;left:20px;line-height:25px;position:absolute;text-align:center;width:160px;z-index:3;white-space:pre}#needle{background:rgba(52,52,64,0.7);border-radius:4px;bottom:-4px;-webkit-box-shadow:3px -1px 4px rgba(0,0,0,0.4);box-shadow:3px -1px 4px rgba(0,0,0,0.4);display:block;height:8px;left:5px;position:absolute;width:95px;-webkit-transform-origin:100% 4px;transform-origin:100% 4px;-webkit-transition:all 1s;transition:all 1s;border-radius:4px;bottom:-4px;box-shadow:3px -1px 4px rgba(0,0,0,0.4);display:block;height:8px;left:5px;position:absolute;width:95px;transform-origin:100% 4px;transition:all 1s}.dropdown-menu.show{left:inherit;right:0px} html{position:relative;min-height:100%}html[dir='rtl'] #auto_refresh_description,html[dir='rtl'] #log_retention_period_help{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}html[dir='ltr'] #auto_refresh_description,html[dir='ltr'] #log_retention_period_help{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}body{padding-top:4.5rem;margin-bottom:80px}.container-fluid{max-width:1920px}.footer{position:absolute;bottom:0;width:100%;height:60px;line-height:60px;background-color:#f5f5f5}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,0.64)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,0.85)}dl,dt,dd{margin-bottom:0}footer .text-muted{color:#4C5557 !important}a,button,.nav-link{min-height:44px !important;min-width:44px !important}a.icon{text-decoration:none;cursor:pointer;padding-left:10px}form.form-signin input[type="text"],form.form-reset input[type="text"]{border-bottom-left-radius:0;border-bottom-right-radius:0}form.form-signin input[type="password"]{border-top-left-radius:0;border-top-right-radius:0}form.form-reset input#input-password{border-radius:0}form.form-reset input#input-password-repeat{border-top-left-radius:0;border-top-right-radius:0}form.form-signin,form.form-forgot,form.form-reset{margin:auto}table{table-layout:fixed}th,td{max-width:1px}.content{word-wrap:break-word;overflow-wrap:break-word}table tr[visible='false'],.no-result{display:none}table tr[visible='true']{display:table-row}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:unset}#meter{border-radius:200px 200px 0 0;height:100px;margin:50px auto 0;overflow:hidden;position:relative;width:200px}#meter:before{background:#fbfbfb;border-radius:200px 200px 0 0;-webkit-box-shadow:3px 1px 8px rgba(0,0,0,0.15) inset;box-shadow:3px 1px 8px rgba(0,0,0,0.15) inset;content:"";height:100px;position:absolute;width:200px}#meter:after{background:#fff;border-radius:140px 140px 0 0;bottom:0;-webkit-box-shadow:3px 1px 8px rgba(0,0,0,0.15);box-shadow:3px 1px 8px rgba(0,0,0,0.15);content:"\a" attr(data-value) "%\a" attr(translation);font-size:1.5em;font-weight:100;height:80px;left:20px;line-height:25px;position:absolute;text-align:center;width:160px;z-index:3;white-space:pre}#needle{background:rgba(52,52,64,0.7);border-radius:4px;bottom:-4px;-webkit-box-shadow:3px -1px 4px rgba(0,0,0,0.4);box-shadow:3px -1px 4px rgba(0,0,0,0.4);display:block;height:8px;left:5px;position:absolute;width:95px;-webkit-transform-origin:100% 4px;transform-origin:100% 4px;-webkit-transition:all 1s;transition:all 1s;border-radius:4px;bottom:-4px;box-shadow:3px -1px 4px rgba(0,0,0,0.4);display:block;height:8px;left:5px;position:absolute;width:95px;transform-origin:100% 4px;transition:all 1s}.dropdown-menu.show{left:inherit;right:0px}
/*# sourceMappingURL=style.min.css.map */ /*# sourceMappingURL=style.min.css.map */

View File

@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "AAAA,AAAA,IAAI,AAAC,CACD,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,IAAI,CACnB,AAED,AACI,IADA,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EACD,yBAAyB,CAD7B,IAAI,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EAED,0BAA0B,AAAC,CACvB,sBAAsB,CAAE,MAAM,CAC9B,yBAAyB,CAAE,MAAM,CACpC,AAGL,AACI,IADA,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EACD,yBAAyB,CAD7B,IAAI,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EAED,0BAA0B,AAAC,CACvB,uBAAuB,CAAE,MAAM,CAC/B,0BAA0B,CAAE,MAAM,CACrC,AAGL,AAAA,IAAI,AAAC,CACD,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,IAAI,CACtB,AAED,AAAA,OAAO,AAAC,CACJ,QAAQ,CAAE,QAAQ,CAClB,MAAM,CAAE,CAAC,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,WAAW,CAAE,IAAI,CACjB,gBAAgB,CAAE,OAAO,CAC5B,AAED,AAAA,YAAY,CAAC,WAAW,CAAC,SAAS,AAAC,CAC/B,KAAK,CAAE,sBAAwB,CAMlC,AAPD,AAGI,YAHQ,CAAC,WAAW,CAAC,SAAS,AAG7B,MAAM,CAHX,YAAY,CAAC,WAAW,CAAC,SAAS,AAI7B,MAAM,AAAC,CACJ,KAAK,CAAE,sBAAwB,CAClC,AAGL,AAAA,EAAE,CACF,EAAE,CACF,EAAE,AAAC,CACC,aAAa,CAAE,CAAC,CACnB,AAED,AAAA,MAAM,CAAC,WAAW,AAAC,CACf,KAAK,CAAE,kBAAkB,CAC5B,AAED,AAAA,CAAC,CACD,MAAM,CACN,SAAS,AAAC,CACN,UAAU,CAAE,eAAe,CAC3B,SAAS,CAAE,eAAe,CAC7B,AAED,AAAA,CAAC,AAAA,KAAK,AAAC,CACH,eAAe,CAAE,IAAI,CACrB,MAAM,CAAE,OAAO,CACf,YAAY,CAAE,IAAI,CACrB,AAED,AAAA,IAAI,AAAA,YAAY,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,EACvB,IAAI,AAAA,WAAW,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,CAAa,CAC/B,yBAAyB,CAAE,CAAC,CAC5B,0BAA0B,CAAE,CAAC,CAChC,AAED,AAAA,IAAI,AAAA,YAAY,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,UAAU,AAAf,CAAiB,CACpC,sBAAsB,CAAE,CAAC,CACzB,uBAAuB,CAAE,CAAC,CAC7B,AAED,AACI,IADA,AAAA,WAAW,CACX,KAAK,AAAA,eAAe,AAAC,CACjB,aAAa,CAAE,CAAC,CACnB,AAHL,AAKI,IALA,AAAA,WAAW,CAKX,KAAK,AAAA,sBAAsB,AAAC,CACxB,sBAAsB,CAAE,CAAC,CACzB,uBAAuB,CAAE,CAAC,CAC7B,AAGL,AAAA,IAAI,AAAA,YAAY,CAChB,IAAI,AAAA,YAAY,CAChB,IAAI,AAAA,WAAW,AAAC,CACZ,MAAM,CAAE,IAAI,CACf,AAED,AAAA,KAAK,AAAC,CACF,YAAY,CAAE,KAAK,CACtB,AAED,AAAA,EAAE,CAAE,EAAE,AAAC,CACH,SAAS,CAAC,GAAG,CAChB,AACD,AAAA,QAAQ,AAAC,CACL,SAAS,CAAC,UAAU,CACpB,aAAa,CAAC,UAAU,CAC3B,AAED,AAAA,KAAK,CAAC,EAAE,CAAA,AAAA,OAAC,CAAQ,OAAO,AAAf,EACT,UAAU,AAAC,CACP,OAAO,CAAE,IAAI,CAChB,AAED,AAAA,KAAK,CAAC,EAAE,CAAA,AAAA,OAAC,CAAQ,MAAM,AAAd,CAAgB,CACrB,OAAO,CAAE,SAAS,CACrB,AAED,AAAA,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,CACjD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,OAAO,CACxD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,MAAM,CACvD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,MAAM,AAAC,CACpD,KAAK,CAAE,KAAK,CACf,AAED,AAAA,MAAM,AAAC,CACH,aAAa,CAAE,eAAe,CAC9B,MAAM,CAAE,KAAK,CACb,MAAM,CAAE,WAAW,CACnB,QAAQ,CAAE,MAAM,CAChB,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,KAAK,CA4Bf,AAlCD,AAOI,MAPE,AAOD,OAAO,AAAC,CACL,UAAU,CAAE,OAAO,CACnB,aAAa,CAAE,eAAe,CAC9B,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CAAC,KAAK,CACjD,OAAO,CAAE,EAAE,CACX,MAAM,CAAE,KAAK,CACb,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,KAAK,CACf,AAfL,AAgBI,MAhBE,AAgBD,MAAM,AAAC,CACJ,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,eAAe,CAC9B,MAAM,CAAE,CAAC,CACT,kBAAkB,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CACnD,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CAC3C,OAAO,CAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAA,iBAAiB,CACrD,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,GAAG,CAChB,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,WAAW,CAAE,IAAI,CACjB,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,KAAK,CACZ,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,GAAG,CACnB,AAGL,AAAA,OAAO,AAAC,CACJ,UAAU,CAAE,kBAAqB,CACjC,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,GAAG,CAAE,IAAG,CAAC,GAAG,CAAC,eAAkB,CAC3C,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,IAAI,CAAE,GAAG,CACT,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,QAAQ,CAC1B,UAAU,CAAE,MAAM,CAClB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,GAAG,CAAE,IAAG,CAAC,GAAG,CAAC,eAAkB,CAC3C,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,IAAI,CAAE,GAAG,CACT,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,QAAQ,CAC1B,UAAU,CAAE,MAAM,CACrB,AAED,AAAA,cAAc,AAAA,KAAK,AAAC,CAChB,IAAI,CAAE,OAAO,CACb,KAAK,CAAE,GAAG,CACb", "mappings": "AAAA,AAAA,IAAI,AAAC,CACD,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,IAAI,CACnB,AAED,AACI,IADA,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EACD,yBAAyB,CAD7B,IAAI,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EAED,0BAA0B,AAAC,CACvB,sBAAsB,CAAE,MAAM,CAC9B,yBAAyB,CAAE,MAAM,CACpC,AAGL,AACI,IADA,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EACD,yBAAyB,CAD7B,IAAI,CAAA,AAAA,GAAC,CAAI,KAAK,AAAT,EAED,0BAA0B,AAAC,CACvB,uBAAuB,CAAE,MAAM,CAC/B,0BAA0B,CAAE,MAAM,CACrC,AAGL,AAAA,IAAI,AAAC,CACD,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,IAAI,CACtB,AAED,AAAA,gBAAgB,AAAC,CACb,SAAS,CAAE,MAAM,CACpB,AAED,AAAA,OAAO,AAAC,CACJ,QAAQ,CAAE,QAAQ,CAClB,MAAM,CAAE,CAAC,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,WAAW,CAAE,IAAI,CACjB,gBAAgB,CAAE,OAAO,CAC5B,AAED,AAAA,YAAY,CAAC,WAAW,CAAC,SAAS,AAAC,CAC/B,KAAK,CAAE,sBAAwB,CAMlC,AAPD,AAGI,YAHQ,CAAC,WAAW,CAAC,SAAS,AAG7B,MAAM,CAHX,YAAY,CAAC,WAAW,CAAC,SAAS,AAI7B,MAAM,AAAC,CACJ,KAAK,CAAE,sBAAwB,CAClC,AAGL,AAAA,EAAE,CACF,EAAE,CACF,EAAE,AAAC,CACC,aAAa,CAAE,CAAC,CACnB,AAED,AAAA,MAAM,CAAC,WAAW,AAAC,CACf,KAAK,CAAE,kBAAkB,CAC5B,AAED,AAAA,CAAC,CACD,MAAM,CACN,SAAS,AAAC,CACN,UAAU,CAAE,eAAe,CAC3B,SAAS,CAAE,eAAe,CAC7B,AAED,AAAA,CAAC,AAAA,KAAK,AAAC,CACH,eAAe,CAAE,IAAI,CACrB,MAAM,CAAE,OAAO,CACf,YAAY,CAAE,IAAI,CACrB,AAED,AAAA,IAAI,AAAA,YAAY,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,EACvB,IAAI,AAAA,WAAW,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,CAAa,CAC/B,yBAAyB,CAAE,CAAC,CAC5B,0BAA0B,CAAE,CAAC,CAChC,AAED,AAAA,IAAI,AAAA,YAAY,CAAC,KAAK,CAAA,AAAA,IAAC,CAAK,UAAU,AAAf,CAAiB,CACpC,sBAAsB,CAAE,CAAC,CACzB,uBAAuB,CAAE,CAAC,CAC7B,AAED,AACI,IADA,AAAA,WAAW,CACX,KAAK,AAAA,eAAe,AAAC,CACjB,aAAa,CAAE,CAAC,CACnB,AAHL,AAKI,IALA,AAAA,WAAW,CAKX,KAAK,AAAA,sBAAsB,AAAC,CACxB,sBAAsB,CAAE,CAAC,CACzB,uBAAuB,CAAE,CAAC,CAC7B,AAGL,AAAA,IAAI,AAAA,YAAY,CAChB,IAAI,AAAA,YAAY,CAChB,IAAI,AAAA,WAAW,AAAC,CACZ,MAAM,CAAE,IAAI,CACf,AAED,AAAA,KAAK,AAAC,CACF,YAAY,CAAE,KAAK,CACtB,AAED,AAAA,EAAE,CAAE,EAAE,AAAC,CACH,SAAS,CAAC,GAAG,CAChB,AACD,AAAA,QAAQ,AAAC,CACL,SAAS,CAAC,UAAU,CACpB,aAAa,CAAC,UAAU,CAC3B,AAED,AAAA,KAAK,CAAC,EAAE,CAAA,AAAA,OAAC,CAAQ,OAAO,AAAf,EACT,UAAU,AAAC,CACP,OAAO,CAAE,IAAI,CAChB,AAED,AAAA,KAAK,CAAC,EAAE,CAAA,AAAA,OAAC,CAAQ,MAAM,AAAd,CAAgB,CACrB,OAAO,CAAE,SAAS,CACrB,AAED,AAAA,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,CACjD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,OAAO,CACxD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,MAAM,CACvD,iBAAiB,CAAC,gBAAgB,AAAA,eAAe,AAAA,MAAM,AAAC,CACpD,KAAK,CAAE,KAAK,CACf,AAED,AAAA,MAAM,AAAC,CACH,aAAa,CAAE,eAAe,CAC9B,MAAM,CAAE,KAAK,CACb,MAAM,CAAE,WAAW,CACnB,QAAQ,CAAE,MAAM,CAChB,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,KAAK,CA4Bf,AAlCD,AAOI,MAPE,AAOD,OAAO,AAAC,CACL,UAAU,CAAE,OAAO,CACnB,aAAa,CAAE,eAAe,CAC9B,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CAAC,KAAK,CACjD,OAAO,CAAE,EAAE,CACX,MAAM,CAAE,KAAK,CACb,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,KAAK,CACf,AAfL,AAgBI,MAhBE,AAgBD,MAAM,AAAC,CACJ,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,eAAe,CAC9B,MAAM,CAAE,CAAC,CACT,kBAAkB,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CACnD,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAmB,CAC3C,OAAO,CAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAA,iBAAiB,CACrD,SAAS,CAAE,KAAK,CAChB,WAAW,CAAE,GAAG,CAChB,MAAM,CAAE,IAAI,CACZ,IAAI,CAAE,IAAI,CACV,WAAW,CAAE,IAAI,CACjB,QAAQ,CAAE,QAAQ,CAClB,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,KAAK,CACZ,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,GAAG,CACnB,AAGL,AAAA,OAAO,AAAC,CACJ,UAAU,CAAE,kBAAqB,CACjC,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,GAAG,CAAE,IAAG,CAAC,GAAG,CAAC,eAAkB,CAC3C,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,IAAI,CAAE,GAAG,CACT,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,QAAQ,CAC1B,UAAU,CAAE,MAAM,CAClB,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,GAAG,CAAE,IAAG,CAAC,GAAG,CAAC,eAAkB,CAC3C,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,IAAI,CAAE,GAAG,CACT,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,QAAQ,CAC1B,UAAU,CAAE,MAAM,CACrB,AAED,AAAA,cAAc,AAAA,KAAK,AAAC,CAChB,IAAI,CAAE,OAAO,CACb,KAAK,CAAE,GAAG,CACb",
"sources": [ "sources": [
"../scss/style.scss" "../scss/style.scss"
], ],

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -24,6 +24,10 @@ body {
margin-bottom: 80px; margin-bottom: 80px;
} }
.container-fluid {
max-width: 1920px;
}
.footer { .footer {
position: absolute; position: absolute;
bottom: 0; bottom: 0;