From b235bf76391adf1284c164e1bc08cde6b1f10afd Mon Sep 17 00:00:00 2001 From: Jason Cheng <30381035+jasoncheng7115@users.noreply.github.com> Date: Mon, 13 Aug 2018 15:20:47 +0800 Subject: [PATCH 01/77] Add Traditional Chinese Language File. --- src/lang/zh_TW.lang.php | 299 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 src/lang/zh_TW.lang.php diff --git a/src/lang/zh_TW.lang.php b/src/lang/zh_TW.lang.php new file mode 100644 index 00000000..643a1eca --- /dev/null +++ b/src/lang/zh_TW.lang.php @@ -0,0 +1,299 @@ +. + * + * @package phpservermon + * @author manhere + * @copyright Copyright (c) 2008-2014 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: v3.1.1 + * @link http://www.phpservermonitor.org/ + **/ + +$sm_lang = array( + 'name' => '繁體中文 - Traditional Chinese', + 'locale' => array('zh_TW.UTF-8', 'zh_TW', 'chinese', 'chinese-zhtw'), + 'system' => array( + 'title' => 'Server Monitor', + 'install' => '安裝', + 'action' => '動作', + 'save' => '儲存', + 'edit' => '編輯', + 'delete' => '刪除', + 'date' => '日期', + 'message' => '訊息', + 'yes' => '是', + 'no' => '否', + 'insert' => '插入', + 'add_new' => '增加', + 'update_available' => '發現新版本({version}) http://www.phpservermonitor.org.', + 'back_to_top' => '回到最上層', + 'go_back' => '返回', + 'ok' => 'OK', + 'cancel' => '取消', + // date/time format according the strftime php function format parameter http://php.net/manual/function.strftime.php + 'short_day_format' => '%B %e', + 'long_day_format' => '%B %e, %Y', + 'yesterday_format' => '昨日 %k:%M', + 'other_day_format' => '%A %k:%M', + 'never' => '從未', + 'hours_ago' => '%d小時前', + 'an_hour_ago' => '1小時前', + 'minutes_ago' => '%d分鐘前', + 'a_minute_ago' => '1分鐘前', + 'seconds_ago' => '%d秒前', + 'a_second_ago' => '剛剛', + ), + 'menu' => array( + 'config' => '設定', + 'server' => '伺服器', + 'server_log' => '記錄', + 'server_status' => '狀態', + 'server_update' => '更新', + 'user' => '使用者', + 'help' => '說明', + ), + 'users' => array( + 'user' => '使用者', + 'name' => '顯示名稱', + 'user_name' => '使用者名稱', + 'password' => '密碼', + 'password_repeat' => '再次輸入密碼', + 'password_leave_blank' => '將密碼欄位保持空白,表示不做修改', + 'level' => '等級', + 'level_10' => '超級管理員', + 'level_20' => '一般使用者', + 'level_description' => '超級管理員 具有所有伺服器的管理權限,可管理使用者以及修改系統設定。
一般使用者 僅能查看以及更新自己所負責的伺服器。', + 'mobile' => '行動電話', + 'email' => '電子郵件', + 'pushover' => 'Pushover 通知', + 'pushover_description' => 'Pushover是一種雲端服務,讓你可以很方便的收到即時訊息通知,您可以到網站了解更多的內容。', + 'pushover_key' => 'Pushover 金鑰', + 'pushover_device' => 'Pushover 裝置', + 'pushover_device_description' => '發送訊息的裝置名稱,若保留空白,將會發送到所有的裝置。', + 'delete_title' => '刪除使用者', + 'delete_message' => '您確定要刪除使用者 \'%1\'?', + 'deleted' => '已刪除使用者。', + 'updated' => '已更新使用者。', + 'inserted' => '已增加使用者。', + 'profile' => '個人資料', + 'profile_updated' => '個人資料已經更新。', + 'error_user_name_bad_length' => '使用者名稱長度必須為2-64個字元。', + 'error_user_name_invalid' => '使用者名稱只允許英文字母(a-z、A-Z)、數字(0-9)以及底線(_)。', + 'error_user_name_exists' => '這個使用者名稱已存在。', + 'error_user_email_bad_length' => '電子郵件長度為5-255個字元。', + 'error_user_email_invalid' => '無效的電子郵件。', + 'error_user_level_invalid' => '無效的使用者等級。', + 'error_user_no_match' => '這個使用者名稱不存在。', + 'error_user_password_invalid' => '無效的密碼。', + 'error_user_password_no_match' => '密碼不符。', + ), + 'log' => array( + 'title' => '記錄概覽', + 'type' => '類型', + 'status' => '狀態', + 'email' => '電子郵件通知', + 'sms' => '簡訊通知', + 'pushover' => 'Pushover 通知', + 'no_logs' => '沒有記錄', + ), + 'servers' => array( + 'server' => '伺服器', + 'status' => '狀態', + 'label' => '標籤', + 'domain' => '網域/IP', + 'timeout' => '逾時', + 'timeout_description' => '等待伺服器回應的秒數。', + 'port' => '連接埠', + 'type' => '類型', + 'type_website' => '網站', + 'type_service' => '服務', + 'pattern' => '字串', + 'pattern_description' => '如果在網站上沒有找到符合的字串,則將網站鑣示為離線。', + 'last_check' => '最後檢查', + 'last_online' => '最後上線', + 'monitoring' => '監控中', + 'no_monitoring' => '未監控', + 'email' => '電子郵件通知', + 'send_email' => '發送電子郵件', + 'sms' => '簡訊通知', + 'send_sms' => '發送簡訊', + 'pushover' => 'Pushover 通知', + 'users' => '使用者', + 'delete_title' => '刪除伺服器', + 'delete_message' => '您確定要刪除這個伺服器 \'%1\'?', + 'deleted' => '伺服器已刪除。', + 'updated' => '伺服器已更新。', + 'inserted' => '伺服器已增加。', + 'latency' => '延遲', + 'latency_max' => '延遲(最大)', + 'latency_min' => '延遲(最小)', + 'latency_avg' => '延遲(平均)', + 'uptime' => '上線時間', + 'year' => '年', + 'month' => '月', + 'week' => '周', + 'day' => '日', + 'hour' => '小時', + 'warning_threshold' => '警報臨界值', + 'warning_threshold_description' => '失敗達到多少次數則標示為離線。', + 'chart_last_week' => '上週', + 'chart_history' => '更早', + // Charts date format according jqPlot date format http://www.jqplot.com/docs/files/plugins/jqplot-dateAxisRenderer-js.html + 'chart_day_format' => '%Y-%m-%d', + 'chart_long_date_format' => '%Y-%m-%d %H:%M:%S', + 'chart_short_date_format' => '%m/%d %H:%M', + 'chart_short_time_format' => '%H:%M', + 'warning_notifications_disabled_sms' => '警告!簡訊通知目前是關閉的。', + 'warning_notifications_disabled_email' => '警告!電子郵件通知目前是關閉的。', + 'warning_notifications_disabled_pushover' => '警告!Pushover 通知目前是關閉的。', + 'error_server_no_match' => '找不到伺服器。', + 'error_server_label_bad_length' => '這個標籤必須在1到255之間的字元。', + 'error_server_ip_bad_length' => '這個網域/IP必須在1到255之間的字元。', + 'error_server_ip_bad_service' => '無效的IP地址。', + 'error_server_ip_bad_website' => '無效的網址。', + 'error_server_type_invalid' => '無效的的伺服器型態', + 'error_server_warning_threshold_invalid' => '警報臨界值必須是大於0的有效整數。', + ), + 'config' => array( + 'general' => '一般', + 'language' => '語言', + 'show_update' => '檢查更新', + 'email_status' => '啟用電子郵件通知', + 'email_from_email' => '寄件者信箱', + 'email_from_name' => '寄件者名稱', + 'email_smtp' => '使用SMTP發信', + 'email_smtp_host' => 'SMTP主機', + 'email_smtp_port' => 'SMTP連接埠口', + 'email_smtp_security' => 'SMTP安全性', + 'email_smtp_security_none' => '無', + 'email_smtp_username' => 'SMTP使用者名稱', + 'email_smtp_password' => 'SMTP使用者密碼', + 'email_smtp_noauth' => '留空白表示不做帳號驗證', + 'sms_status' => '啟用簡訊通知', + 'sms_gateway' => '簡訊服務提供者', + 'sms_gateway_mosms' => 'Mosms', + 'sms_gateway_mollie' => 'Mollie', + 'sms_gateway_spryng' => 'Spryng', + 'sms_gateway_inetworx' => 'Inetworx', + 'sms_gateway_clickatell' => 'Clickatell', + 'sms_gateway_textmarketer' => 'Textmarketer', + 'sms_gateway_smsglobal' => 'SMSGlobal', + 'sms_gateway_smsit' => 'Smsit', + 'sms_gateway_username' => '簡訊閘道使用者名稱', + 'sms_gateway_password' => '簡訊閘道使用者密碼', + 'sms_from' => '發送人電話號碼', + 'pushover_status' => '啟用Pushover通知', + 'pushover_description' => 'Pushover是線上服務,讓您可以方便的收到即時通知,請參考 網站 可以得到更詳細的資訊。 ', + 'pushover_clone_app' => '點選這裡可快速建立Pushover App', + 'pushover_api_token' => 'Pushover App API Token', + 'pushover_api_token_description' => '在您使用Pushover通知之前,需要先到這裡->註冊Pushover App帳號 接著在這個網頁輸入你的的Pushover App API Token號碼。', + 'alert_type' => '需要提醒的類別', + 'alert_type_description' => '狀態改變: '. + '伺服器 連線 -> 離線或連線 -> 連線的狀態變化將會收到提醒通知。
'. + '
離線: '. + '伺服器首次發生離線狀態將會收到提醒,如:'. + '設定為15分鐘執行一次,伺服器從1:00-6:00一直處於離線狀態'. + '那麼你將會在1:00首次收到一則提醒通知,之後便不會在收到重覆的提醒通知。
'. + '
全部: '. + '每次執行當伺服器離線(即使伺服器離線很久已提醒過了)均發送提醒通知。', + 'alert_type_status' => '狀態改變', + 'alert_type_offline' => '離線', + 'alert_type_always' => '全部', + 'log_status' => '狀態記錄', + 'log_status_description' => '如果啟用狀態記錄,則每一筆提醒通知都會保留記錄。', + 'log_email' => '保留電子郵件通知發送記錄', + 'log_sms' => '保留簡訊通知發送記錄', + 'log_pushover' => '保留pushover通知發送記錄', + 'updated' => '已更新設定。', + 'tab_email' => '電子郵件發送設定', + 'tab_sms' => '簡訊發送設定', + 'tab_pushover' => 'Pushover通知', + 'settings_email' => '電子郵件發送設定', + 'settings_sms' => '簡訊發送設定', + 'settings_pushover' => 'Pushover通知設定', + 'settings_notification' => '提醒設定', + 'settings_log' => '記錄設定', + 'auto_refresh' => '自動更新', + 'auto_refresh_servers' => + '自動更新伺服器頁。
'. + ''. + '單位為秒,設定為0則不自動更新。'. + '', + 'seconds' => '秒', + 'test' => '測試', + 'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。', + 'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。', + 'test_pushover' => 'Pushover通知將發送到您在使用者設定的裝置。', + 'send' => '傳送', + 'test_subject' => '標題', + 'test_message' => '訊息', + 'email_sent' => '傳送', + 'email_error' => '電子郵件傳送發生錯誤', + 'sms_sent' => '簡訊發送', + 'sms_error' => '簡訊發送發生錯誤', + 'sms_error_nomobile' => '無法傳送SMS簡訊測試:您設定的電話號碼無效或無法找到。', + 'pushover_sent' => '傳送Pushover通知', + 'pushover_error' => '傳送Pushover通知發生錯誤: %s', + 'pushover_error_noapp' => '無法傳送Pushover通知: 找不到Pushover App API token在你的系統設定。', + 'pushover_error_nokey' => '無法傳送Pushover通知: 找不到Pushover key found在你的系統設定。', + 'log_retention_period' => '記錄保留期限', + 'log_retention_period_description' => '保留伺服器運作時間和記錄歸檔的天數,輸入0可以防止清除記錄', + 'log_retention_days' => '天', + ), + // for newlines in the email messages use
+ 'notifications' => array( + 'off_sms' => '伺服器 \'%LABEL%\' 關機: ip=%IP%, port=%PORT%. Error=%ERROR%', + 'off_email_subject' => 'IMPORTANT: 服務器 \'%LABEL%\' 關機', + 'off_email_body' => "無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%", + 'off_pushover_title' => '伺服器 \'%LABEL%\' 關機', + 'off_pushover_message' => "無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%", + 'on_sms' => '伺服器 \'%LABEL%\' 運行中: ip=%IP%, port=%PORT%', + 'on_email_subject' => 'IMPORTANT: 伺服器 \'%LABEL%\' 運行中', + 'on_email_body' => "伺服器 '%LABEL%' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%", + 'on_pushover_title' => '伺服器 \'%LABEL%\' 運作中', + 'on_pushover_message' => "伺服器 '%LABEL%' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%", + ), + 'login' => array( + 'welcome_usermenu' => '歡迎, %user_name%', + 'title_sign_in' => '請登入', + 'title_forgot' => '忘記密碼', + 'title_reset' => '重設密碼', + 'submit' => '送出', + 'remember_me' => '記住我', + 'login' => '登入', + 'logout' => '登出', + 'username' => '使用者名稱', + 'password' => '密碼', + 'password_repeat' => '再次輸入密碼', + 'password_forgot' => '忘記密碼', + 'password_reset' => '重設密碼', + 'password_reset_email_subject' => '重設你的密碼', + 'password_reset_email_body' => '點選以下連結來重設密碼,這個連結於1小時後失效。

%link%', + 'error_user_incorrect' => '使用者不存在。', + 'error_login_incorrect' => '登入資料不正確。', + 'error_login_passwords_nomatch' => '密碼不符。', + 'error_reset_invalid_link' => '重設密碼連結無效。', + 'success_password_forgot' => '重設密碼電子郵件已發送。', + 'success_password_reset' => '密碼重設成功,請登入。', + ), + 'error' => array( + '401_unauthorized' => '認證失敗', + '401_unauthorized_description' => '您没有權限進入這個頁面。', + ), +); From c401a255d654387782e4e95e6b245b0fbce6632e Mon Sep 17 00:00:00 2001 From: Jason Cheng <30381035+jasoncheng7115@users.noreply.github.com> Date: Mon, 13 Aug 2018 23:56:38 +0800 Subject: [PATCH 02/77] Translate all contents according to v3.3.1 version --- src/lang/zh_TW.lang.php | 188 ++++++++++++++++++++++++++-------------- 1 file changed, 123 insertions(+), 65 deletions(-) diff --git a/src/lang/zh_TW.lang.php b/src/lang/zh_TW.lang.php index 643a1eca..1e5b93f2 100644 --- a/src/lang/zh_TW.lang.php +++ b/src/lang/zh_TW.lang.php @@ -27,7 +27,14 @@ $sm_lang = array( 'name' => '繁體中文 - Traditional Chinese', - 'locale' => array('zh_TW.UTF-8', 'zh_TW', 'chinese', 'chinese-zhtw'), + 'locale' => array( + '0' => 'zh_TW.UTF-8', + '1' => 'zh_TW', + '2' => 'chinese', + '3' => 'chinese-tw', + ), + 'locale_tag' => 'zh_TW', + 'locale_dir' => 'ltr', 'system' => array( 'title' => 'Server Monitor', 'install' => '安裝', @@ -41,12 +48,12 @@ $sm_lang = array( 'no' => '否', 'insert' => '插入', 'add_new' => '增加', - 'update_available' => '發現新版本({version}) http://www.phpservermonitor.org.', + 'update_available' => '找到新版本({version}) http://www.phpservermonitor.org.', 'back_to_top' => '回到最上層', 'go_back' => '返回', - 'ok' => 'OK', + 'ok' => '確定', 'cancel' => '取消', - // date/time format according the strftime php function format parameter http://php.net/manual/function.strftime.php + 'activate' => '啟用', 'short_day_format' => '%B %e', 'long_day_format' => '%B %e, %Y', 'yesterday_format' => '昨日 %k:%M', @@ -58,6 +65,20 @@ $sm_lang = array( 'a_minute_ago' => '1分鐘前', 'seconds_ago' => '%d秒前', 'a_second_ago' => '剛剛', + 'year' => '年', + 'years' => '年', + 'month' => '月', + 'months' => '月', + 'day' => '日', + 'days' => '日', + 'hour' => '時', + 'hours' => '時', + 'minute' => '分', + 'minutes' => '分', + 'second' => '秒', + 'seconds' => '秒', + 'online' => '線上', + 'offline' => '離線', ), 'menu' => array( 'config' => '設定', @@ -74,18 +95,28 @@ $sm_lang = array( 'user_name' => '使用者名稱', 'password' => '密碼', 'password_repeat' => '再次輸入密碼', - 'password_leave_blank' => '將密碼欄位保持空白,表示不做修改', + 'password_leave_blank' => '若密碼欄位保持空白,表示不做修改', 'level' => '等級', 'level_10' => '超級管理員', 'level_20' => '一般使用者', - 'level_description' => '超級管理員 具有所有伺服器的管理權限,可管理使用者以及修改系統設定。
一般使用者 僅能查看以及更新自己所負責的伺服器。', + 'level_description' => '超級管理員 具備所有伺服器的管理權限,可管理使用者以及修改系統設定。
一般使用者 僅能查看以及更新自己所負責的伺服器。', 'mobile' => '行動電話', 'email' => '電子郵件', 'pushover' => 'Pushover 通知', - 'pushover_description' => 'Pushover是一種雲端服務,讓你可以很方便的收到即時訊息通知,您可以到網站了解更多的內容。', + 'pushover_description' => 'Pushover 是一種雲端服務,讓你可以很方便的收到即時訊息通知,您可以到網站了解更多的內容。', 'pushover_key' => 'Pushover 金鑰', 'pushover_device' => 'Pushover 裝置', 'pushover_device_description' => '發送訊息的裝置名稱,若保留空白,將會發送到所有的裝置。', + 'telegram' => 'Telegram 通知', + 'telegram_description' => 'Telegram 是一種聊天應用程式,它提供很容易使用的的即時通知能力。您可以到 documentation 了解更多的內容。', + 'telegram_chat_id' => 'Telegram Chat ID', + 'telegram_chat_id_description' => '將訊息發送到指定的聊天室', + 'telegram_get_chat_id' => '點選這裡可以取得您的 Chat ID', + 'activate_telegram' => '啟用 Telegram 通知', + 'activate_telegram_description' => '允許 Telegram 將訊息發送到指定的 Chat ID。若沒有啟用此項目,Telegram 將不允許我們發送通知給您。', + 'telegram_bot_username_found' => 'The bot was found!

This will open a chat with the bot. Here you need to press start of type /start.', + 'telegram_bot_username_error_token' => '401 - 未授權,請確認您的 API Token 是有效的。', + 'telegram_bot_error' => '啟用 Telegram 通知時發生錯誤:%s', 'delete_title' => '刪除使用者', 'delete_message' => '您確定要刪除使用者 \'%1\'?', 'deleted' => '已刪除使用者。', @@ -110,7 +141,11 @@ $sm_lang = array( 'email' => '電子郵件通知', 'sms' => '簡訊通知', 'pushover' => 'Pushover 通知', + 'telegram' => 'Telegram 通知', 'no_logs' => '沒有記錄', + 'clear' => '清除記錄', + 'delete_title' => '刪除記錄', + 'delete_message' => '您確定要刪除 所有 記錄?', ), 'servers' => array( 'server' => '伺服器', @@ -119,14 +154,31 @@ $sm_lang = array( 'domain' => '網域/IP', 'timeout' => '逾時', 'timeout_description' => '等待伺服器回應的秒數。', + 'authentication_settings' => '驗證設定 (非必要)', + 'website_username' => '使用者', + 'website_username_description' => '存取這個網站的使用者。(只支援 Apache 驗證)', + 'website_password' => '密碼', + 'website_password_description' => '存取這個網站的使用者。(密碼將會以加密形式存放在資料庫)', + 'fieldset_monitoring' => '監視', + 'fieldset_permissions' => '權限', 'port' => '連接埠', + 'custom_port' => '自訂連接埠', + 'popular_ports' => '常用連接埠', + 'please_select' => '請選擇', 'type' => '類型', 'type_website' => '網站', 'type_service' => '服務', + 'type_ping' => 'Ping', 'pattern' => '字串', - 'pattern_description' => '如果在網站上沒有找到符合的字串,則將網站鑣示為離線。', - 'last_check' => '最後檢查', - 'last_online' => '最後上線', + 'pattern_description' => '如果在網站上沒有找到符合的字串,則將網站標示為離線。', + 'pattern_online' => '指明網站上的字串', + 'pattern_online_description' => '線上:如果在網站上沒有找到符合的字串,則將網站標示為線上。', + 'header' => '標頭', + 'header_name_description' => '標頭名稱 (區分大小寫)', + 'header_value_description' => '標頭的值,可以使用正則表示式。', + 'last_check' => '最後一次檢查', + 'last_online' => '最後一次上線', + 'last_offline' => '最後一次離線', 'monitoring' => '監控中', 'no_monitoring' => '未監控', 'email' => '電子郵件通知', @@ -134,6 +186,9 @@ $sm_lang = array( 'sms' => '簡訊通知', 'send_sms' => '發送簡訊', 'pushover' => 'Pushover 通知', + 'send_pushover' => '發送 Pushover 通知', + 'telegram' => 'Telegram 通知', + 'send_telegram' => '發送 Telegram 通知', 'users' => '使用者', 'delete_title' => '刪除伺服器', 'delete_message' => '您確定要刪除這個伺服器 \'%1\'?', @@ -141,39 +196,45 @@ $sm_lang = array( 'updated' => '伺服器已更新。', 'inserted' => '伺服器已增加。', 'latency' => '延遲', - 'latency_max' => '延遲(最大)', - 'latency_min' => '延遲(最小)', - 'latency_avg' => '延遲(平均)', + 'latency_max' => '延遲 (最大)', + 'latency_min' => '延遲 (最小)', + 'latency_avg' => '延遲 (平均)', 'uptime' => '上線時間', 'year' => '年', 'month' => '月', - 'week' => '周', + 'week' => '週', 'day' => '日', 'hour' => '小時', 'warning_threshold' => '警報臨界值', 'warning_threshold_description' => '失敗達到多少次數則標示為離線。', 'chart_last_week' => '上週', 'chart_history' => '更早', - // Charts date format according jqPlot date format http://www.jqplot.com/docs/files/plugins/jqplot-dateAxisRenderer-js.html 'chart_day_format' => '%Y-%m-%d', 'chart_long_date_format' => '%Y-%m-%d %H:%M:%S', 'chart_short_date_format' => '%m/%d %H:%M', 'chart_short_time_format' => '%H:%M', - 'warning_notifications_disabled_sms' => '警告!簡訊通知目前是關閉的。', - 'warning_notifications_disabled_email' => '警告!電子郵件通知目前是關閉的。', - 'warning_notifications_disabled_pushover' => '警告!Pushover 通知目前是關閉的。', + 'warning_notifications_disabled_sms' => '簡訊通知已關閉。', + 'warning_notifications_disabled_email' => '電子郵件通知已關閉。', + 'warning_notifications_disabled_pushover' => 'Pushover 通知已關閉。', + 'warning_notifications_disabled_telegram' => 'Telegram 通知已關閉。', 'error_server_no_match' => '找不到伺服器。', - 'error_server_label_bad_length' => '這個標籤必須在1到255之間的字元。', - 'error_server_ip_bad_length' => '這個網域/IP必須在1到255之間的字元。', - 'error_server_ip_bad_service' => '無效的IP地址。', + 'error_server_label_bad_length' => '標籤必須在1到255間的字元。', + 'error_server_ip_bad_length' => '網域/IP必須在1到255間的字元。', + 'error_server_ip_bad_service' => '無效的 IP 位址。', 'error_server_ip_bad_website' => '無效的網址。', 'error_server_type_invalid' => '無效的的伺服器型態', - 'error_server_warning_threshold_invalid' => '警報臨界值必須是大於0的有效整數。', + 'error_server_warning_threshold_invalid' => '警報臨界值必須是大於 0 的有效整數。', ), 'config' => array( 'general' => '一般', 'language' => '語言', 'show_update' => '檢查更新', + 'password_encrypt_key' => '加密金鑰', + 'password_encrypt_key_note' => '這個加密金鑰將用於保護您登入這個網站的密碼,如果修改了此金鑰,原本已經存在的密碼將無法使用!', + 'proxy' => '啟用 Proxy', + 'proxy_url' => 'Proxy URL', + 'proxy_user' => 'Proxy 使用者名稱', + 'proxy_password' => 'Proxy 密碼', 'email_status' => '啟用電子郵件通知', 'email_from_email' => '寄件者信箱', 'email_from_name' => '寄件者名稱', @@ -187,14 +248,6 @@ $sm_lang = array( 'email_smtp_noauth' => '留空白表示不做帳號驗證', 'sms_status' => '啟用簡訊通知', 'sms_gateway' => '簡訊服務提供者', - 'sms_gateway_mosms' => 'Mosms', - 'sms_gateway_mollie' => 'Mollie', - 'sms_gateway_spryng' => 'Spryng', - 'sms_gateway_inetworx' => 'Inetworx', - 'sms_gateway_clickatell' => 'Clickatell', - 'sms_gateway_textmarketer' => 'Textmarketer', - 'sms_gateway_smsglobal' => 'SMSGlobal', - 'sms_gateway_smsit' => 'Smsit', 'sms_gateway_username' => '簡訊閘道使用者名稱', 'sms_gateway_password' => '簡訊閘道使用者密碼', 'sms_from' => '發送人電話號碼', @@ -202,44 +255,44 @@ $sm_lang = array( 'pushover_description' => 'Pushover是線上服務,讓您可以方便的收到即時通知,請參考 網站 可以得到更詳細的資訊。 ', 'pushover_clone_app' => '點選這裡可快速建立Pushover App', 'pushover_api_token' => 'Pushover App API Token', - 'pushover_api_token_description' => '在您使用Pushover通知之前,需要先到這裡->註冊Pushover App帳號 接著在這個網頁輸入你的的Pushover App API Token號碼。', + 'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡->註冊Pushover App帳號 接著在這個網頁輸入你的的Pushover App API Token號碼。', + 'telegram_status' => '允許發送 Telegram 訊息', + 'telegram_description' => 'Telegram 是一種聊天應用程式,它提供很容易使用的即時通知服務。請參考 文件庫 可以取得更多資訊與安裝說明。', + 'telegram_api_token' => 'Telegram API Token', + 'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 文件庫 取得說明。', 'alert_type' => '需要提醒的類別', - 'alert_type_description' => '狀態改變: '. - '伺服器 連線 -> 離線或連線 -> 連線的狀態變化將會收到提醒通知。
'. - '
離線: '. - '伺服器首次發生離線狀態將會收到提醒,如:'. - '設定為15分鐘執行一次,伺服器從1:00-6:00一直處於離線狀態'. - '那麼你將會在1:00首次收到一則提醒通知,之後便不會在收到重覆的提醒通知。
'. - '
全部: '. - '每次執行當伺服器離線(即使伺服器離線很久已提醒過了)均發送提醒通知。', + 'alert_type_description' => '狀態改變: 伺服器 連線 -> 離線或連線 -> 連線的狀態變化將會收到提醒通知。

離線: 伺服器首次發生離線狀態將會收到提醒,如:設定為15分鐘執行一次,伺服器從1:00-6:00一直處於離線狀態那麼你將會在1:00首次收到一則提醒通知,之後便不會在收到重覆的提醒通知。

全部: 每次執行當伺服器離線(即使伺服器離線很久已提醒過了)均發送提醒通知。', 'alert_type_status' => '狀態改變', 'alert_type_offline' => '離線', 'alert_type_always' => '全部', + 'alert_proxy' => 'Even if enabled, proxy is never used for services', + 'alert_proxy_url' => '格式: Host:Port', 'log_status' => '狀態記錄', 'log_status_description' => '如果啟用狀態記錄,則每一筆提醒通知都會保留記錄。', 'log_email' => '保留電子郵件通知發送記錄', 'log_sms' => '保留簡訊通知發送記錄', - 'log_pushover' => '保留pushover通知發送記錄', + 'log_pushover' => '保留 pushover 通知發送記錄', + 'log_telegram' => '保留 telegram 通知發送記錄', 'updated' => '已更新設定。', 'tab_email' => '電子郵件發送設定', 'tab_sms' => '簡訊發送設定', - 'tab_pushover' => 'Pushover通知', + 'tab_pushover' => 'Pushover 通知', + 'tab_telegram' => 'Telegram 通知', 'settings_email' => '電子郵件發送設定', 'settings_sms' => '簡訊發送設定', - 'settings_pushover' => 'Pushover通知設定', + 'settings_pushover' => 'Pushover 發送設定', + 'settings_telegram' => 'Telegram 發送設定', 'settings_notification' => '提醒設定', 'settings_log' => '記錄設定', + 'settings_proxy' => 'Proxy 設定', 'auto_refresh' => '自動更新', - 'auto_refresh_servers' => - '自動更新伺服器頁。
'. - ''. - '單位為秒,設定為0則不自動更新。'. - '', + 'auto_refresh_servers' => '自動更新伺服器頁。
單位為秒,設定為0則不自動更新。', 'seconds' => '秒', 'test' => '測試', 'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。', 'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。', - 'test_pushover' => 'Pushover通知將發送到您在使用者設定的裝置。', + 'test_pushover' => 'Pushover 通知將發送到您在使用者設定的裝置。', + 'test_telegram' => 'Telegram 通知將發送到您在使用者設定的 Chat ID。', 'send' => '傳送', 'test_subject' => '標題', 'test_message' => '訊息', @@ -247,33 +300,38 @@ $sm_lang = array( 'email_error' => '電子郵件傳送發生錯誤', 'sms_sent' => '簡訊發送', 'sms_error' => '簡訊發送發生錯誤', - 'sms_error_nomobile' => '無法傳送SMS簡訊測試:您設定的電話號碼無效或無法找到。', - 'pushover_sent' => '傳送Pushover通知', - 'pushover_error' => '傳送Pushover通知發生錯誤: %s', - 'pushover_error_noapp' => '無法傳送Pushover通知: 找不到Pushover App API token在你的系統設定。', - 'pushover_error_nokey' => '無法傳送Pushover通知: 找不到Pushover key found在你的系統設定。', + 'sms_error_nomobile' => '無法傳送 SMS 簡訊測試:您設定的電話號碼無效或無法找到。', + 'pushover_sent' => '傳送 Pushover 通知', + 'pushover_error' => '傳送 Pushover 通知發生錯誤: %s', + 'pushover_error_noapp' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover App API token。', + 'pushover_error_nokey' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover key found 。', + 'telegram_sent' => '傳送 Telegram 通知', + 'telegram_error' => '傳送 Telegram 通知發生錯誤: %s', + 'telegram_error_notoken' => '無法傳送 Telegram 通知: 在系統設定找不到 Telegram API token。', + 'telegram_error_noid' => '無法傳送 Telegram 通知: 在您的個人資料找不到 Chat ID。', 'log_retention_period' => '記錄保留期限', - 'log_retention_period_description' => '保留伺服器運作時間和記錄歸檔的天數,輸入0可以防止清除記錄', - 'log_retention_days' => '天', + 'log_retention_period_description' => '保留伺服器運作時間和記錄歸檔的天數,輸入0可以防止記錄被清除', + 'log_retention_days' => '日', ), - // for newlines in the email messages use
'notifications' => array( 'off_sms' => '伺服器 \'%LABEL%\' 關機: ip=%IP%, port=%PORT%. Error=%ERROR%', 'off_email_subject' => 'IMPORTANT: 服務器 \'%LABEL%\' 關機', - 'off_email_body' => "無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%", + 'off_email_body' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', 'off_pushover_title' => '伺服器 \'%LABEL%\' 關機', - 'off_pushover_message' => "無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%", + 'off_pushover_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', + 'off_telegram_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', 'on_sms' => '伺服器 \'%LABEL%\' 運行中: ip=%IP%, port=%PORT%', 'on_email_subject' => 'IMPORTANT: 伺服器 \'%LABEL%\' 運行中', - 'on_email_body' => "伺服器 '%LABEL%' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%", + 'on_email_body' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', 'on_pushover_title' => '伺服器 \'%LABEL%\' 運作中', - 'on_pushover_message' => "伺服器 '%LABEL%' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%", + 'on_pushover_message' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', + 'on_telegram_message' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', ), 'login' => array( - 'welcome_usermenu' => '歡迎, %user_name%', + 'welcome_usermenu' => '歡迎,%user_name%', 'title_sign_in' => '請登入', 'title_forgot' => '忘記密碼', - 'title_reset' => '重設密碼', + 'title_reset' => '密碼重置', 'submit' => '送出', 'remember_me' => '記住我', 'login' => '登入', @@ -283,17 +341,17 @@ $sm_lang = array( 'password_repeat' => '再次輸入密碼', 'password_forgot' => '忘記密碼', 'password_reset' => '重設密碼', - 'password_reset_email_subject' => '重設你的密碼', + 'password_reset_email_subject' => '重設您的密碼', 'password_reset_email_body' => '點選以下連結來重設密碼,這個連結於1小時後失效。

%link%', 'error_user_incorrect' => '使用者不存在。', 'error_login_incorrect' => '登入資料不正確。', - 'error_login_passwords_nomatch' => '密碼不符。', + 'error_login_passwords_nomatch' => '密碼不符合。', 'error_reset_invalid_link' => '重設密碼連結無效。', 'success_password_forgot' => '重設密碼電子郵件已發送。', 'success_password_reset' => '密碼重設成功,請登入。', ), 'error' => array( - '401_unauthorized' => '認證失敗', + '401_unauthorized' => '驗證失敗', '401_unauthorized_description' => '您没有權限進入這個頁面。', ), ); From 86ecc09c3b942cd4dbb9f58b1ac7cac9e9242d2a Mon Sep 17 00:00:00 2001 From: Jason Cheng <30381035+jasoncheng7115@users.noreply.github.com> Date: Tue, 14 Aug 2018 09:18:53 +0800 Subject: [PATCH 03/77] put translator name --- src/lang/zh_TW.lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/zh_TW.lang.php b/src/lang/zh_TW.lang.php index 1e5b93f2..0cc2310e 100644 --- a/src/lang/zh_TW.lang.php +++ b/src/lang/zh_TW.lang.php @@ -18,7 +18,7 @@ * along with PHP Server Monitor. If not, see . * * @package phpservermon - * @author manhere + * @author Jason Cheng * @copyright Copyright (c) 2008-2014 Pepijn Over * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 * @version Release: v3.1.1 From 620ab023f9b3337f43f587ba1efda83d1b69a25b Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 19 Dec 2019 20:19:41 +0100 Subject: [PATCH 04/77] Update zh_TW.lang.php --- src/lang/zh_TW.lang.php | 670 ++++++++++++++++++++-------------------- 1 file changed, 342 insertions(+), 328 deletions(-) diff --git a/src/lang/zh_TW.lang.php b/src/lang/zh_TW.lang.php index 0cc2310e..d7de212f 100644 --- a/src/lang/zh_TW.lang.php +++ b/src/lang/zh_TW.lang.php @@ -1,4 +1,5 @@ '繁體中文 - Traditional Chinese', - 'locale' => array( - '0' => 'zh_TW.UTF-8', - '1' => 'zh_TW', - '2' => 'chinese', - '3' => 'chinese-tw', - ), - 'locale_tag' => 'zh_TW', - 'locale_dir' => 'ltr', - 'system' => array( - 'title' => 'Server Monitor', - 'install' => '安裝', - 'action' => '動作', - 'save' => '儲存', - 'edit' => '編輯', - 'delete' => '刪除', - 'date' => '日期', - 'message' => '訊息', - 'yes' => '是', - 'no' => '否', - 'insert' => '插入', - 'add_new' => '增加', - 'update_available' => '找到新版本({version}) http://www.phpservermonitor.org.', - 'back_to_top' => '回到最上層', - 'go_back' => '返回', - 'ok' => '確定', - 'cancel' => '取消', - 'activate' => '啟用', - 'short_day_format' => '%B %e', - 'long_day_format' => '%B %e, %Y', - 'yesterday_format' => '昨日 %k:%M', - 'other_day_format' => '%A %k:%M', - 'never' => '從未', - 'hours_ago' => '%d小時前', - 'an_hour_ago' => '1小時前', - 'minutes_ago' => '%d分鐘前', - 'a_minute_ago' => '1分鐘前', - 'seconds_ago' => '%d秒前', - 'a_second_ago' => '剛剛', - 'year' => '年', - 'years' => '年', - 'month' => '月', - 'months' => '月', - 'day' => '日', - 'days' => '日', - 'hour' => '時', - 'hours' => '時', - 'minute' => '分', - 'minutes' => '分', - 'second' => '秒', - 'seconds' => '秒', - 'online' => '線上', - 'offline' => '離線', - ), - 'menu' => array( - 'config' => '設定', - 'server' => '伺服器', - 'server_log' => '記錄', - 'server_status' => '狀態', - 'server_update' => '更新', - 'user' => '使用者', - 'help' => '說明', - ), - 'users' => array( - 'user' => '使用者', - 'name' => '顯示名稱', - 'user_name' => '使用者名稱', - 'password' => '密碼', - 'password_repeat' => '再次輸入密碼', - 'password_leave_blank' => '若密碼欄位保持空白,表示不做修改', - 'level' => '等級', - 'level_10' => '超級管理員', - 'level_20' => '一般使用者', - 'level_description' => '超級管理員 具備所有伺服器的管理權限,可管理使用者以及修改系統設定。
一般使用者 僅能查看以及更新自己所負責的伺服器。', - 'mobile' => '行動電話', - 'email' => '電子郵件', - 'pushover' => 'Pushover 通知', - 'pushover_description' => 'Pushover 是一種雲端服務,讓你可以很方便的收到即時訊息通知,您可以到網站了解更多的內容。', - 'pushover_key' => 'Pushover 金鑰', - 'pushover_device' => 'Pushover 裝置', - 'pushover_device_description' => '發送訊息的裝置名稱,若保留空白,將會發送到所有的裝置。', - 'telegram' => 'Telegram 通知', - 'telegram_description' => 'Telegram 是一種聊天應用程式,它提供很容易使用的的即時通知能力。您可以到 documentation 了解更多的內容。', - 'telegram_chat_id' => 'Telegram Chat ID', - 'telegram_chat_id_description' => '將訊息發送到指定的聊天室', - 'telegram_get_chat_id' => '點選這裡可以取得您的 Chat ID', - 'activate_telegram' => '啟用 Telegram 通知', - 'activate_telegram_description' => '允許 Telegram 將訊息發送到指定的 Chat ID。若沒有啟用此項目,Telegram 將不允許我們發送通知給您。', - 'telegram_bot_username_found' => 'The bot was found!

This will open a chat with the bot. Here you need to press start of type /start.', - 'telegram_bot_username_error_token' => '401 - 未授權,請確認您的 API Token 是有效的。', - 'telegram_bot_error' => '啟用 Telegram 通知時發生錯誤:%s', - 'delete_title' => '刪除使用者', - 'delete_message' => '您確定要刪除使用者 \'%1\'?', - 'deleted' => '已刪除使用者。', - 'updated' => '已更新使用者。', - 'inserted' => '已增加使用者。', - 'profile' => '個人資料', - 'profile_updated' => '個人資料已經更新。', - 'error_user_name_bad_length' => '使用者名稱長度必須為2-64個字元。', - 'error_user_name_invalid' => '使用者名稱只允許英文字母(a-z、A-Z)、數字(0-9)以及底線(_)。', - 'error_user_name_exists' => '這個使用者名稱已存在。', - 'error_user_email_bad_length' => '電子郵件長度為5-255個字元。', - 'error_user_email_invalid' => '無效的電子郵件。', - 'error_user_level_invalid' => '無效的使用者等級。', - 'error_user_no_match' => '這個使用者名稱不存在。', - 'error_user_password_invalid' => '無效的密碼。', - 'error_user_password_no_match' => '密碼不符。', - ), - 'log' => array( - 'title' => '記錄概覽', - 'type' => '類型', - 'status' => '狀態', - 'email' => '電子郵件通知', - 'sms' => '簡訊通知', - 'pushover' => 'Pushover 通知', - 'telegram' => 'Telegram 通知', - 'no_logs' => '沒有記錄', - 'clear' => '清除記錄', - 'delete_title' => '刪除記錄', - 'delete_message' => '您確定要刪除 所有 記錄?', - ), - 'servers' => array( - 'server' => '伺服器', - 'status' => '狀態', - 'label' => '標籤', - 'domain' => '網域/IP', - 'timeout' => '逾時', - 'timeout_description' => '等待伺服器回應的秒數。', - 'authentication_settings' => '驗證設定 (非必要)', - 'website_username' => '使用者', - 'website_username_description' => '存取這個網站的使用者。(只支援 Apache 驗證)', - 'website_password' => '密碼', - 'website_password_description' => '存取這個網站的使用者。(密碼將會以加密形式存放在資料庫)', - 'fieldset_monitoring' => '監視', - 'fieldset_permissions' => '權限', - 'port' => '連接埠', - 'custom_port' => '自訂連接埠', - 'popular_ports' => '常用連接埠', - 'please_select' => '請選擇', - 'type' => '類型', - 'type_website' => '網站', - 'type_service' => '服務', - 'type_ping' => 'Ping', - 'pattern' => '字串', - 'pattern_description' => '如果在網站上沒有找到符合的字串,則將網站標示為離線。', - 'pattern_online' => '指明網站上的字串', - 'pattern_online_description' => '線上:如果在網站上沒有找到符合的字串,則將網站標示為線上。', - 'header' => '標頭', - 'header_name_description' => '標頭名稱 (區分大小寫)', - 'header_value_description' => '標頭的值,可以使用正則表示式。', - 'last_check' => '最後一次檢查', - 'last_online' => '最後一次上線', - 'last_offline' => '最後一次離線', - 'monitoring' => '監控中', - 'no_monitoring' => '未監控', - 'email' => '電子郵件通知', - 'send_email' => '發送電子郵件', - 'sms' => '簡訊通知', - 'send_sms' => '發送簡訊', - 'pushover' => 'Pushover 通知', - 'send_pushover' => '發送 Pushover 通知', - 'telegram' => 'Telegram 通知', - 'send_telegram' => '發送 Telegram 通知', - 'users' => '使用者', - 'delete_title' => '刪除伺服器', - 'delete_message' => '您確定要刪除這個伺服器 \'%1\'?', - 'deleted' => '伺服器已刪除。', - 'updated' => '伺服器已更新。', - 'inserted' => '伺服器已增加。', - 'latency' => '延遲', - 'latency_max' => '延遲 (最大)', - 'latency_min' => '延遲 (最小)', - 'latency_avg' => '延遲 (平均)', - 'uptime' => '上線時間', - 'year' => '年', - 'month' => '月', - 'week' => '週', - 'day' => '日', - 'hour' => '小時', - 'warning_threshold' => '警報臨界值', - 'warning_threshold_description' => '失敗達到多少次數則標示為離線。', - 'chart_last_week' => '上週', - 'chart_history' => '更早', - 'chart_day_format' => '%Y-%m-%d', - 'chart_long_date_format' => '%Y-%m-%d %H:%M:%S', - 'chart_short_date_format' => '%m/%d %H:%M', - 'chart_short_time_format' => '%H:%M', - 'warning_notifications_disabled_sms' => '簡訊通知已關閉。', - 'warning_notifications_disabled_email' => '電子郵件通知已關閉。', - 'warning_notifications_disabled_pushover' => 'Pushover 通知已關閉。', - 'warning_notifications_disabled_telegram' => 'Telegram 通知已關閉。', - 'error_server_no_match' => '找不到伺服器。', - 'error_server_label_bad_length' => '標籤必須在1到255間的字元。', - 'error_server_ip_bad_length' => '網域/IP必須在1到255間的字元。', - 'error_server_ip_bad_service' => '無效的 IP 位址。', - 'error_server_ip_bad_website' => '無效的網址。', - 'error_server_type_invalid' => '無效的的伺服器型態', - 'error_server_warning_threshold_invalid' => '警報臨界值必須是大於 0 的有效整數。', - ), - 'config' => array( - 'general' => '一般', - 'language' => '語言', - 'show_update' => '檢查更新', - 'password_encrypt_key' => '加密金鑰', - 'password_encrypt_key_note' => '這個加密金鑰將用於保護您登入這個網站的密碼,如果修改了此金鑰,原本已經存在的密碼將無法使用!', - 'proxy' => '啟用 Proxy', - 'proxy_url' => 'Proxy URL', - 'proxy_user' => 'Proxy 使用者名稱', - 'proxy_password' => 'Proxy 密碼', - 'email_status' => '啟用電子郵件通知', - 'email_from_email' => '寄件者信箱', - 'email_from_name' => '寄件者名稱', - 'email_smtp' => '使用SMTP發信', - 'email_smtp_host' => 'SMTP主機', - 'email_smtp_port' => 'SMTP連接埠口', - 'email_smtp_security' => 'SMTP安全性', - 'email_smtp_security_none' => '無', - 'email_smtp_username' => 'SMTP使用者名稱', - 'email_smtp_password' => 'SMTP使用者密碼', - 'email_smtp_noauth' => '留空白表示不做帳號驗證', - 'sms_status' => '啟用簡訊通知', - 'sms_gateway' => '簡訊服務提供者', - 'sms_gateway_username' => '簡訊閘道使用者名稱', - 'sms_gateway_password' => '簡訊閘道使用者密碼', - 'sms_from' => '發送人電話號碼', - 'pushover_status' => '啟用Pushover通知', - 'pushover_description' => 'Pushover是線上服務,讓您可以方便的收到即時通知,請參考 網站 可以得到更詳細的資訊。 ', - 'pushover_clone_app' => '點選這裡可快速建立Pushover App', - 'pushover_api_token' => 'Pushover App API Token', - 'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡->註冊Pushover App帳號 接著在這個網頁輸入你的的Pushover App API Token號碼。', - 'telegram_status' => '允許發送 Telegram 訊息', - 'telegram_description' => 'Telegram 是一種聊天應用程式,它提供很容易使用的即時通知服務。請參考 文件庫 可以取得更多資訊與安裝說明。', - 'telegram_api_token' => 'Telegram API Token', - 'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 文件庫 取得說明。', - 'alert_type' => '需要提醒的類別', - 'alert_type_description' => '狀態改變: 伺服器 連線 -> 離線或連線 -> 連線的狀態變化將會收到提醒通知。

離線: 伺服器首次發生離線狀態將會收到提醒,如:設定為15分鐘執行一次,伺服器從1:00-6:00一直處於離線狀態那麼你將會在1:00首次收到一則提醒通知,之後便不會在收到重覆的提醒通知。

全部: 每次執行當伺服器離線(即使伺服器離線很久已提醒過了)均發送提醒通知。', - 'alert_type_status' => '狀態改變', - 'alert_type_offline' => '離線', - 'alert_type_always' => '全部', - 'alert_proxy' => 'Even if enabled, proxy is never used for services', - 'alert_proxy_url' => '格式: Host:Port', - 'log_status' => '狀態記錄', - 'log_status_description' => '如果啟用狀態記錄,則每一筆提醒通知都會保留記錄。', - 'log_email' => '保留電子郵件通知發送記錄', - 'log_sms' => '保留簡訊通知發送記錄', - 'log_pushover' => '保留 pushover 通知發送記錄', - 'log_telegram' => '保留 telegram 通知發送記錄', - 'updated' => '已更新設定。', - 'tab_email' => '電子郵件發送設定', - 'tab_sms' => '簡訊發送設定', - 'tab_pushover' => 'Pushover 通知', - 'tab_telegram' => 'Telegram 通知', - 'settings_email' => '電子郵件發送設定', - 'settings_sms' => '簡訊發送設定', - 'settings_pushover' => 'Pushover 發送設定', - 'settings_telegram' => 'Telegram 發送設定', - 'settings_notification' => '提醒設定', - 'settings_log' => '記錄設定', - 'settings_proxy' => 'Proxy 設定', - 'auto_refresh' => '自動更新', - 'auto_refresh_servers' => '自動更新伺服器頁。
單位為秒,設定為0則不自動更新。', - 'seconds' => '秒', - 'test' => '測試', - 'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。', - 'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。', - 'test_pushover' => 'Pushover 通知將發送到您在使用者設定的裝置。', - 'test_telegram' => 'Telegram 通知將發送到您在使用者設定的 Chat ID。', - 'send' => '傳送', - 'test_subject' => '標題', - 'test_message' => '訊息', - 'email_sent' => '傳送', - 'email_error' => '電子郵件傳送發生錯誤', - 'sms_sent' => '簡訊發送', - 'sms_error' => '簡訊發送發生錯誤', - 'sms_error_nomobile' => '無法傳送 SMS 簡訊測試:您設定的電話號碼無效或無法找到。', - 'pushover_sent' => '傳送 Pushover 通知', - 'pushover_error' => '傳送 Pushover 通知發生錯誤: %s', - 'pushover_error_noapp' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover App API token。', - 'pushover_error_nokey' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover key found 。', - 'telegram_sent' => '傳送 Telegram 通知', - 'telegram_error' => '傳送 Telegram 通知發生錯誤: %s', - 'telegram_error_notoken' => '無法傳送 Telegram 通知: 在系統設定找不到 Telegram API token。', - 'telegram_error_noid' => '無法傳送 Telegram 通知: 在您的個人資料找不到 Chat ID。', - 'log_retention_period' => '記錄保留期限', - 'log_retention_period_description' => '保留伺服器運作時間和記錄歸檔的天數,輸入0可以防止記錄被清除', - 'log_retention_days' => '日', - ), - 'notifications' => array( - 'off_sms' => '伺服器 \'%LABEL%\' 關機: ip=%IP%, port=%PORT%. Error=%ERROR%', - 'off_email_subject' => 'IMPORTANT: 服務器 \'%LABEL%\' 關機', - 'off_email_body' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', - 'off_pushover_title' => '伺服器 \'%LABEL%\' 關機', - 'off_pushover_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', - 'off_telegram_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
錯誤: %ERROR%
日期: %DATE%', - 'on_sms' => '伺服器 \'%LABEL%\' 運行中: ip=%IP%, port=%PORT%', - 'on_email_subject' => 'IMPORTANT: 伺服器 \'%LABEL%\' 運行中', - 'on_email_body' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', - 'on_pushover_title' => '伺服器 \'%LABEL%\' 運作中', - 'on_pushover_message' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', - 'on_telegram_message' => '伺服器 \'%LABEL%\' 恢復運作:

伺服器: %LABEL%
IP: %IP%
Port: %PORT%
日期: %DATE%', - ), - 'login' => array( - 'welcome_usermenu' => '歡迎,%user_name%', - 'title_sign_in' => '請登入', - 'title_forgot' => '忘記密碼', - 'title_reset' => '密碼重置', - 'submit' => '送出', - 'remember_me' => '記住我', - 'login' => '登入', - 'logout' => '登出', - 'username' => '使用者名稱', - 'password' => '密碼', - 'password_repeat' => '再次輸入密碼', - 'password_forgot' => '忘記密碼', - 'password_reset' => '重設密碼', - 'password_reset_email_subject' => '重設您的密碼', - 'password_reset_email_body' => '點選以下連結來重設密碼,這個連結於1小時後失效。

%link%', - 'error_user_incorrect' => '使用者不存在。', - 'error_login_incorrect' => '登入資料不正確。', - 'error_login_passwords_nomatch' => '密碼不符合。', - 'error_reset_invalid_link' => '重設密碼連結無效。', - 'success_password_forgot' => '重設密碼電子郵件已發送。', - 'success_password_reset' => '密碼重設成功,請登入。', - ), - 'error' => array( - '401_unauthorized' => '驗證失敗', - '401_unauthorized_description' => '您没有權限進入這個頁面。', - ), + 'name' => '繁體中文 - Traditional Chinese', + 'locale' => array( + '0' => 'zh_TW.UTF-8', + '1' => 'zh_TW', + '2' => 'chinese', + '3' => 'chinese-tw', + ), + 'locale_tag' => 'zh_TW', + 'locale_dir' => 'ltr', + 'system' => array( + 'title' => 'Server Monitor', + 'install' => '安裝', + 'action' => '動作', + 'save' => '儲存', + 'edit' => '編輯', + 'delete' => '刪除', + 'date' => '日期', + 'message' => '訊息', + 'yes' => '是', + 'no' => '否', + 'insert' => '插入', + 'add_new' => '增加', + 'update_available' => '找到新版本({version}) http://www.phpservermonitor.org.', + 'back_to_top' => '回到最上層', + 'go_back' => '返回', + 'ok' => '確定', + 'cancel' => '取消', + 'activate' => '啟用', + 'short_day_format' => '%B %e', + 'long_day_format' => '%B %e, %Y', + 'yesterday_format' => '昨日 %k:%M', + 'other_day_format' => '%A %k:%M', + 'never' => '從未', + 'hours_ago' => '%d小時前', + 'an_hour_ago' => '1小時前', + 'minutes_ago' => '%d分鐘前', + 'a_minute_ago' => '1分鐘前', + 'seconds_ago' => '%d秒前', + 'a_second_ago' => '剛剛', + 'year' => '年', + 'years' => '年', + 'month' => '月', + 'months' => '月', + 'day' => '日', + 'days' => '日', + 'hour' => '時', + 'hours' => '時', + 'minute' => '分', + 'minutes' => '分', + 'second' => '秒', + 'seconds' => '秒', + ), + 'menu' => array( + 'config' => '設定', + 'server' => '伺服器', + 'server_log' => '記錄', + 'server_status' => '狀態', + 'server_update' => '更新', + 'user' => '使用者', + 'help' => '說明', + ), + 'users' => array( + 'user' => '使用者', + 'name' => '顯示名稱', + 'user_name' => '使用者名稱', + 'password' => '密碼', + 'password_repeat' => '再次輸入密碼', + 'password_leave_blank' => '若密碼欄位保持空白,表示不做修改', + 'level' => '等級', + 'level_10' => '超級管理員', + 'level_20' => '一般使用者', + 'level_description' => '超級管理員 + 具備所有伺服器的管理權限,可管理使用者以及修改系統設定。
一般使用者 + 僅能查看以及更新自己所負責的伺服器。', + 'mobile' => '行動電話', + 'email' => '電子郵件', + 'pushover' => 'Pushover 通知', + 'pushover_description' => 'Pushover + 是一種雲端服務,讓你可以很方便的收到即時訊息通知,您可以到網站了解更多的內容。', + 'pushover_key' => 'Pushover 金鑰', + 'pushover_device' => 'Pushover 裝置', + 'pushover_device_description' => '發送訊息的裝置名稱,若保留空白,將會發送到所有的裝置。', + 'telegram' => 'Telegram 通知', + 'telegram_description' => 'Telegram + 是一種聊天應用程式,它提供很容易使用的的即時通知能力。您可以到 + documentation + 了解更多的內容。', + 'telegram_chat_id' => 'Telegram Chat ID', + 'telegram_chat_id_description' => '將訊息發送到指定的聊天室', + 'telegram_get_chat_id' => '點選這裡可以取得您的 Chat ID', + 'activate_telegram' => '啟用 Telegram 通知', + 'activate_telegram_description' => '允許 Telegram 將訊息發送到指定的 Chat + ID。若沒有啟用此項目,Telegram + 將不允許我們發送通知給您。', + 'telegram_bot_username_error_token' => '401 - 未授權,請確認您的 API Token 是有效的。', + 'telegram_bot_error' => '啟用 Telegram 通知時發生錯誤:%s', + 'delete_title' => '刪除使用者', + 'delete_message' => '您確定要刪除使用者 \'%1\'?', + 'deleted' => '已刪除使用者。', + 'updated' => '已更新使用者。', + 'inserted' => '已增加使用者。', + 'profile' => '個人資料', + 'profile_updated' => '個人資料已經更新。', + 'error_user_name_bad_length' => '使用者名稱長度必須為2-64個字元。', + 'error_user_name_invalid' => '使用者名稱只允許英文字母(a-z、A-Z)、數字(0-9)以及底線(_)。', + 'error_user_name_exists' => '這個使用者名稱已存在。', + 'error_user_email_bad_length' => '電子郵件長度為5-255個字元。', + 'error_user_email_invalid' => '無效的電子郵件。', + 'error_user_level_invalid' => '無效的使用者等級。', + 'error_user_no_match' => '這個使用者名稱不存在。', + 'error_user_password_invalid' => '無效的密碼。', + 'error_user_password_no_match' => '密碼不符。', + ), + 'log' => array( + 'title' => '記錄概覽', + 'type' => '類型', + 'status' => '狀態', + 'email' => '電子郵件通知', + 'sms' => '簡訊通知', + 'pushover' => 'Pushover 通知', + 'telegram' => 'Telegram 通知', + 'no_logs' => '沒有記錄', + 'clear' => '清除記錄', + 'delete_title' => '刪除記錄', + 'delete_message' => '您確定要刪除 所有 記錄?', + ), + 'servers' => array( + 'server' => '伺服器', + 'status' => '狀態', + 'label' => '標籤', + 'domain' => '網域/IP', + 'timeout' => '逾時', + 'timeout_description' => '等待伺服器回應的秒數。', + 'authentication_settings' => '驗證設定 (非必要)', + 'website_username' => '使用者', + 'website_username_description' => '存取這個網站的使用者。(只支援 Apache 驗證)', + 'website_password' => '密碼', + 'website_password_description' => '存取這個網站的使用者。(密碼將會以加密形式存放在資料庫)', + 'fieldset_monitoring' => '監視', + 'fieldset_permissions' => '權限', + 'port' => '連接埠', + 'custom_port' => '自訂連接埠', + 'popular_ports' => '常用連接埠', + 'please_select' => '請選擇', + 'type' => '類型', + 'type_website' => '網站', + 'type_service' => '服務', + 'type_ping' => 'Ping', + 'pattern' => '字串', + 'pattern_description' => '如果在網站上沒有找到符合的字串,則將網站標示為離線。', + 'pattern_online' => '指明網站上的字串', + 'pattern_online_description' => '線上:如果在網站上沒有找到符合的字串,則將網站標示為線上。', + 'header_name_description' => '標頭名稱 (區分大小寫)', + 'header_value_description' => '標頭的值,可以使用正則表示式。', + 'last_check' => '最後一次檢查', + 'last_online' => '最後一次上線', + 'last_offline' => '最後一次離線', + 'monitoring' => '監控中', + 'no_monitoring' => '未監控', + 'email' => '電子郵件通知', + 'send_email' => '發送電子郵件', + 'sms' => '簡訊通知', + 'send_sms' => '發送簡訊', + 'pushover' => 'Pushover 通知', + 'send_pushover' => '發送 Pushover 通知', + 'telegram' => 'Telegram 通知', + 'send_telegram' => '發送 Telegram 通知', + 'users' => '使用者', + 'delete_title' => '刪除伺服器', + 'delete_message' => '您確定要刪除這個伺服器 \'%1\'?', + 'deleted' => '伺服器已刪除。', + 'updated' => '伺服器已更新。', + 'inserted' => '伺服器已增加。', + 'latency' => '延遲', + 'latency_max' => '延遲 (最大)', + 'latency_min' => '延遲 (最小)', + 'latency_avg' => '延遲 (平均)', + 'uptime' => '上線時間', + 'year' => '年', + 'month' => '月', + 'week' => '週', + 'day' => '日', + 'hour' => '小時', + 'warning_threshold' => '警報臨界值', + 'warning_threshold_description' => '失敗達到多少次數則標示為離線。', + 'chart_last_week' => '上週', + 'chart_history' => '更早', + 'chart_day_format' => '%Y-%m-%d', + 'chart_long_date_format' => '%Y-%m-%d %H:%M:%S', + 'chart_short_date_format' => '%m/%d %H:%M', + 'chart_short_time_format' => '%H:%M', + 'warning_notifications_disabled_sms' => '簡訊通知已關閉。', + 'warning_notifications_disabled_email' => '電子郵件通知已關閉。', + 'warning_notifications_disabled_pushover' => 'Pushover 通知已關閉。', + 'warning_notifications_disabled_telegram' => 'Telegram 通知已關閉。', + 'error_server_no_match' => '找不到伺服器。', + 'error_server_label_bad_length' => '標籤必須在1到255間的字元。', + 'error_server_ip_bad_length' => '網域/IP必須在1到255間的字元。', + 'error_server_ip_bad_service' => '無效的 IP 位址。', + 'error_server_ip_bad_website' => '無效的網址。', + 'error_server_type_invalid' => '無效的的伺服器型態', + 'error_server_warning_threshold_invalid' => '警報臨界值必須是大於 0 的有效整數。', + ), + 'config' => array( + 'general' => '一般', + 'language' => '語言', + 'show_update' => '檢查更新', + 'password_encrypt_key' => '加密金鑰', + 'password_encrypt_key_note' => '這個加密金鑰將用於保護您登入這個網站的密碼,如果修改了此金鑰,原本已經存在的密碼將無法使用!', + 'proxy' => '啟用 Proxy', + 'proxy_url' => 'Proxy URL', + 'proxy_user' => 'Proxy 使用者名稱', + 'proxy_password' => 'Proxy 密碼', + 'email_status' => '啟用電子郵件通知', + 'email_from_email' => '寄件者信箱', + 'email_from_name' => '寄件者名稱', + 'email_smtp' => '使用SMTP發信', + 'email_smtp_host' => 'SMTP主機', + 'email_smtp_port' => 'SMTP連接埠口', + 'email_smtp_security' => 'SMTP安全性', + 'email_smtp_security_none' => '無', + 'email_smtp_username' => 'SMTP使用者名稱', + 'email_smtp_password' => 'SMTP使用者密碼', + 'email_smtp_noauth' => '留空白表示不做帳號驗證', + 'sms_status' => '啟用簡訊通知', + 'sms_gateway' => '簡訊服務提供者', + 'sms_gateway_username' => '簡訊閘道使用者名稱', + 'sms_gateway_password' => '簡訊閘道使用者密碼', + 'sms_from' => '發送人電話號碼', + 'pushover_status' => '啟用Pushover通知', + 'pushover_description' => 'Pushover是線上服務,讓您可以方便的收到即時通知,請參考 網站 可以得到更詳細的資訊。 ', + 'pushover_clone_app' => '點選這裡可快速建立Pushover App', + 'pushover_api_token' => 'Pushover App API Token', + 'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡->註冊Pushover App帳號 + 接著在這個網頁輸入你的的Pushover App API Token號碼。', + 'telegram_status' => '允許發送 Telegram 訊息', + 'telegram_description' => 'Telegram + 是一種聊天應用程式,它提供很容易使用的即時通知服務。請參考 + 文件庫 + 可以取得更多資訊與安裝說明。', + 'telegram_api_token' => 'Telegram API Token', + 'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 文件庫 取得說明。', + 'alert_type' => '需要提醒的類別', + 'alert_type_description' => '狀態改變: 伺服器 連線 -> 離線或連線 -> + 連線的狀態變化將會收到提醒通知。

離線: + 伺服器首次發生離線狀態將會收到提醒,如:設定為15分鐘執行一次,伺服器從1:00-6:00一直處於離線狀態那麼你將會在1:00首次收到一則提醒通知,之後便不會在收到重覆的提醒通知。

全部: + 每次執行當伺服器離線(即使伺服器離線很久已提醒過了)均發送提醒通知。', + 'alert_type_status' => '狀態改變', + 'alert_type_offline' => '離線', + 'alert_type_always' => '全部', + 'alert_proxy_url' => '格式: Host:Port', + 'log_status' => '狀態記錄', + 'log_status_description' => '如果啟用狀態記錄,則每一筆提醒通知都會保留記錄。', + 'log_email' => '保留電子郵件通知發送記錄', + 'log_sms' => '保留簡訊通知發送記錄', + 'log_pushover' => '保留 pushover 通知發送記錄', + 'log_telegram' => '保留 telegram 通知發送記錄', + 'updated' => '已更新設定。', + 'tab_email' => '電子郵件發送設定', + 'tab_sms' => '簡訊發送設定', + 'tab_pushover' => 'Pushover 通知', + 'tab_telegram' => 'Telegram 通知', + 'settings_email' => '電子郵件發送設定', + 'settings_sms' => '簡訊發送設定', + 'settings_pushover' => 'Pushover 發送設定', + 'settings_telegram' => 'Telegram 發送設定', + 'settings_notification' => '提醒設定', + 'settings_log' => '記錄設定', + 'settings_proxy' => 'Proxy 設定', + 'auto_refresh' => '自動更新', + 'seconds' => '秒', + 'test' => '測試', + 'test_email' => '電子郵件將發送到您在使用者設定內指定的電子郵件信箱。', + 'test_sms' => '簡訊將發送到您在使用者設定內指定的行動電話號碼。', + 'test_pushover' => 'Pushover 通知將發送到您在使用者設定的裝置。', + 'test_telegram' => 'Telegram 通知將發送到您在使用者設定的 Chat ID。', + 'send' => '傳送', + 'test_subject' => '標題', + 'test_message' => '訊息', + 'email_sent' => '傳送', + 'email_error' => '電子郵件傳送發生錯誤', + 'sms_sent' => '簡訊發送', + 'sms_error' => '簡訊發送發生錯誤', + 'sms_error_nomobile' => '無法傳送 SMS 簡訊測試:您設定的電話號碼無效或無法找到。', + 'pushover_sent' => '傳送 Pushover 通知', + 'pushover_error' => '傳送 Pushover 通知發生錯誤: %s', + 'pushover_error_noapp' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover App API token。', + 'pushover_error_nokey' => '無法傳送 Pushover 通知: 在系統設定找不到 Pushover key found 。', + 'telegram_sent' => '傳送 Telegram 通知', + 'telegram_error' => '傳送 Telegram 通知發生錯誤: %s', + 'telegram_error_notoken' => '無法傳送 Telegram 通知: 在系統設定找不到 Telegram API token。', + 'telegram_error_noid' => '無法傳送 Telegram 通知: 在您的個人資料找不到 Chat ID。', + 'log_retention_period' => '記錄保留期限', + 'log_retention_period_description' => '保留伺服器運作時間和記錄歸檔的天數,輸入0可以防止記錄被清除', + 'log_retention_days' => '日', + ), + 'notifications' => array( + 'off_sms' => '伺服器 \'%LABEL%\' 關機: ip=%IP%, port=%PORT%. Error=%ERROR%', + 'off_email_subject' => 'IMPORTANT: 服務器 \'%LABEL%\' 關機', + 'off_email_body' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: + %PORT%
錯誤: %ERROR%
日期: %DATE%', + 'off_pushover_title' => '伺服器 \'%LABEL%\' 關機', + 'off_pushover_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: + %PORT%
錯誤: %ERROR%
日期: %DATE%', + 'off_telegram_message' => '無法連線到以下伺服器:

伺服器: %LABEL%
IP: %IP%
Port: + %PORT%
錯誤: %ERROR%
日期: %DATE%', + 'on_email_subject' => 'IMPORTANT: 伺服器 \'%LABEL%\' 運行中', + 'on_pushover_title' => '伺服器 \'%LABEL%\' 運作中', + ), + 'login' => array( + 'welcome_usermenu' => '歡迎,%user_name%', + 'title_sign_in' => '請登入', + 'title_forgot' => '忘記密碼', + 'title_reset' => '密碼重置', + 'submit' => '送出', + 'remember_me' => '記住我', + 'login' => '登入', + 'logout' => '登出', + 'username' => '使用者名稱', + 'password' => '密碼', + 'password_repeat' => '再次輸入密碼', + 'password_forgot' => '忘記密碼', + 'password_reset' => '重設密碼', + 'password_reset_email_subject' => '重設您的密碼', + 'password_reset_email_body' => '點選以下連結來重設密碼,這個連結於1小時後失效。

%link%', + 'error_user_incorrect' => '使用者不存在。', + 'error_login_incorrect' => '登入資料不正確。', + 'error_login_passwords_nomatch' => '密碼不符合。', + 'error_reset_invalid_link' => '重設密碼連結無效。', + 'success_password_forgot' => '重設密碼電子郵件已發送。', + 'success_password_reset' => '密碼重設成功,請登入。', + ), + 'error' => array( + '401_unauthorized' => '驗證失敗', + '401_unauthorized_description' => '您没有權限進入這個頁面。', + ), ); From 50b5a6937ba9645cefa9f946344d3f7a52caa72e Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 19 Dec 2019 20:26:26 +0100 Subject: [PATCH 05/77] Update zh_TW.lang.php --- src/lang/zh_TW.lang.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lang/zh_TW.lang.php b/src/lang/zh_TW.lang.php index d7de212f..47b73a9f 100644 --- a/src/lang/zh_TW.lang.php +++ b/src/lang/zh_TW.lang.php @@ -49,8 +49,6 @@ $sm_lang = array( 'no' => '否', 'insert' => '插入', 'add_new' => '增加', - 'update_available' => '找到新版本({version}) http://www.phpservermonitor.org.', 'back_to_top' => '回到最上層', 'go_back' => '返回', 'ok' => '確定', @@ -262,16 +260,14 @@ $sm_lang = array( 'pushover_description' => 'Pushover是線上服務,讓您可以方便的收到即時通知,請參考 網站 可以得到更詳細的資訊。 ', 'pushover_clone_app' => '點選這裡可快速建立Pushover App', - 'pushover_api_token' => 'Pushover App API Token', 'pushover_api_token_description' => '在您使用 Pushover 通知之前,需要先到這裡->註冊Pushover App帳號 + target="_blank" rel="noopener">註冊Pushover App帳號 接著在這個網頁輸入你的的Pushover App API Token號碼。', 'telegram_status' => '允許發送 Telegram 訊息', 'telegram_description' => 'Telegram 是一種聊天應用程式,它提供很容易使用的即時通知服務。請參考 文件庫 可以取得更多資訊與安裝說明。', - 'telegram_api_token' => 'Telegram API Token', 'telegram_api_token_description' => '使用 Telegram 通知之前,您必需先取得 API Token。請到 文件庫 取得說明。', 'alert_type' => '需要提醒的類別', From 6ba4b5923907df3793b5e22c04cd1335b3d944a7 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Tue, 14 Jan 2020 19:59:08 +0100 Subject: [PATCH 06/77] Changed ping from socket to exec function As there are a lot of problems with permissions and ping, the function now uses exec(). Resolved #405, #576, #614, #748. Co-Authored-By: Sean Perryman Co-Authored-By: Luke C --- src/psm/Util/Server/Updater/StatusUpdater.php | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index bbcc5791..24d37cd8 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -165,40 +165,44 @@ class StatusUpdater } /** - * Check the current servers ping status - Code from http://stackoverflow.com/a/20467492 + * Check the current servers ping status * @param int $max_runs * @param int $run * @return boolean */ protected function updatePing($max_runs, $run = 1) { - // save response time - $starttime = microtime(true); - // set ping payload - $package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost"; + if ($max_runs == null || $max_runs > 1) { + $max_runs = 1; + } + $txt = exec("ping -c " . $max_runs . " " . $this->server['ip']); + // 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\\.])'; - $socket = socket_create(AF_INET, SOCK_RAW, 1); - socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 10, 'usec' => 0)); - socket_connect($socket, $this->server['ip'], null); + if ($c = preg_match_all("/" . $re1 . $re2 . $re3 . $re4 . "/is", $txt, $matches)) { + $result = $matches[1][0]; + } else { + $result = null; + } - socket_send($socket, $package, strLen($package), 0); - if (socket_read($socket, 255)) { + if (!is_null($result)) { $status = true; } else { $status = false; - - // set error message - $errorcode = socket_last_error(); - $this->error = "Couldn't create socket [" . $errorcode . "]: " . socket_strerror($errorcode); } - $this->rtime = microtime(true) - $starttime; - socket_close($socket); + //Divide by a thousand to convert to milliseconds + $this->rtime = $result / 1000; // check if server is available and rerun if asked. if (!$status && $run < $max_runs) { return $this->updatePing($max_runs, $run + 1); } - return $status; } From 0550ff7dcf5162f446188de264fe26f3b302117c Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Wed, 15 Jan 2020 10:33:47 +0100 Subject: [PATCH 07/77] Added ping error --- src/psm/Util/Server/Updater/StatusUpdater.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 24d37cd8..8dfa421f 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -175,7 +175,9 @@ class StatusUpdater if ($max_runs == null || $max_runs > 1) { $max_runs = 1; } - $txt = exec("ping -c " . $max_runs . " " . $this->server['ip']); + $result = null; + // Execute ping + $txt = exec("ping -c " . $max_runs . " " . $this->server['ip'] . " 2>&1", $output); // Non-greedy match on filler $re1 = '.*?'; // Uninteresting: float @@ -184,16 +186,16 @@ class StatusUpdater $re3 = '.*?'; // Float 1 $re4 = '([+-]?\\d*\\.\\d+)(?![-+0-9\\.])'; - - if ($c = preg_match_all("/" . $re1 . $re2 . $re3 . $re4 . "/is", $txt, $matches)) { + if (preg_match_all("/" . $re1 . $re2 . $re3 . $re4 . "/is", $txt, $matches)) { $result = $matches[1][0]; - } else { - $result = null; } 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 From 676e80d42f100353509178eb040e8b1d12df3b77 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Wed, 15 Jan 2020 23:15:30 +0100 Subject: [PATCH 08/77] Improved servers table layout Fixes #779. Co-Authored-By: James --- .../module/server/server/list.tpl.html | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index 17c6262d..3a01ac82 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -5,17 +5,17 @@ - {{ label_label }} - {{ label_domain }} - {{ label_port }} - {{ label_type }} - {{ label_rtime }} - {{ label_last_online }} - {{ label_last_offline }} - {{ label_monitoring }} - {% if user_level == 10 %} - - {% endif %} + {{ label_label }} + {{ label_domain }} + {{ label_port }} + {{ label_type }} + {{ label_rtime }} + {{ label_last_online }} + {{ label_last_offline }} + {{ label_monitoring }} + {% if user_level == 10 %} + + {% endif %} No result From 71c4114747f37f7dde2ab3ae8a811c705dd54bbb Mon Sep 17 00:00:00 2001 From: Petr Suchy Date: Tue, 4 Feb 2020 15:44:11 +0100 Subject: [PATCH 09/77] Fixed psm_password_decrypt BUG: HTTP2 Authentification Fixes #706. --- src/includes/functions.inc.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 783aa795..85d3cb63 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -893,15 +893,12 @@ namespace { $cipher = "AES-256-CBC"; $ivlen = openssl_cipher_iv_length($cipher); $iv = substr($data, 0, $ivlen); - $decrypted = rtrim( - openssl_decrypt( - base64_encode(substr($data, $ivlen)), - $cipher, - hash('sha256', $key, true), - OPENSSL_ZERO_PADDING, - $iv - ), - "\0" + $decrypted = openssl_decrypt( + substr($data, $ivlen), + $cipher, + hash('sha256', $key, true), + OPENSSL_RAW_DATA, + $iv ); return $decrypted; From 3568a5700b7df9795b0c789c80281d71ff3df75b Mon Sep 17 00:00:00 2001 From: Nayef Alebrahim <37157638+nayefalebrahim@users.noreply.github.com> Date: Tue, 4 Feb 2020 18:16:30 +0300 Subject: [PATCH 10/77] Fixed removing and demoting last admin (#841) Fixes #824. Co-authored-by: Tim --- .../Module/User/Controller/UserController.php | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/psm/Module/User/Controller/UserController.php b/src/psm/Module/User/Controller/UserController.php index cbc3ff64..496c0826 100644 --- a/src/psm/Module/User/Controller/UserController.php +++ b/src/psm/Module/User/Controller/UserController.php @@ -274,13 +274,6 @@ class UserController extends AbstractController $user_validator->username($clean['user_name'], $user_id); $user_validator->email($clean['email']); $user_validator->level($clean['level']); - if ( - count($this->db->select(PSM_DB_PREFIX . 'users', array('level' => PSM_USER_ADMIN))) == 1 && - $this->getUser()->getUserLevel() == PSM_USER_ADMIN - ) { - $this->addMessage(psm_get_lang('users', 'error_user_admin_cant_be_deleted'), 'warning'); - $clean['level'] = PSM_USER_ADMIN; - } // always validate password for new users, // but only validate it for existing users when they change it. @@ -302,6 +295,15 @@ class UserController extends AbstractController if ($user_id > 0) { // edit user unset($clean['password']); // password update is executed separately + $admins = $this->db->select(PSM_DB_PREFIX . 'users', array('level' => PSM_USER_ADMIN)); + if ( + (int) count($admins) === (int) 1 && + (int) $admins[0]['user_id'] === (int) $user_id && + (int) $clean['level'] === (int) PSM_USER_USER + ) { + $this->addMessage(psm_get_lang('users', 'error_user_admin_cant_be_deleted'), 'warning'); + $clean['level'] = PSM_USER_ADMIN; + } $this->db->save(PSM_DB_PREFIX . 'users', $clean, array('user_id' => $user_id)); $this->addMessage(psm_get_lang('users', 'updated'), 'success'); @@ -352,7 +354,11 @@ class UserController extends AbstractController try { $this->container->get('util.user.validator')->userId($id); - if (count($this->db->select(PSM_DB_PREFIX . 'users', array('level' => PSM_USER_ADMIN))) == 1) { + $admins = $this->db->select(PSM_DB_PREFIX . 'users', array('level' => PSM_USER_ADMIN)); + if ( + (int) count($admins) === (int) 1 && + (int) $admins[0]['user_id'] === (int) $id + ) { $this->addMessage(psm_get_lang('users', 'error_user_admin_cant_be_deleted'), 'error'); } else { $this->db->delete(PSM_DB_PREFIX . 'users', array('user_id' => $id,)); From 442f9d115ef15bd62f40c32010a77fc2fcb05248 Mon Sep 17 00:00:00 2001 From: Petr Suchy Date: Tue, 4 Feb 2020 16:41:34 +0100 Subject: [PATCH 11/77] Added Separate check when server is down (#844) Future request - separate checks when down. Closes #755. --- cron/status.cron.php | 73 ++++++++++++++++++++++++--- docs/install.rst | 11 ++++ src/psm/Util/Install/Installer.php | 4 +- src/psm/Util/Server/UpdateManager.php | 9 +++- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/cron/status.cron.php b/cron/status.cron.php index 92b70182..249e8743 100644 --- a/cron/status.cron.php +++ b/cron/status.cron.php @@ -28,6 +28,9 @@ namespace { // include main configuration and functionality + use psm\Router; + use psm\Util\Server\UpdateManager; + require_once __DIR__ . '/../src/bootstrap.php'; if (!psm_is_cli()) { @@ -81,21 +84,79 @@ namespace { // however if the cron has been running for X mins, we'll assume it died and run anyway // if you want to change PSM_CRON_TIMEOUT, have a look in src/includes/psmconfig.inc.php. // or you can provide the --timeout=x argument + + $status = null; + if (PHP_SAPI === 'cli') { + $shortOptions = 's:'; // status + + $longOptions = [ + 'status:' + ]; + + $options = getopt($shortOptions, $longOptions); + + $possibleValues = [ + 'on' => 'on', + '1' => 'on', + 'up' => 'on', + 'off' => 'off', + '0' => 'off', + 'down' => 'off' + ]; + + if ( + true === array_key_exists('status', $options) && + true === array_key_exists(strtolower($options['status']), $possibleValues) + ) { + $status = $possibleValues[$options['status']]; + } elseif ( + true === array_key_exists('s', $options) && + true === array_key_exists(strtolower($options['s']), $possibleValues) + ) { + $status = $possibleValues[$options['s']]; + } + } + + if ($status === 'off') { + $confPrefix = 'cron_off_'; + } else { + $confPrefix = 'cron_'; + } + $time = time(); if ( - psm_get_conf('cron_running') == 1 + psm_get_conf($confPrefix . 'running') == 1 && $cron_timeout > 0 - && ($time - psm_get_conf('cron_running_time') < $cron_timeout) + && ($time - psm_get_conf($confPrefix . 'running_time') < $cron_timeout) ) { die('Cron is already running. Exiting.'); } if (!defined('PSM_DEBUG') || !PSM_DEBUG) { - psm_update_conf('cron_running', 1); + psm_update_conf($confPrefix . 'running', 1); } - psm_update_conf('cron_running_time', $time); + psm_update_conf($confPrefix . 'running_time', $time); + /** @var Router $router */ + /** @var UpdateManager $autorun */ $autorun = $router->getService('util.server.updatemanager'); - $autorun->run(true); - psm_update_conf('cron_running', 0); + if ($status !== 'off') { + $autorun->run(true, $status); + } else { + set_time_limit(60); + if (false === defined('CRON_DOWN_INTERVAL')) { + define('CRON_DOWN_INTERVAL', 5); // every 5 second call update + } + $start = time(); + $i = 0; + while ($i < 59) { + $autorun->run(true, $status); + if ($i < (59 - CRON_DOWN_INTERVAL)) { + time_sleep_until($start + $i + CRON_DOWN_INTERVAL); + } + $i += CRON_DOWN_INTERVAL; + } + } + + psm_update_conf($confPrefix . 'running', 0); } diff --git a/docs/install.rst b/docs/install.rst index 93898e36..56126553 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -92,6 +92,16 @@ Please note that some distros have user-specific crontabs (e.g. Debian). If that */15 * * * * /usr/bin/php /var/www/html/phpservermon/cron/status.cron.php +If you want to check in different intervals online and offline servers you can use attribute `-s` (or `--status`) with value `on` or `off`. +So for example you want to check your servers which are online every 10 minutes and offline every 5 seconds. So configure two cron jobs:: + + */10 * * * * /usr/bin/php /var/www/html/phpservermon/cron/status.cron.php -s on + */1 * * * * /usr/bin/php /var/www/html/phpservermon/cron/status.cron.php -s off + +By default `off` servers are checked every 5 seconds. If you want to change it add into your config file this constant with required value in seconds:: + + define('CRON_DOWN_INTERVAL', 1); // every 1 second call update + The update script has been designed to prevent itself from running multiple times. It has a maximum timeout of 10 minutes. After that the script is assumed dead and the cronjob will run again. If you want to change the 10 minutes timeout, find the constant "PSM_CRON_TIMEOUT" in src/includes/psmconfig.inc.php. @@ -144,3 +154,4 @@ If you have problems setting up or accessing your monitor and do not know why, e To enable debug mode, add the following line to your config.php file:: define('PSM_DEBUG', true); + diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 010b9fbf..eb307294 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -178,7 +178,9 @@ class Installer ('show_update', '1'), ('last_update_check', '0'), ('cron_running', '0'), - ('cron_running_time', '0');"; + ('cron_running_time', '0'), + ('cron_off_running', '0'), + ('cron_off_running_time', '0');"; $this->execSQL($queries); } diff --git a/src/psm/Util/Server/UpdateManager.php b/src/psm/Util/Server/UpdateManager.php index 29a397cd..92b37bad 100644 --- a/src/psm/Util/Server/UpdateManager.php +++ b/src/psm/Util/Server/UpdateManager.php @@ -49,9 +49,14 @@ class UpdateManager implements ContainerAwareInterface * Go :-) * * @param boolean $skip_perms if TRUE, no user permissions will be taken in account and all servers will be updated + * @param string|null $status If all servers (null), or just `on` or `off` should be checked. */ - public function run($skip_perms = false) + public function run($skip_perms = false, $status = null) { + if (false === in_array($status, ['on', 'off'], true)) { + $status = null; + } + // check if we need to restrict the servers to a certain user $sql_join = ''; @@ -67,7 +72,7 @@ class UpdateManager implements ContainerAwareInterface `s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`telegram` FROM `" . PSM_DB_PREFIX . "servers` AS `s` {$sql_join} - WHERE `active`='yes' "; + WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : ''); $servers = $this->container->get('db')->query($sql); From 45d1c03e5a15679295baca63c0bdf30067b1b723 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 4 Feb 2020 16:44:48 +0100 Subject: [PATCH 12/77] Feature/ssl cert expiration check (#831) Added ssl expiration to warning state. --- src/includes/functions.inc.php | 7 ++- src/includes/psmconfig.inc.php | 2 +- src/lang/en_US.lang.php | 7 +++ .../Controller/AbstractServerController.php | 13 ++++- .../Server/Controller/ServerController.php | 5 ++ .../Server/Controller/StatusController.php | 2 + src/psm/Util/Install/Installer.php | 18 +++++++ src/psm/Util/Server/ServerValidator.php | 14 +++++ src/psm/Util/Server/Updater/StatusUpdater.php | 52 ++++++++++++++++--- .../module/server/server/update.tpl.html | 4 +- .../module/server/server/view.tpl.html | 6 +-- 11 files changed, 116 insertions(+), 14 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 85d3cb63..3036c8fa 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -390,7 +390,7 @@ namespace { * @param string|bool $website_password Password website * @param string|null $request_method Request method like GET, POST etc. * @param string|null $post_field POST data - * @return string cURL result + * @return array cURL result */ function psm_curl_get( $href, @@ -418,6 +418,7 @@ namespace { curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_ENCODING, ''); + curl_setopt($ch, CURLOPT_CERTINFO, 1); if (!empty($request_method)) { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method); @@ -455,7 +456,9 @@ namespace { PSM_VERSION . '; +https://github.com/phpservermon/phpservermon)'); } - $result = curl_exec($ch); + $result['exec'] = curl_exec($ch); + $result['info'] = curl_getinfo($ch); + curl_close($ch); if (defined('PSM_DEBUG') && PSM_DEBUG === true && psm_is_cli()) { diff --git a/src/includes/psmconfig.inc.php b/src/includes/psmconfig.inc.php index 530753c8..314eccdb 100644 --- a/src/includes/psmconfig.inc.php +++ b/src/includes/psmconfig.inc.php @@ -30,7 +30,7 @@ /** * Current PSM version */ -define('PSM_VERSION', '3.4.5'); +define('PSM_VERSION', '3.4.6-beta.1'); /** * URL to check for updates. Will not be checked if turned off on config page. diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index 621a6aed..570d32c2 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -247,6 +247,11 @@ $sm_lang = array( 'hour' => 'Hour', 'warning_threshold' => 'Warning threshold', 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', + 'ssl_cert_expiry_days' => 'SSL Certificate Validity', + 'ssl_cert_expiry_days_description' => 'The minimum remaining days the SSL certificate is still valid. Use 0 to + disable check.', + 'ssl_cert_expired' => 'SSL certificate expired since', + 'ssl_cert_expiring' => 'SSL certificate expiring:', 'chart_last_week' => 'Last week', 'chart_history' => 'History', 'chart_day_format' => '%Y-%m-%d', @@ -264,6 +269,8 @@ $sm_lang = array( 'error_server_ip_bad_website' => 'The website URL is not valid.', 'error_server_type_invalid' => 'The selected server type is invalid.', 'error_server_warning_threshold_invalid' => 'The warning threshold must be a valid integer greater than 0.', + 'error_server_ssl_cert_expiry_days' => 'The remaining days for SSL certificate validity must be a valid integer + greater than or equal to 0.', ), 'config' => array( 'general' => 'General', diff --git a/src/psm/Module/Server/Controller/AbstractServerController.php b/src/psm/Module/Server/Controller/AbstractServerController.php index 1a1c210e..efc70072 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.php @@ -85,6 +85,8 @@ abstract class AbstractServerController extends AbstractController `s`.`telegram`, `s`.`warning_threshold`, `s`.`warning_threshold_counter`, + `s`.`ssl_cert_expiry_days`, + `s`.`ssl_cert_expired_time`, `s`.`timeout`, `s`.`website_username`, `s`.`website_password`, @@ -120,7 +122,16 @@ abstract class AbstractServerController extends AbstractController } $server['last_check'] = psm_timespan($server['last_check']); - if ($server['status'] == 'on' && $server['warning_threshold_counter'] > 0) { + if ( + ( + $server['status'] == 'on' && + $server['warning_threshold_counter'] > 0 + ) || ( + $server['status'] == 'on' && + $server['ssl_cert_expired_time'] !== null && + $server['ssl_cert_expiry_days'] > 0 + ) + ) { $server['status'] = 'warning'; } diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 097329fd..ab27dd68 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -208,6 +208,7 @@ class ServerController extends AbstractServerController 'edit_value_website_username' => $edit_server['website_username'], 'edit_value_website_password' => empty($edit_server['website_password']) ? '' : sha1($edit_server['website_password']), + 'edit_value_ssl_cert_expiry_days' => $edit_server['ssl_cert_expiry_days'], 'edit_type_selected_' . $edit_server['type'] => 'selected="selected"', 'edit_active_selected' => $edit_server['active'], 'edit_email_selected' => $edit_server['email'], @@ -281,6 +282,7 @@ class ServerController extends AbstractServerController 'header_name' => psm_POST('header_name', ''), 'header_value' => psm_POST('header_value', ''), 'warning_threshold' => intval(psm_POST('warning_threshold', 0)), + 'ssl_cert_expiry_days' => intval(psm_POST('ssl_cert_expiry_days', 1)), 'active' => in_array($_POST['active'], array('yes', 'no')) ? $_POST['active'] : 'no', 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', @@ -325,6 +327,7 @@ class ServerController extends AbstractServerController $server_validator->type($clean['type']); $server_validator->ip($clean['ip'], $clean['type']); $server_validator->warningThreshold($clean['warning_threshold']); + $server_validator->sslCertExpiryDays($clean['ssl_cert_expiry_days']); } catch (\InvalidArgumentException $ex) { $this->addMessage(psm_get_lang('servers', 'error_' . $ex->getMessage()), 'error'); return $this->executeEdit(); @@ -558,6 +561,8 @@ class ServerController extends AbstractServerController 'label_users' => psm_get_lang('servers', 'users'), 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), + 'label_ssl_cert_expiry_days' => psm_get_lang('servers', 'ssl_cert_expiry_days'), + 'label_ssl_cert_expiry_days_description' => psm_get_lang('servers', 'ssl_cert_expiry_days_description'), 'label_action' => psm_get_lang('system', 'action'), 'label_save' => psm_get_lang('system', 'save'), 'label_go_back' => psm_get_lang('system', 'go_back'), diff --git a/src/psm/Module/Server/Controller/StatusController.php b/src/psm/Module/Server/Controller/StatusController.php index efe840f3..d4ee083d 100644 --- a/src/psm/Module/Server/Controller/StatusController.php +++ b/src/psm/Module/Server/Controller/StatusController.php @@ -100,6 +100,8 @@ class StatusController extends AbstractServerController $layout_data['servers_offline'][] = $server; } elseif ($server['warning_threshold_counter'] > 0) { $layout_data['servers_warning'][] = $server; + } elseif ($server['ssl_cert_expired_time'] !== null && $server['ssl_cert_expiry_days'] > 0) { + $layout_data['servers_warning'][] = $server; } else { $layout_data['servers_online'][] = $server; } diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index eb307294..78f078c9 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -265,6 +265,8 @@ class Installer `telegram` enum('yes','no') NOT NULL default 'yes', `warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1', `warning_threshold_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', + `ssl_cert_expiry_days` mediumint(1) unsigned NOT NULL DEFAULT '0', + `ssl_cert_expired_time` varchar(255) NULL, `timeout` smallint(1) unsigned NULL DEFAULT NULL, `website_username` varchar(255) DEFAULT NULL, `website_password` varchar(255) DEFAULT NULL, @@ -343,6 +345,9 @@ class Installer if (version_compare($version_from, '3.4.2', '<')) { $this->upgrade342(); } + if (version_compare($version_from, '3.4.6-beta.1', '<')) { + $this->upgrade346(); + } psm_update_conf('version', $version_to); } @@ -657,4 +662,17 @@ class Installer $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` CHANGE `last_output` `last_output` TEXT;"; $this->execSQL($queries); } + + /** + * Upgrade for v3.4.6 release + */ + protected function upgrade346() + { + $queries = array(); + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` + ADD `ssl_cert_expiry_days` MEDIUMINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `warning_threshold_counter`"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` + ADD `ssl_cert_expired_time` VARCHAR(255) NULL AFTER `ssl_cert_expiry_days`"; + $this->execSQL($queries); + } } diff --git a/src/psm/Util/Server/ServerValidator.php b/src/psm/Util/Server/ServerValidator.php index 63e5688b..18dc658b 100644 --- a/src/psm/Util/Server/ServerValidator.php +++ b/src/psm/Util/Server/ServerValidator.php @@ -154,4 +154,18 @@ class ServerValidator } return true; } + + /** + * Check SSL expiry days + * @param int $value + * @return boolean + * @throws \InvalidArgumentException + */ + public function sslCertExpiryDays($value) + { + if (!is_numeric($value) || $value < 0) { + throw new \InvalidArgumentException('server_ssl_cert_expiry_days'); + } + return true; + } } diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 8dfa421f..da0cb72e 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -41,6 +41,8 @@ class StatusUpdater public $header = ''; + public $curl_info = ''; + public $rtime = 0; public $status_new = false; @@ -86,6 +88,7 @@ class StatusUpdater $this->server_id = $server_id; $this->error = ''; $this->header = ''; + $this->curl_info = ''; $this->rtime = ''; // get server info from db @@ -96,7 +99,7 @@ class StatusUpdater 'type', 'pattern', 'pattern_online', 'post_field', 'allow_http_status', 'redirect_check', 'header_name', 'header_value', 'status', 'active', 'warning_threshold', - 'warning_threshold_counter', 'timeout', 'website_username', + 'warning_threshold_counter', 'ssl_cert_expiry_days', 'ssl_cert_expired_time', 'timeout', 'website_username', 'website_password', 'last_offline' )); if (empty($this->server)) { @@ -263,12 +266,13 @@ class StatusUpdater $this->server['request_method'], $this->server['post_field'] ); - $this->header = $curl_result; + $this->header = $curl_result['exec']; + $this->curl_info = $curl_result['info']; $this->rtime = (microtime(true) - $starttime); // the first line would be the status code.. - $status_code = strtok($curl_result, "\r\n"); + $status_code = strtok($curl_result['exec'], "\r\n"); // keep it general // $code[2][0] = status code // $code[3][0] = name of status code @@ -299,7 +303,7 @@ class StatusUpdater ($this->server['pattern_online'] == 'yes') == !preg_match( "/{$this->server['pattern']}/i", - $curl_result + $curl_result['exec'] ) ) { $this->error = "TEXT ERROR : Pattern '{$this->server['pattern']}' " . @@ -314,7 +318,7 @@ class StatusUpdater $location_matches = array(); preg_match( '/([Ll]ocation: )(https*:\/\/)(www.)?([a-zA-Z.:0-9]*)([\/][[:alnum:][:punct:]]*)/', - $curl_result, + $curl_result['exec'], $location_matches ); if (!empty($location_matches)) { @@ -335,7 +339,7 @@ class StatusUpdater if ($this->server['header_name'] != '' && $this->server['header_value'] != '') { $header_flag = false; // Only get the header text if the result also includes the body - $header_text = substr($curl_result, 0, strpos($curl_result, "\r\n\r\n")); + $header_text = substr($curl_result['exec'], 0, strpos($curl_result['exec'], "\r\n\r\n")); foreach (explode("\r\n", $header_text) as $i => $line) { if ($i === 0 || strpos($line, ':') == false) { continue; // We skip the status code & other non-header lines. Needed for proxy or redirects @@ -362,6 +366,9 @@ class StatusUpdater } } + // Check ssl cert + $this->checkSsl($this->server, $this->error, $result); + // check if server is available and rerun if asked. if (!$result && $run < $max_runs) { return $this->updateWebsite($max_runs, $run + 1); @@ -389,4 +396,37 @@ class StatusUpdater { return $this->rtime; } + + /** + * Check if a server speaks SSL and if the certificate is not expired. + * @param string $error + * @param bool $result + */ + private function checkSsl($server, &$error, &$result) + { + if (version_compare(PHP_RELEASE_VERSION, '7.1', '<')) { + $error = "The server you're running PSM on must use PHP 7.1 or higher to test the SSL expiration."; + return; + } + if ( + !empty($this->curl_info['certinfo']) && + $server['ssl_cert_expiry_days'] > 0 + ) { + $cert_expiration_date = strtotime($this->curl_info['certinfo'][0]['Expire date']); + $expiration_time = round((int)($cert_expiration_date - time()) / 86400); + $latest_time = time() + (86400 * $server['ssl_cert_expiry_days']); + if ($expiration_time >= 0) { + $this->header = psm_get_lang('servers', 'ssl_cert_expiring') . " " . + psm_date($this->curl_info['certinfo'][0]['Expire date']) . + "\n\n" . $this->header; + $save['ssl_cert_expired_time'] = null; + } else { + $error = psm_get_lang('servers', 'ssl_cert_expired') . " " . + psm_timespan($cert_expiration_date) . ".\n\n" . + $error; + $save['ssl_cert_expired_time'] = $expiration_time; + } + $this->db->save(PSM_DB_PREFIX . 'servers', $save, array('server_id' => $this->server_id)); + } + } } diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index 5d9eee53..e5fb7fbf 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -46,7 +46,9 @@ - {{ macro.input_field("number", "port", "port types typeService", "port", label_custom_port, edit_value_port, null, "5") }} + {{ macro.input_field("number", "port", "port types typeService", "port", label_custom_port, edit_value_port, null, "5") }} + + {{ macro.input_field("number", "ssl_cert_expiry_days", "types typeWebsite", "ssl_cert_expiry_days", label_ssl_cert_expiry_days, edit_value_ssl_cert_expiry_days, 0, "5", 'ssl_cert_help', label_ssl_cert_expiry_days_description) }}
diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index ff8783a6..05b9c984 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -227,13 +227,13 @@
  • {{ label_last_error }}:
    -
    {{ last_error }}
    +
    {{ last_error|nl2br }}
  • {{ label_last_output }}:
    -
    {{ last_output_truncated }}
    +
    {{ last_output_truncated|nl2br }}
    {% if last_output_truncated != last_output %}
    @@ -247,7 +247,7 @@
  • {{ label_last_error_output }}:
    -
    {{ last_error_output_truncated }}
    +
    {{ last_error_output_truncated|nl2br }}
    {% if last_error_output_truncated != last_error_output %}
    From e32977ffff167001f92430d7d63d2c86773cd075 Mon Sep 17 00:00:00 2001 From: "Ing. Petr Suchy" Date: Fri, 7 Feb 2020 07:43:16 +0100 Subject: [PATCH 13/77] *fix - check and update latest version --- src/includes/functions.inc.php | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 3036c8fa..226b620f 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -555,22 +555,32 @@ namespace { // update last check date psm_update_conf('last_update_check', time()); $latest = psm_curl_get(PSM_UPDATE_URL); + if ($latest['info'] === false || (int)$latest['info']['http_code'] >= 300) { + // error + return false; + } // extract latest version from Github. - preg_match('/"tag_name":"[v](([\d][.][\d][.][\d])(-?\w*))"/', $latest, $latest); - // add latest version to database - if (!empty($latest) && strlen($latest[2]) < 15) { - psm_update_conf('version_update_check', $latest[2]); + $githubInfo = json_decode($latest['exec']); + if (property_exists($githubInfo, 'tag_name') === false) { + // version not found + return false; + } + $tagName = $githubInfo->tag_name; + $latestVersion = str_replace('v', '', $tagName); + // check from old version ... maybe has reason but I don't think so ... + if (empty($latestVersion) === true || strlen($latestVersion) >= 15) { + // weird version + return false; + } + // add latest version to database + psm_update_conf('version_update_check', $latestVersion); } else { - $latest[2] = psm_get_conf('version_update_check'); + $latestVersion = psm_get_conf('version_update_check'); } - if (!empty($latest)) { - $current = psm_get_conf('version'); - return version_compare($latest[2], $current, '>'); - } else { - return false; - } + $current = psm_get_conf('version'); + return version_compare($latestVersion, $current, '>'); } /** From 8fa1bf6c0d7a628a7d3c19cbae4711b358dcb53a Mon Sep 17 00:00:00 2001 From: "Ing. Petr Suchy" Date: Fri, 7 Feb 2020 07:59:50 +0100 Subject: [PATCH 14/77] *edit - check ssl just when other error is not already in --- src/psm/Util/Server/Updater/StatusUpdater.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index da0cb72e..7b54cbe0 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -366,8 +366,10 @@ class StatusUpdater } } - // Check ssl cert - $this->checkSsl($this->server, $this->error, $result); + // Check ssl cert just when other error is not already in... + if ($result !== false) { + $this->checkSsl($this->server, $this->error, $result); + } // check if server is available and rerun if asked. if (!$result && $run < $max_runs) { From 5934e9a25c1bedda308c1c5c38f28510deec5751 Mon Sep 17 00:00:00 2001 From: "Ing. Petr Suchy" Date: Fri, 7 Feb 2020 08:03:12 +0100 Subject: [PATCH 15/77] *fix - checkSsl should check PHP_VERSION and not PHP_RELEASE_VERSION --- src/psm/Util/Server/Updater/StatusUpdater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 7b54cbe0..635dcd02 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -406,7 +406,7 @@ class StatusUpdater */ private function checkSsl($server, &$error, &$result) { - if (version_compare(PHP_RELEASE_VERSION, '7.1', '<')) { + if (version_compare(PHP_VERSION, '7.1', '<')) { $error = "The server you're running PSM on must use PHP 7.1 or higher to test the SSL expiration."; return; } From 51dbbf9510b64dab76fcd9b1ae80872d40c81aef Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sat, 8 Feb 2020 20:57:53 +0100 Subject: [PATCH 16/77] Refactor --- src/includes/functions.inc.php | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 226b620f..f054ff9f 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -555,28 +555,27 @@ namespace { // update last check date psm_update_conf('last_update_check', time()); $latest = psm_curl_get(PSM_UPDATE_URL); - if ($latest['info'] === false || (int)$latest['info']['http_code'] >= 300) { - // error - return false; - } - // extract latest version from Github. - $githubInfo = json_decode($latest['exec']); - if (property_exists($githubInfo, 'tag_name') === false) { - // version not found - return false; - } - $tagName = $githubInfo->tag_name; - $latestVersion = str_replace('v', '', $tagName); - // check from old version ... maybe has reason but I don't think so ... - if (empty($latestVersion) === true || strlen($latestVersion) >= 15) { - // weird version - return false; - + if ($latest['info'] === false || (int)$latest['info']['http_code'] >= 300) { + // error + return false; } - // add latest version to database - psm_update_conf('version_update_check', $latestVersion); + // extract latest version from Github. + $githubInfo = json_decode($latest['exec']); + if (property_exists($githubInfo, 'tag_name') === false) { + // version not found + return false; + } + $tagName = $githubInfo->tag_name; + $latestVersion = str_replace('v', '', $tagName); + // check from old version ... maybe has reason but I don't think so ... + if (empty($latestVersion) === true || strlen($latestVersion) >= 15) { + // weird version + return false; + } + // add latest version to database + psm_update_conf('version_update_check', $latestVersion); } else { - $latestVersion = psm_get_conf('version_update_check'); + $latestVersion = psm_get_conf('version_update_check'); } $current = psm_get_conf('version'); From 7ffc75598a6685dc89b3e693fc02cef92dcf88d4 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 9 Feb 2020 15:10:07 +0100 Subject: [PATCH 17/77] Refactor --- src/psm/Util/Server/Updater/StatusUpdater.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 635dcd02..41f9aea3 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -367,9 +367,9 @@ class StatusUpdater } // Check ssl cert just when other error is not already in... - if ($result !== false) { - $this->checkSsl($this->server, $this->error, $result); - } + if ($result !== false) { + $this->checkSsl($this->server, $this->error, $result); + } // check if server is available and rerun if asked. if (!$result && $run < $max_runs) { From ed6ef89df5a9f07f3119f4c2565bbcc995ece53f Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 9 Feb 2020 15:15:13 +0100 Subject: [PATCH 18/77] Hotfix - sslCheck warning days Minimum amount of days the ssl cert needs to be valid before expiration wasn't used. --- src/psm/Util/Server/Updater/StatusUpdater.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 41f9aea3..22bcab59 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -415,14 +415,21 @@ class StatusUpdater $server['ssl_cert_expiry_days'] > 0 ) { $cert_expiration_date = strtotime($this->curl_info['certinfo'][0]['Expire date']); - $expiration_time = round((int)($cert_expiration_date - time()) / 86400); + $expiration_time = + round((int)($cert_expiration_date - time()) / 86400); $latest_time = time() + (86400 * $server['ssl_cert_expiry_days']); - if ($expiration_time >= 0) { + + if ($expiration_time - $server['ssl_cert_expiry_days'] < 0) { + // Cert is not expired, but date is withing user set range $this->header = psm_get_lang('servers', 'ssl_cert_expiring') . " " . psm_date($this->curl_info['certinfo'][0]['Expire date']) . "\n\n" . $this->header; + $save['ssl_cert_expired_time'] = $expiration_time - $server['ssl_cert_expiry_days']; + } elseif ($expiration_time >= 0) { + // Cert is not expired $save['ssl_cert_expired_time'] = null; } else { + // Cert is expired $error = psm_get_lang('servers', 'ssl_cert_expired') . " " . psm_timespan($cert_expiration_date) . ".\n\n" . $error; From 1d779760ceac1de7d9089e6ec9459ba9bc22af58 Mon Sep 17 00:00:00 2001 From: Michael <33117529+mtelgkamp@users.noreply.github.com> Date: Sun, 9 Feb 2020 15:40:45 +0100 Subject: [PATCH 19/77] Improve accessibility of cards and tableview (#851) To enable keyboard users to show server details the links are added as HTML `a` Tags not only for
  • {% endblock %} \ No newline at end of file From c6e53b9a6fc4fef01699048c7b335c6661e23335 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 9 Feb 2020 19:48:07 +0100 Subject: [PATCH 23/77] Added missing pushover and telegram description --- src/psm/Module/User/Controller/UserController.php | 1 - src/templates/default/module/config/config.tpl.html | 2 ++ src/templates/default/module/user/profile.tpl.html | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/psm/Module/User/Controller/UserController.php b/src/psm/Module/User/Controller/UserController.php index 496c0826..58247049 100644 --- a/src/psm/Module/User/Controller/UserController.php +++ b/src/psm/Module/User/Controller/UserController.php @@ -396,7 +396,6 @@ class UserController extends AbstractController 'label_pushover_device' => psm_get_lang('users', 'pushover_device'), 'label_pushover_device_description' => psm_get_lang('users', 'pushover_device_description'), 'label_telegram' => psm_get_lang('users', 'telegram'), - 'label_telegram_description' => psm_get_lang('users', 'telegram_description'), 'label_telegram_id' => psm_get_lang('users', 'telegram_chat_id'), 'label_telegram_id_description' => psm_get_lang('users', 'telegram_chat_id_description'), 'label_email' => psm_get_lang('users', 'email'), diff --git a/src/templates/default/module/config/config.tpl.html b/src/templates/default/module/config/config.tpl.html index 0c35ffc3..a5c4086c 100644 --- a/src/templates/default/module/config/config.tpl.html +++ b/src/templates/default/module/config/config.tpl.html @@ -129,6 +129,7 @@
    {{ label_settings_pushover }} +

    {{ label_pushover_description|raw }}

    {{ macro.input_checkbox("pushover_status", "pushover_status", label_pushover_status, pushover_status_checked) }} @@ -143,6 +144,7 @@
    {{ label_settings_telegram }} +

    {{ label_telegram_description|raw }}

    {{ macro.input_checkbox("telegram_status", "telegram_status[]", label_telegram_status, telegram_status_checked) }} diff --git a/src/templates/default/module/user/profile.tpl.html b/src/templates/default/module/user/profile.tpl.html index e1768b88..dbf9012e 100644 --- a/src/templates/default/module/user/profile.tpl.html +++ b/src/templates/default/module/user/profile.tpl.html @@ -21,7 +21,8 @@
    - {{ label_pushover }} + {{ label_pushover }} +

    {{ label_pushover_description|raw }}

    {{ macro.input_field("text", "pushover_key", null, "pushover_key", label_pushover_key, pushover_key, label_pushover_key, "255", "pushover_key_help", pushover_key_description) }} @@ -29,10 +30,11 @@
    - {{ label_telegram }} + {{ label_telegram }} +

    {{ label_telegram_description|raw }}

    {{ 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) }} From 7ca93c40a620d8d42f5c6e918bbee495e6b5ab39 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 9 Feb 2020 19:57:31 +0100 Subject: [PATCH 24/77] Hide port for ping Closes #859. --- src/psm/Module/Server/Controller/ServerController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index ab27dd68..4e9fa54f 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -114,6 +114,9 @@ class ServerController extends AbstractServerController $servers[$x]['ip'] = '' . $ip . ''; } + if ($servers[$x]['type'] == 'ping') { + $servers[$x]['port'] = ''; + } if (($servers[$x]['active'] == 'yes')) { $servers[$x]['active_title'] = psm_get_lang('servers', 'monitoring'); } else { From 39be47d5735defe4faf8a82899506f0c63e04de4 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 9 Feb 2020 20:19:08 +0100 Subject: [PATCH 25/77] Hide icon if it's globally disabled Closes #858. --- .../Module/Server/Controller/ServerController.php | 13 ++++++------- .../default/module/server/server/list.tpl.html | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 4e9fa54f..eeef0336 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -97,13 +97,6 @@ class ServerController extends AbstractServerController psm_get_lang('menu', 'server_update') ); - $icons = array( - 'email' => 'icon-envelope', - 'sms' => 'icon-mobile', - 'pushover' => 'icon-pushover', - 'telegram' => 'icon-telegram', - ); - $servers = $this->getServers(); $server_count = count($servers); @@ -126,6 +119,12 @@ class ServerController extends AbstractServerController $servers[$x] = $this->formatServer($servers[$x]); } $tpl_data['servers'] = $servers; + + $tpl_data['config']['email'] = psm_get_conf('email_status'); + $tpl_data['config']['sms'] = psm_get_conf('sms_status'); + $tpl_data['config']['pushover'] = psm_get_conf('pushover_status'); + $tpl_data['config']['telegram'] = psm_get_conf('telegram_status'); + return $this->twig->render('module/server/server/list.tpl.html', $tpl_data); } diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index 3a01ac82..70b6dfd7 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -50,19 +50,19 @@ {% else %} {% endif %} - {% if server.email|lower == 'yes'%} + {% if server.email|lower == 'yes' and config.email|lower%} {% endif %} - {% if server.sms|lower == 'yes'%} + {% if server.sms|lower == 'yes' and config.sms|lower%} {% endif %} - {% if server.pushover|lower == 'yes'%} + {% if server.pushover|lower == 'yes'and config.pushover|lower %} P {% endif %} - {% if server.telegram|lower == 'yes'%} + {% if server.telegram|lower == 'yes' and config.telegram|lower%} T From 098a552774fb4eaa4ed5c5950e8bbcdb35dbb4e2 Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 9 Feb 2020 20:29:38 +0100 Subject: [PATCH 26/77] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 5 +++-- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/ISSUE_TEMPLATE/question.md | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 19282003..3b079baa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -23,8 +23,9 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** - - Version [e.g. 3.3.5, develop] +**Version (please complete the following information):** + - Version [e.g. 3.3.5] + - PHP [e.g. 7.3] **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4a439c2d..eee253b6 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: "[Feature Request]" -labels: '' +labels: 'Type: Feature' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index c522ec69..d1b6afb8 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -2,7 +2,7 @@ name: Question about: Ask your questions title: "[Question] " -labels: '' +labels: 'Type: Question' assignees: '' --- From 02f8484b3bd0c6858c97d6a5fc1b9a2062893110 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Tue, 11 Feb 2020 20:07:59 +0100 Subject: [PATCH 27/77] Set sender's phone number to max 15 characters E.164 standard. Fixes #866. --- src/psm/Txtmsg/CMBulkSMS.php | 4 ++-- src/psm/Txtmsg/ClickSend.php | 2 +- src/psm/Txtmsg/FreeVoipDeal.php | 2 +- src/psm/Txtmsg/Mosms.php | 2 +- src/psm/Txtmsg/Octopush.php | 2 +- src/psm/Txtmsg/Smsglobal.php | 2 +- src/psm/Txtmsg/Smsit.php | 2 +- src/psm/Txtmsg/SolutionsInfini.php | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/psm/Txtmsg/CMBulkSMS.php b/src/psm/Txtmsg/CMBulkSMS.php index d0d3e0b1..a009d252 100644 --- a/src/psm/Txtmsg/CMBulkSMS.php +++ b/src/psm/Txtmsg/CMBulkSMS.php @@ -131,7 +131,7 @@ class CMBulkSMS extends Core ), 'msg' => array( array( - 'from' => substr($this->originator, 0, 11), + 'from' => substr($this->originator, 0, 15), 'to' => $recipients, 'body' => array( 'content' => $message @@ -172,7 +172,7 @@ class CMBulkSMS extends Core $msg = $xml->addChild('MSG'); // From - $msg->addChild('FROM', substr($this->originator, 0, 11)); + $msg->addChild('FROM', substr($this->originator, 0, 15)); // Recipients foreach ($this->recipients as $recipient) { diff --git a/src/psm/Txtmsg/ClickSend.php b/src/psm/Txtmsg/ClickSend.php index d0176ce7..b62261a0 100644 --- a/src/psm/Txtmsg/ClickSend.php +++ b/src/psm/Txtmsg/ClickSend.php @@ -64,7 +64,7 @@ class ClickSend extends Core foreach ($this->recipients as $recipient) { $data['messages'][] = array( 'source' => 'phpservermon', - 'from' => substr($this->originator, 0, 11), + 'from' => substr($this->originator, 0, 15), 'to' => $recipient, 'body' => $message, ); diff --git a/src/psm/Txtmsg/FreeVoipDeal.php b/src/psm/Txtmsg/FreeVoipDeal.php index 234e6bd0..7decf766 100644 --- a/src/psm/Txtmsg/FreeVoipDeal.php +++ b/src/psm/Txtmsg/FreeVoipDeal.php @@ -63,7 +63,7 @@ class FreeVoipDeal extends Core array( "username" => $this->username, "password" => $this->password, - "from" => substr($this->originator, 0, 11), + "from" => substr($this->originator, 0, 15), "to" => $recipient, "text" => $message, ) diff --git a/src/psm/Txtmsg/Mosms.php b/src/psm/Txtmsg/Mosms.php index 98381579..ffcf15d0 100644 --- a/src/psm/Txtmsg/Mosms.php +++ b/src/psm/Txtmsg/Mosms.php @@ -63,7 +63,7 @@ class Mosms extends Core array( "username" => $this->username, "password" => $this->password, - "customsender" => substr($this->originator, 0, 11), + "customsender" => substr($this->originator, 0, 15), "nr" => $recipient, "type" => "text", "data" => $message, diff --git a/src/psm/Txtmsg/Octopush.php b/src/psm/Txtmsg/Octopush.php index 4ce98de1..942f91b5 100644 --- a/src/psm/Txtmsg/Octopush.php +++ b/src/psm/Txtmsg/Octopush.php @@ -72,7 +72,7 @@ class Octopush extends Core "api_key" => $this->password, "sms_recipients" => $recipients, "sms_type" => $smsType, - "sms_sender" => substr($this->originator, 0, 11), + "sms_sender" => substr($this->originator, 0, 15), "sms_text" => $message, ) )); diff --git a/src/psm/Txtmsg/Smsglobal.php b/src/psm/Txtmsg/Smsglobal.php index 9947b05a..174fc0bb 100644 --- a/src/psm/Txtmsg/Smsglobal.php +++ b/src/psm/Txtmsg/Smsglobal.php @@ -58,7 +58,7 @@ class Smsglobal extends Core $recipients = join(',', $this->recipients); - $from = substr($this->originator, 0, 11); // Max 11 Characters + $from = substr($this->originator, 0, 15); // Max 15 Characters $message = substr(rawurlencode($message), 0, 153); $curl = curl_init(); diff --git a/src/psm/Txtmsg/Smsit.php b/src/psm/Txtmsg/Smsit.php index 964ff5eb..58e6a53b 100644 --- a/src/psm/Txtmsg/Smsit.php +++ b/src/psm/Txtmsg/Smsit.php @@ -64,7 +64,7 @@ class Smsit extends Core "apiKey" => $this->password, "mobile" => $recipient, "message" => urlencode($message), - "senderId" => substr($this->originator, 0, 11), + "senderId" => substr($this->originator, 0, 15), ) )); diff --git a/src/psm/Txtmsg/SolutionsInfini.php b/src/psm/Txtmsg/SolutionsInfini.php index a21d1479..bc1e8196 100644 --- a/src/psm/Txtmsg/SolutionsInfini.php +++ b/src/psm/Txtmsg/SolutionsInfini.php @@ -66,7 +66,7 @@ class SolutionsInfini extends Core "api_key" => $this->password, "method" => "sms", "to" => $recipients, - "sender" => substr($this->originator, 0, 11), + "sender" => substr($this->originator, 0, 15), "message" => $message, ) )); From be928f8241831c11d3282dbe7d22ae1f78083f91 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 15 Mar 2020 17:34:26 +0100 Subject: [PATCH 28/77] Fixed delete server dialog Fixes #873. --- src/templates/default/module/server/server/list.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index 70b6dfd7..f54920d0 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -81,7 +81,7 @@ {{ label_edit }} + data-modal-param="{{ server.label }}"> {{ label_delete }}
    From 951586d77deadb0513534edac6f2f0f1bd639210 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 15 Mar 2020 17:45:40 +0100 Subject: [PATCH 29/77] Misplaced user dropdown Fixes #867. --- src/templates/default/static/scss/style.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/templates/default/static/scss/style.scss b/src/templates/default/static/scss/style.scss index d5ecf7fb..6114ad76 100644 --- a/src/templates/default/static/scss/style.scss +++ b/src/templates/default/static/scss/style.scss @@ -179,4 +179,9 @@ table tr[visible='true'] { width: 95px; transform-origin: 100% 4px; transition: all 1s; +} + +.dropdown-menu.show { + left: inherit; + right: 0px; } \ No newline at end of file From 11b18507546b59233daef360051fd684b1967f35 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 15 Mar 2020 17:49:32 +0100 Subject: [PATCH 30/77] Updated style sheets --- src/templates/default/static/css/style.min.css | 2 +- src/templates/default/static/css/style.min.css.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/templates/default/static/css/style.min.css b/src/templates/default/static/css/style.min.css index 6df4bd03..5bc79370 100644 --- a/src/templates/default/static/css/style.min.css +++ b/src/templates/default/static/css/style.min.css @@ -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} +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} /*# sourceMappingURL=style.min.css.map */ \ No newline at end of file diff --git a/src/templates/default/static/css/style.min.css.map b/src/templates/default/static/css/style.min.css.map index 840e7613..e9d01194 100644 --- a/src/templates/default/static/css/style.min.css.map +++ b/src/templates/default/static/css/style.min.css.map @@ -1,6 +1,6 @@ { "version": 3, - "mappings": "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", + "mappings": "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", "sources": [ "../scss/style.scss" ], From 86bff4dbaebac2cb2f993e2d6c036fab3f230d1b Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 15 Mar 2020 21:12:27 +0100 Subject: [PATCH 31/77] Removed English translations --- src/lang/zh_CN.lang.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lang/zh_CN.lang.php b/src/lang/zh_CN.lang.php index a33c6664..c3350957 100644 --- a/src/lang/zh_CN.lang.php +++ b/src/lang/zh_CN.lang.php @@ -124,9 +124,6 @@ $sm_lang = array( 'sms' => '短信', 'pushover' => 'Pushover', 'no_logs' => '没有日志', - 'clear' => 'Clear log', - 'delete_title' => 'Delete log', - 'delete_message' => 'Are you sure you want to delete all logs?', ), 'servers' => array( 'server' => '业务', From ee16078884e661c87250b06e2d7e11aaa7352358 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 15 Mar 2020 21:34:27 +0100 Subject: [PATCH 32/77] Delete button on server edit Fixes #860. --- .../Server/Controller/ServerController.php | 11 ++++++++++ .../module/server/server/update.tpl.html | 20 +++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index eeef0336..04b867d8 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -135,6 +135,12 @@ class ServerController extends AbstractServerController { $back_to = isset($_GET['back_to']) ? $_GET['back_to'] : ''; + $modal = new \psm\Util\Module\Modal($this->twig, 'delete', \psm\Util\Module\Modal::MODAL_TYPE_DANGER); + $this->addModal($modal); + $modal->setTitle(psm_get_lang('servers', 'delete_title')); + $modal->setMessage(psm_get_lang('servers', 'delete_message')); + $modal->setOKButtonLabel(psm_get_lang('system', 'delete')); + $tpl_data = $this->getLabels(); $tpl_data['edit_server_id'] = $this->server_id; $tpl_data['url_save'] = psm_build_url(array( @@ -143,6 +149,11 @@ class ServerController extends AbstractServerController 'id' => $this->server_id, 'back_to' => $back_to, )); + $tpl_data['url_delete'] = psm_build_url(array( + 'mod' => 'server', + 'action' => 'delete', + 'id' => $this->server_id, + )); // depending on where the user came from, add the go back url: if ($back_to == 'view' && $this->server_id > 0) { diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index e5fb7fbf..c46e72a8 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -143,13 +143,25 @@ {{ macro.input_select_monitoring("telegram", "telegram", label_send_telegram, edit_telegram_selected, label_yes, label_no, warning_telegram, label_warning_telegram) }}
    - +
    {{ label_fieldset_permissions }} {{ macro.input_select_multiple("user_id", "user_id[]", label_permissions, label_search, users, label_please_select) }} - {{ macro.button_save(null, label_save) }} - {{ label_go_back }} -
    + +
    + {{ label_save }} + {{ macro.button_save(null, label_save) }} + {{ label_go_back }} +
    + {% if edit_server_id > 0 %} +
    + {{ label_delete }} + + {{ label_delete }} + +
    + {% endif %} {{ macro.input_csrf() }} From ec21df15550ec0977a915facbea94f6d94028e88 Mon Sep 17 00:00:00 2001 From: Rich B Date: Wed, 8 Apr 2020 13:20:15 +0200 Subject: [PATCH 33/77] Corrected grammar in Telegram activation message (#885) --- src/lang/en_US.lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index 9bf6cae6..1429f2cf 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -130,7 +130,7 @@ $sm_lang = array( this permission, Telegram doesn\'t allow us to send notifications to you.', 'telegram_bot_username_found' => 'The bot was found!

    This will open a chat - with the bot. Here you need to press start of type /start.', + with the bot. Here you need to press start or type /start.', 'telegram_bot_username_error_token' => '401 - Unauthorized. Please make sure that the API token is valid.', 'telegram_bot_error' => 'An error has occurred while activating Telegram notification: %s', 'delete_title' => 'Delete User', From a129d88167b54f2bda7ad679570914a8f2a558e3 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 8 Apr 2020 13:43:36 +0200 Subject: [PATCH 34/77] Disable web page preview for Telegram (#886) Resolves #883. --- src/includes/functions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 689fce0c..9f25e3a6 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -965,7 +965,7 @@ namespace { if (!empty($this->token) && !empty($this->user) && !empty($this->message)) { $this->url = 'https://api.telegram.org/bot' . urlencode($this->token) . '/sendMessage?chat_id=' . urlencode($this->user) . '&text=' . - urlencode($this->message) . '&parse_mode=HTML'; + urlencode($this->message) . '&parse_mode=HTML&disable_web_page_preview=True'; } return $this->sendurl(); } From 40dc6fe64a3bb0261281c02335aa8f7d7c53ed8a Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 19 Apr 2020 12:59:02 +0200 Subject: [PATCH 35/77] Added Paypal and bunq bunq is a dutch bank. --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 59012128..42242799 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: ["https://www.paypal.me/TimZandbergen99", "https://bunq.me/t"] From bd6510b18835220ed119a0c1dbfb667b4b242b8b Mon Sep 17 00:00:00 2001 From: mklemme1 Date: Sun, 19 Apr 2020 14:19:33 +0200 Subject: [PATCH 36/77] cron update over the web via secret key (#888) As an alternative to allowing cron by IP. Co-authored-by: Michael Klemme --- config.php.sample | 3 ++- cron/status.cron.php | 5 ++++- docs/install.rst | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/config.php.sample b/config.php.sample index 31d490d7..bf902aaa 100644 --- a/config.php.sample +++ b/config.php.sample @@ -5,4 +5,5 @@ define('PSM_DB_PASS', 'db_pass'); define('PSM_DB_NAME', 'db_name'); define('PSM_DB_HOST', 'localhost'); define('PSM_DB_PORT', '3306'); //3306 is the default port for MySQL. If no specfic port is used, leave it empty. -define('PSM_BASE_URL', ''); \ No newline at end of file +define('PSM_BASE_URL', ''); +define('PSM_WEBCRON_KEY', ''); diff --git a/cron/status.cron.php b/cron/status.cron.php index 249e8743..0151d202 100644 --- a/cron/status.cron.php +++ b/cron/status.cron.php @@ -44,7 +44,10 @@ namespace { $data = @unserialize(PSM_CRON_ALLOW); $allow = $data === false ? PSM_CRON_ALLOW : $data; - if (!in_array($_SERVER['REMOTE_ADDR'], $allow) && !in_array($_SERVER["HTTP_X_FORWARDED_FOR"], $allow)) { + if (!in_array($_SERVER['REMOTE_ADDR'], $allow) && !in_array($_SERVER["HTTP_X_FORWARDED_FOR"], $allow) + && ! (array_key_exists ("webcron_key", $_GET) && + $_GET["webcron_key"]==PSM_WEBCRON_KEY && (PSM_WEBCRON_KEY != "")) + ) { header('HTTP/1.0 403 Forbidden'); die(' diff --git a/docs/install.rst b/docs/install.rst index 56126553..66165614 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -146,6 +146,13 @@ In config.php add following line:: After that, you can hit the url http(s)://"yourmonitor.com"/cron/status.cron.php over the web from your allowed IP. +Alternatively, define a secret key to allow the update over the web: + +In config.php add following line:: + + define('PSM_WEBCRON_KEY', 'YOURKEY'); + +After that, you can hit the url http(s)://"yourmonitor.com"/cron/status.cron.php?webcron_key=YOURKEY . Troubleshooting +++++++++++++++ From 13589299589250b8166fc9a419897b80ecd65cc3 Mon Sep 17 00:00:00 2001 From: Michael <33117529+mtelgkamp@users.noreply.github.com> Date: Sun, 19 Apr 2020 14:30:13 +0200 Subject: [PATCH 37/77] Prevent loading main page if installed in subdirectory (fix #869) (#870) When installed in a subdirectory the service-worker should not load (and cache) /. --- service-worker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-worker.js b/service-worker.js index 3d0a4edb..e0758905 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,7 +1,7 @@ var dataCacheName = 'PSM-v1'; var cacheName = 'PSM-PWA-final-1'; var filesToCache = [ - '/', + '', 'index.php', 'src/templates/default/static/js/history.js', 'src/templates/default/static/js/scripts.js', From b346cd9c4d64183b4b201c32b60c4c7a05c2197d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Gomes=20da=20Silva=20Lisboa?= Date: Sun, 19 Apr 2020 09:41:29 -0300 Subject: [PATCH 38/77] Fixed fail to ping IPv6 #879 (#880) Fixes #879. --- .gitignore | 2 ++ src/psm/Util/Server/Updater/StatusUpdater.php | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7118155f..e1c85147 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ *.bak __MACOSX/ .DS_Store +.buildpath +.settings/ diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 22bcab59..6d6ff34b 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -180,7 +180,12 @@ class StatusUpdater } $result = null; // Execute ping - $txt = exec("ping -c " . $max_runs . " " . $this->server['ip'] . " 2>&1", $output); + $pingCommand = 'ping6'; + $serverIp = $this->server['ip']; + if (filter_var($serverIp,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false){ + $pingCommand = 'ping'; + } + $txt = exec($pingCommand . " -c " . $max_runs . " " . $serverIp . " 2>&1", $output); // Non-greedy match on filler $re1 = '.*?'; // Uninteresting: float @@ -192,7 +197,9 @@ class StatusUpdater 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; @@ -225,7 +232,11 @@ class StatusUpdater // save response time $starttime = microtime(true); - $fp = @fsockopen($this->server['ip'], $this->server['port'], $errno, $this->error, $timeout); + $serverIp = $this->server['ip']; + if (filter_var($serverIp,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false){ + $serverIp = "[$serverIp]"; + } + $fp = @fsockopen($serverIp, $this->server['port'], $errno, $this->error, $timeout); $status = ($fp === false) ? false : true; $this->rtime = (microtime(true) - $starttime); From af5334a0736dd7943100d612125f1c707d6a6b11 Mon Sep 17 00:00:00 2001 From: Petr Suchy Date: Sun, 19 Apr 2020 15:31:40 +0200 Subject: [PATCH 40/77] Jabber (XMPP) notifications (#852) Added Jabber/XMPP notifications. Closes #829. --- README.rst | 4 +- composer.json | 5 +- composer.lock | 75 ++++++++++++++++- docs/faq.rst | 13 +++ docs/intro.rst | 4 +- logs/.gitignore | 2 + src/includes/functions.inc.php | 54 ++++++++++++ src/includes/psmconfig.inc.php | 14 +++- src/lang/en_US.lang.php | 42 ++++++++++ .../Config/Controller/ConfigController.php | 56 +++++++++++-- .../Install/Controller/InstallController.php | 1 + .../Controller/AbstractServerController.php | 1 + .../Server/Controller/LogController.php | 3 +- .../Server/Controller/ServerController.php | 14 +++- .../User/Controller/ProfileController.php | 4 +- .../Module/User/Controller/UserController.php | 4 + src/psm/Util/Install/Installer.php | 65 ++++++++++----- src/psm/Util/Server/UpdateManager.php | 6 +- .../Util/Server/Updater/StatusNotifier.php | 83 ++++++++++++++++--- .../default/module/config/config.tpl.html | 27 +++++- .../module/server/server/list.tpl.html | 6 ++ .../module/server/server/update.tpl.html | 2 + .../module/server/server/view.tpl.html | 13 +++ .../default/module/user/profile.tpl.html | 8 +- .../default/module/user/user/update.tpl.html | 2 + 25 files changed, 456 insertions(+), 52 deletions(-) create mode 100644 logs/.gitignore diff --git a/README.rst b/README.rst index d0a633ee..e7472654 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ Features: --------- * Monitor services and websites (see below). -* Email, SMS, Pushover, Telegram notifications. +* Email, SMS, Pushover, Telegram and Jabber notifications. * View history graphs of uptime and latency. * User authentication with 2 levels (administrator and regular user). * Logs of connection errors, outgoing emails and text messages. @@ -39,7 +39,7 @@ There are two different ways to monitor a server: In both cases the script will return a "status offline", and will start sending out notifications. Each server has its own settings regarding notification. -You can choose for email, text message (SMS), Pushover.net and Telegram notifications. +You can choose for email, text message (SMS), Pushover.net, Telegram and Jabber notifications. The following SMS gateways are currently available: * Clickatell - diff --git a/composer.json b/composer.json index d09fb164..88c4658d 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "symfony/filesystem": "~3.4", "php-pushover/php-pushover": "dev-master", "paragonie/random_compat": "^2.0", - "twig/twig": "~1.35" + "twig/twig": "~1.35", + "jaxl/jaxl": "^3.1" }, "autoload": { "files": [ @@ -27,4 +28,4 @@ "psm\\": "src/psm/" } } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index f07bb924..1ffbcc76 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,81 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b2a2bd93aeb6abf9b4e1905aa7ea4217", + "content-hash": "f78e950e2dfef7debe88d7b64e2b4aec", "packages": [ + { + "name": "jaxl/jaxl", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/jaxl/JAXL.git", + "reference": "27aa43c4600b05809779428843d8d51db6ce6e0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jaxl/JAXL/zipball/27aa43c4600b05809779428843d8d51db6ce6e0d", + "reference": "27aa43c4600b05809779428843d8d51db6ce6e0d", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-openssl": "*", + "ext-pcre": "*", + "ext-sockets": "*", + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "^3.7.0", + "squizlabs/php_codesniffer": "*" + }, + "suggest": { + "ext-pcntl": "Interrupt JAXL with signals" + }, + "bin": [ + "jaxlctl" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/JAXL" + ], + "exclude-from-classmap": [ + "/tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Abhinavsingh", + "homepage": "https://abhinavsingh.com/" + } + ], + "description": "Jaxl - Async, Non-Blocking, Event based Networking Library in PHP.", + "homepage": "http://jaxl.readthedocs.org/en/latest/index.html", + "keywords": [ + "abhinavsingh", + "asynchronous", + "event loop", + "http", + "jabber", + "jaxl", + "non blocking", + "php", + "xmpp" + ], + "time": "2016-09-13T01:59:35+00:00" + }, { "name": "paragonie/random_compat", "version": "v2.0.18", diff --git a/docs/faq.rst b/docs/faq.rst index 0fdfb03c..529960da 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -151,3 +151,16 @@ What is the username of my bot? 1. Go to profile on the monitor. 2. Press activate. 3. A button will appear, this will direct you to your Telegram bot. + +How do I setup Jabber notifications from Google account? +------------------------ +A few steps are required to get Jabber notifications working for Google account. +You need to be an administrator for this part. + +1. Go into you Google Account Security settings (https://myaccount.google.com/security). +2. Check that you have two factor auth enabled. If not, activate it. +3. Add new app password - copy it. +4. Login to PhpServerMonitor dashboard > config > Jabber and use password from step 3 with your Google account in PhpServerMonitor jabber settings. +5. As host use `talk.google.com`. +6. As username use your whole Google account (for example `example@google.com`). +7. As port use `5223` (really, not typo error ...). diff --git a/docs/intro.rst b/docs/intro.rst index 40c66a4e..1ed2e397 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -15,7 +15,7 @@ Features ++++++++ * Monitor services and websites (see below). -* Email, SMS, Pushover and Telegram notifications. +* Email, SMS, Pushover, Telegram and Jabber notifications. * View history graphs of uptime and latency. * User authentication with 2 levels (administrator and regular user). * Logs of connection errors, outgoing emails and text messages. @@ -44,7 +44,7 @@ There are two different ways to monitor a server: Notifications ------------- Each server has its own settings regarding notification. -You can choose for email, text message (SMS), Pushover.net and Telegram notifications. +You can choose for email, text message (SMS), Pushover.net, Telegram and Jabber notifications. The following SMS gateways are currently available: * Clickatell - diff --git a/logs/.gitignore b/logs/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 9f25e3a6..8fb1c449 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -653,6 +653,60 @@ namespace { return $telegram; } + /** + * Send message via XMPP. + * + * @param string $host + * @param string $username + * @param string $password + * @param array $receivers + * @param string $message + * @param int|null $port + * @param string|null $domain + */ + function psm_jabber_send_message($host, $username, $password, $receivers, $message, $port = null, $domain = null) + { + $options = [ + 'jid' => $username, // incl. gmail.com + 'pass' => $password, + 'domain' => $domain, // gmail.com or null + 'host' => $host, // talk.google.com + 'port' => $port, // talk.google.com needs to have 5223 ... 5222 - CN problem - gmail.com vs talk.google.com + 'log_path' => __DIR__ . '/../../logs/jaxl.log', // own log + + // force tls + 'force_tls' => PSM_JABBER_FORCE_TLS, + // (required) perform X-OAUTH2 + 'auth_type' => PSM_JABBER_AUTH_TYPE, //'X-OAUTH2', // auth failure with this option :( so just PLAIN ... + + 'log_level' => PSM_JABBER_DEBUG_LEVEL + ]; + + try { + $client = new JAXL($options); + + // Add Callbacks + $client->add_cb('on_auth_success', function () use ($client, $receivers, $message) { + JAXLLogger::info('got on_auth_success cb'); + foreach ($receivers as $receiver) { + $client->send_chat_msg($receiver, $message); + } + $client->send_end_stream(); + }); + $client->add_cb('on_auth_failure', function ($reason) use ($client) { + $client->send_end_stream(); + JAXLLogger::info('got on_auth_failure cb with reason: ' . $reason); + }); + $client->add_cb('on_disconnect', function () use ($client) { + JAXLLogger::info('got on_disconnect cb'); + }); + + $client->start(); + } catch (Exception $ex) { + JAXLLogger::error('Exception: ' . $ex->getMessage()); + } + } + /** * Prepare a new SMS util. * diff --git a/src/includes/psmconfig.inc.php b/src/includes/psmconfig.inc.php index 5afcf2d7..01101143 100644 --- a/src/includes/psmconfig.inc.php +++ b/src/includes/psmconfig.inc.php @@ -30,7 +30,7 @@ /** * Current PSM version */ -define('PSM_VERSION', '3.4.6-beta.2'); +define('PSM_VERSION', '3.4.6-beta.3'); /** * URL to check for updates. Will not be checked if turned off on config page. @@ -130,3 +130,15 @@ if (!defined('PSM_MODULE_DEFAULT')) { */ define('PSM_MODULE_DEFAULT', 'server_status'); } + +if (defined('PSM_JABBER_FORCE_TLS') === false) { + define('PSM_JABBER_FORCE_TLS', true); +} +if (defined('PSM_JABBER_AUTH_TYPE') === false) { + // possible values: PLAIN, X-OAUTH2, DIGEST-MD5, CRAM-MD5, SCRAM-SHA-1, ANONYMOUS, EXTERNAL + define('PSM_JABBER_AUTH_TYPE', 'PLAIN'); // default just plain because of google for example :( +} +if (defined('PSM_JABBER_DEBUG_LEVEL') === false) { + // possible values: ERROR, WARNING, NOTICE, INFO, DEBUG + define('PSM_JABBER_DEBUG_LEVEL', JAXLLogger::WARNING); +} diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index 1429f2cf..3c461c14 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -133,6 +133,9 @@ $sm_lang = array( with the bot. Here you need to press start or type /start.', 'telegram_bot_username_error_token' => '401 - Unauthorized. Please make sure that the API token is valid.', 'telegram_bot_error' => 'An error has occurred while activating Telegram notification: %s', + 'jabber' => 'Jabber', + 'jabber_label' => 'Jabber', + 'jabber_description' => 'You Jabber account', 'delete_title' => 'Delete User', 'delete_message' => 'Are you sure you want to delete user \'%1\'?', 'deleted' => 'User deleted.', @@ -160,6 +163,7 @@ $sm_lang = array( 'sms' => 'SMS', 'pushover' => 'Pushover', 'telegram' => 'Telegram', + 'jabber' => 'Jabber', 'no_logs' => 'No logs', 'clear' => 'Clear log', 'delete_title' => 'Delete log', @@ -227,6 +231,8 @@ $sm_lang = array( 'send_pushover' => 'Send Pushover notification', 'telegram' => 'Telegram', 'send_telegram' => 'Send Telegram notification', + 'jabber' => 'Jabber', + 'send_jabber' => 'Send Jabber notification', 'users' => 'Users', 'delete_title' => 'Delete server', 'delete_message' => 'Are you sure you want to delete server \'%1\'?', @@ -262,6 +268,7 @@ $sm_lang = array( 'warning_notifications_disabled_email' => 'Email notifications are disabled.', 'warning_notifications_disabled_pushover' => 'Pushover notifications are disabled.', 'warning_notifications_disabled_telegram' => 'Telegram notifications are disabled.', + 'warning_notifications_disabled_jabber' => 'Jabber notifications are disabled.', 'error_server_no_match' => 'Server not found.', 'error_server_label_bad_length' => 'The label must be between 1 and 255 characters.', 'error_server_ip_bad_length' => 'The domain / IP must be between 1 and 255 characters.', @@ -316,6 +323,21 @@ $sm_lang = array( 'telegram_api_token_description' => 'Before you can use Telegram, you need to get a API token. Visit the documentation for help.', + 'jabber_status' => 'Allow sending Jabber (XMPP) messages', + 'jabber_description' => 'Visit the documentation for more info and an + install guide.', + 'jabber_host' => 'Host', + 'jabber_host_description' => 'Host of your Jabber account provider. For Google Account use talk.google.com.', + 'jabber_port' => 'Port', + 'jabber_port_description' => 'Port of your Jabber provider. Default 5222. For Google Account use 5223.', + 'jabber_username' => 'Username', + 'jabber_username_description' => 'For Google Account use incl. domain so for example example@google.com.', + 'jabber_domain' => 'Domain', + 'jabber_domain_description' => 'Domain of your Jabber provider. Left empty for Google Account.', + 'jabber_password' => 'Password', + 'jabber_password_description' => 'Fill only to set or change.', + 'jabber_check' => 'Check your Jabber account if message was received.', 'alert_type' => 'Select when you\'d like to be notified.', 'alert_type_description' => 'Status change: You will receive a notification when a server has a change in status. So from online -> offline or offline -> online.

    Offline: @@ -339,15 +361,18 @@ $sm_lang = array( 'log_sms' => 'Log text messages sent by the script', 'log_pushover' => 'Log pushover messages sent by the script', 'log_telegram' => 'Log Telegram messages sent by the script', + 'log_jabber' => 'Log Jabber messages sent by the script', 'updated' => 'The configuration has been updated.', 'tab_email' => 'Email', 'tab_sms' => 'SMS', 'tab_pushover' => 'Pushover', 'tab_telegram' => 'Telegram', + 'tab_jabber' => 'Jabber', 'settings_email' => 'Email settings', 'settings_sms' => 'Text message settings', 'settings_pushover' => 'Pushover settings', 'settings_telegram' => 'Telegram settings', + 'settings_jabber' => 'Jabber settings', 'settings_notification' => 'Notification settings', 'settings_log' => 'Log settings', 'settings_proxy' => 'Proxy settings', @@ -361,6 +386,7 @@ $sm_lang = array( 'test_pushover' => 'A Pushover notification will be sent to the user key/device 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.', 'send' => 'Send', 'test_subject' => 'Test', 'test_message' => 'Test message', @@ -379,6 +405,11 @@ $sm_lang = array( 'telegram_error_notoken' => 'Unable to send test notification: no Telegram API token found in the global configuration.', 'telegram_error_noid' => 'Unable to send test notification: no chat id found in your profile.', + 'jabber_sent' => 'Telegram notification sent', + 'jabber_error' => 'An error has occurred while sending the Telegram notification: %s', + 'jabber_error_noconfig' => 'Unable to send test notification: no Jabber account set in the global + configuration.', + 'jabber_error_noaccount' => 'Unable to send test notification: no Jabber account found in your profile.', 'log_retention_period' => 'Log retention period', 'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.', @@ -393,6 +424,8 @@ $sm_lang = array( 'off_pushover_message' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', 'off_telegram_message' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: + %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', + 'off_jabber_message' => 'Failed to connect to the following server:

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Error: %ERROR%
    Date: %DATE%', 'on_sms' => 'Server \'%LABEL%\' is RUNNING: ip=%IP%, port=%PORT%, it was down for %LAST_OFFLINE_DURATION%', 'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING', @@ -405,12 +438,17 @@ $sm_lang = array( %DATE%', 'on_telegram_message' => 'Server \'%LABEL%\' is running again, it was down for: %LAST_OFFLINE_DURATION%

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Date: + %DATE%', + 'on_jabber_message' => 'Server \'%LABEL%\' is running again, it was down for: + %LAST_OFFLINE_DURATION%

    Server: %LABEL%
    IP: %IP%
    Port: %PORT%
    Date: %DATE%', 'combi_off_email_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Error: %ERROR%
    • Date: %DATE%
    ', 'combi_off_pushover_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Error: %ERROR%
    • Date: %DATE%
    ', 'combi_off_telegram_message' => '- Server: %LABEL%
    - IP: %IP%
    - Port: %PORT%
    - Error: %ERROR%
    - + Date: %DATE%

    ', + 'combi_off_jabber_message' => '- Server: %LABEL%
    - IP: %IP%
    - Port: %PORT%
    - Error: %ERROR%
    - Date: %DATE%

    ', 'combi_on_email_message' => '
    • Server: %LABEL%
    • IP: %IP%
    • Port: %PORT%
    • Downtime: %LAST_OFFLINE_DURATION%
    • Date: %DATE%
    ', @@ -418,6 +456,8 @@ $sm_lang = array( %PORT%
  • Downtime: %LAST_OFFLINE_DURATION%
  • Date: %DATE%
  • ', 'combi_on_telegram_message' => '- Server: %LABEL%
    - IP: %IP%
    - Port: %PORT%
    - Downtime: + %LAST_OFFLINE_DURATION%
    - Date: %DATE%

    ', + 'combi_on_jabber_message' => '- Server: %LABEL%
    - IP: %IP%
    - Port: %PORT%
    - Downtime: %LAST_OFFLINE_DURATION%
    - Date: %DATE%

    ', 'combi_email_subject' => 'IMPORTANT: \'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', 'combi_pushover_subject' => '\'%UP%\' servers UP again, \'%DOWN%\' servers DOWN', @@ -426,6 +466,8 @@ $sm_lang = array( 'combi_pushover_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following servers are up again:
    %UP_SERVERS%', 'combi_telegram_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following + servers are up again:
    %UP_SERVERS%', + 'combi_jabber_message' => 'The following servers went down:
    %DOWN_SERVERS%
    The following servers are up again:
    %UP_SERVERS%', ), 'login' => array( diff --git a/src/psm/Module/Config/Controller/ConfigController.php b/src/psm/Module/Config/Controller/ConfigController.php index 0dd3f9b2..4c6a7e5d 100644 --- a/src/psm/Module/Config/Controller/ConfigController.php +++ b/src/psm/Module/Config/Controller/ConfigController.php @@ -45,11 +45,13 @@ class ConfigController extends AbstractController 'sms_status', 'pushover_status', 'telegram_status', + 'jabber_status', 'log_status', 'log_email', 'log_sms', 'log_pushover', 'log_telegram', + 'log_jabber', 'show_update', 'combine_notifications', ); @@ -72,6 +74,10 @@ class ConfigController extends AbstractController 'sms_from', 'pushover_api_token', 'telegram_api_token', + 'jabber_host', + 'jabber_port', + 'jabber_username', + 'jabber_domain' ); /** @@ -79,7 +85,8 @@ class ConfigController extends AbstractController * @var array */ protected $encryptedFields = [ - 'email_smtp_password' + 'email_smtp_password', + 'jabber_password' ]; private $default_tab = 'general'; @@ -191,7 +198,7 @@ class ConfigController extends AbstractController $tpl_data[$this->default_tab . '_active'] = 'active'; - $testmodals = array('email', 'sms', 'pushover', 'telegram'); + $testmodals = array('email', 'sms', 'pushover', 'telegram', 'jabber'); foreach ($testmodals as $modal_id) { $modal = new \psm\Util\Module\Modal( $this->twig, @@ -214,7 +221,7 @@ class ConfigController extends AbstractController protected function executeSave() { if (!empty($_POST)) { - // save new config + // save new config $clean = array( 'language' => $_POST['language'], 'sms_gateway' => $_POST['sms_gateway'], @@ -225,9 +232,9 @@ class ConfigController extends AbstractController : '', 'auto_refresh_servers' => intval(psm_POST('auto_refresh_servers', 0)), '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'; } foreach ($this->fields as $input_key) { @@ -256,6 +263,8 @@ class ConfigController extends AbstractController $this->testPushover(); } elseif (!empty($_POST['test_telegram'])) { $this->testTelegram(); + } elseif (!empty($_POST['test_jabber'])) { + $this->testJabber(); } if ($language_refresh) { @@ -273,6 +282,8 @@ class ConfigController extends AbstractController $this->default_tab = 'pushover'; } elseif (isset($_POST['telegram_submit']) || !empty($_POST['test_telegram'])) { $this->default_tab = 'telegram'; + } elseif (isset($_POST['jabber_submit']) || !empty($_POST['test_jabber'])) { + $this->default_tab = 'jabber'; } } return $this->runAction('index'); @@ -397,6 +408,26 @@ class ConfigController extends AbstractController } } + /** + * Test Jabber. + */ + protected function testJabber() + { + $user = $this->getUser()->getUser(); + psm_jabber_send_message( + psm_get_conf('jabber_host'), + psm_get_conf('jabber_username'), + psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), + [$user->jabber], + psm_get_lang('config', 'test_message'), + (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) + ); + // no message - async ... so just info + $this->addMessage(psm_get_lang('config', 'jabber_check'), 'info'); + // @todo possible to set message via ajax with callback ... + } + protected function getLabels() { return array( @@ -404,10 +435,12 @@ class ConfigController extends AbstractController 'label_tab_sms' => psm_get_lang('config', 'tab_sms'), 'label_tab_pushover' => psm_get_lang('config', 'tab_pushover'), 'label_tab_telegram' => psm_get_lang('config', 'tab_telegram'), + 'label_tab_jabber' => psm_get_lang('config', 'tab_jabber'), 'label_settings_email' => psm_get_lang('config', 'settings_email'), 'label_settings_sms' => psm_get_lang('config', 'settings_sms'), 'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'), 'label_settings_telegram' => psm_get_lang('config', 'settings_telegram'), + 'label_settings_jabber' => psm_get_lang('config', 'settings_jabber'), 'label_settings_notification' => psm_get_lang('config', 'settings_notification'), 'label_settings_log' => psm_get_lang('config', 'settings_log'), 'label_settings_proxy' => psm_get_lang('config', 'settings_proxy'), @@ -448,6 +481,18 @@ class ConfigController extends AbstractController 'label_telegram_status' => psm_get_lang('config', 'telegram_status'), '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_jabber_status' => psm_get_lang('config', 'jabber_status'), + 'label_jabber_description' => psm_get_lang('config', 'jabber_description'), + 'label_jabber_host' => psm_get_lang('config', 'jabber_host'), + 'label_jabber_host_description' => psm_get_lang('config', 'jabber_host_description'), + 'label_jabber_port' => psm_get_lang('config', 'jabber_port'), + 'label_jabber_port_description' => psm_get_lang('config', 'jabber_port_description'), + 'label_jabber_username' => psm_get_lang('config', 'jabber_username'), + 'label_jabber_username_description' => psm_get_lang('config', 'jabber_username_description'), + 'label_jabber_domain' => psm_get_lang('config', 'jabber_domain'), + 'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'), + 'label_jabber_password' => psm_get_lang('config', 'jabber_password'), + 'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'), 'label_alert_type' => psm_get_lang('config', 'alert_type'), 'label_alert_type_description' => psm_get_lang('config', 'alert_type_description'), 'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'), @@ -458,6 +503,7 @@ class ConfigController extends AbstractController 'label_log_sms' => psm_get_lang('config', 'log_sms'), 'label_log_pushover' => psm_get_lang('config', 'log_pushover'), 'label_log_telegram' => psm_get_lang('config', 'log_telegram'), + 'label_log_jabber' => psm_get_lang('config', 'log_jabber'), 'label_alert_proxy' => psm_get_lang('config', 'alert_proxy'), 'label_alert_proxy_url' => psm_get_lang('config', 'alert_proxy_url'), 'label_auto_refresh' => psm_get_lang('config', 'auto_refresh'), diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index 3a4ee208..4dc7aa1d 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -257,6 +257,7 @@ class InstallController extends AbstractController 'pushover_key' => '', 'pushover_device' => '', 'telegram_id' => '', + 'jabber' => '' ); $validator = $this->container->get('util.user.validator'); diff --git a/src/psm/Module/Server/Controller/AbstractServerController.php b/src/psm/Module/Server/Controller/AbstractServerController.php index efc70072..befad354 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.php @@ -83,6 +83,7 @@ abstract class AbstractServerController extends AbstractController `s`.`sms`, `s`.`pushover`, `s`.`telegram`, + `s`.`jabber`, `s`.`warning_threshold`, `s`.`warning_threshold_counter`, `s`.`ssl_cert_expiry_days`, diff --git a/src/psm/Module/Server/Controller/LogController.php b/src/psm/Module/Server/Controller/LogController.php index b84ac85d..72685baf 100644 --- a/src/psm/Module/Server/Controller/LogController.php +++ b/src/psm/Module/Server/Controller/LogController.php @@ -57,6 +57,7 @@ class LogController extends AbstractServerController 'label_sms' => psm_get_lang('log', 'sms'), 'label_pushover' => psm_get_lang('log', 'pushover'), 'label_telegram' => psm_get_lang('log', 'telegram'), + 'label_jabber' => psm_get_lang('log', 'jabber'), 'label_title' => psm_get_lang('log', 'title'), 'label_server' => psm_get_lang('servers', 'server'), 'label_type' => psm_get_lang('log', 'type'), @@ -88,7 +89,7 @@ class LogController extends AbstractServerController ); } - $log_types = array('status', 'email', 'sms', 'pushover', 'telegram'); + $log_types = array('status', 'email', 'sms', 'pushover', 'telegram', 'jabber'); foreach ($log_types as $key) { $records = $this->getEntries($key); diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 04b867d8..16f0860d 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -97,6 +97,14 @@ class ServerController extends AbstractServerController psm_get_lang('menu', 'server_update') ); + $icons = array( + 'email' => 'icon-envelope', + 'sms' => 'icon-mobile', + 'pushover' => 'icon-pushover', + 'telegram' => 'icon-telegram', + 'jabber' => 'icon-jabber' + ); + $servers = $this->getServers(); $server_count = count($servers); @@ -228,10 +236,11 @@ class ServerController extends AbstractServerController 'edit_sms_selected' => $edit_server['sms'], 'edit_pushover_selected' => $edit_server['pushover'], 'edit_telegram_selected' => $edit_server['telegram'], + 'edit_jabber_selected' => $edit_server['jabber'], )); } - $notifications = array('email', 'sms', 'pushover', 'telegram'); + $notifications = array('email', 'sms', 'pushover', 'telegram', 'jabber'); foreach ($notifications as $notification) { if (psm_get_conf($notification . '_status') == 0) { $tpl_data['warning_' . $notification] = true; @@ -301,6 +310,7 @@ class ServerController extends AbstractServerController 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', 'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : 'no', 'telegram' => in_array($_POST['telegram'], array('yes', 'no')) ? $_POST['telegram'] : 'no', + 'jabber' => in_array($_POST['jabber'], array('yes', 'no')) ? $_POST['jabber'] : 'no', ); // make sure websites start with http:// if ( @@ -569,8 +579,10 @@ class ServerController extends AbstractServerController 'label_send_sms' => psm_get_lang('servers', 'send_sms'), 'label_send_pushover' => psm_get_lang('servers', 'send_pushover'), 'label_telegram' => psm_get_lang('servers', 'telegram'), + 'label_jabber' => psm_get_lang('servers', 'jabber'), 'label_pushover' => psm_get_lang('servers', 'pushover'), 'label_send_telegram' => psm_get_lang('servers', 'send_telegram'), + 'label_send_jabber' => psm_get_lang('servers', 'send_jabber'), 'label_users' => psm_get_lang('servers', 'users'), 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), diff --git a/src/psm/Module/User/Controller/ProfileController.php b/src/psm/Module/User/Controller/ProfileController.php index bcd04c0f..09f88691 100644 --- a/src/psm/Module/User/Controller/ProfileController.php +++ b/src/psm/Module/User/Controller/ProfileController.php @@ -39,7 +39,7 @@ class ProfileController extends AbstractController * @var array $profile_fields */ protected $profile_fields = - array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id'); + array('name', 'user_name', 'email', 'mobile', 'pushover_key', 'pushover_device', 'telegram_id', 'jabber'); public function __construct(Database $db, \Twig_Environment $twig) { @@ -90,6 +90,8 @@ class ProfileController extends AbstractController 'label_activate_telegram' => psm_get_lang('users', 'activate_telegram'), 'label_telegram_get_chat_id' => psm_get_lang('users', 'telegram_get_chat_id'), 'telegram_get_chat_id_url' => PSM_TELEGRAM_GET_ID_URL, + 'label_jabber' => psm_get_lang('users', 'jabber'), + 'label_jabber_description' => psm_get_lang('users', 'jabber_description'), 'label_email' => psm_get_lang('users', 'email'), 'label_save' => psm_get_lang('system', 'save'), 'form_action' => psm_build_url(array( diff --git a/src/psm/Module/User/Controller/UserController.php b/src/psm/Module/User/Controller/UserController.php index 58247049..1104a4d0 100644 --- a/src/psm/Module/User/Controller/UserController.php +++ b/src/psm/Module/User/Controller/UserController.php @@ -161,6 +161,7 @@ class UserController extends AbstractController 'pushover_key', 'pushover_device', 'telegram_id', + 'jabber', 'email' ); @@ -257,6 +258,7 @@ class UserController extends AbstractController 'pushover_key', 'pushover_device', 'telegram_id', + 'jabber', 'email' ); $clean = array(); @@ -398,6 +400,8 @@ class UserController extends AbstractController 'label_telegram' => psm_get_lang('users', 'telegram'), 'label_telegram_id' => psm_get_lang('users', 'telegram_chat_id'), 'label_telegram_id_description' => psm_get_lang('users', 'telegram_chat_id_description'), + 'label_jabber' => psm_get_lang('users', 'jabber'), + 'label_jabber_description' => psm_get_lang('users', 'jabber_description'), 'label_email' => psm_get_lang('users', 'email'), 'label_servers' => psm_get_lang('menu', 'server'), 'label_save' => psm_get_lang('system', 'save'), diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 78e93ae3..573c9ed1 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -134,11 +134,11 @@ class Installer $queries = array(); $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` ( `ip`, `port`, `label`, `type`, `pattern`, `pattern_online`, `redirect_check`, - `status`, `rtime`, `active`, `email`, `sms`, `pushover`, `telegram`) + `status`, `rtime`, `active`, `email`, `sms`, `pushover`, `telegram`, `jabber`) VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', '', - 'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes'), + 'yes', 'bad', 'on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes'), ('smtp.gmail.com', 465, 'Gmail SMTP', 'service', '', - 'yes', 'bad','on', '0.0000000', 'yes', 'yes', 'yes', 'yes', 'yes')"; + 'yes', 'bad','on', '0.0000000', '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 . "config` (`key`, `value`) VALUE ('language', 'en_US'), @@ -164,6 +164,12 @@ class Installer ('pushover_api_token', ''), ('telegram_status', '0'), ('telegram_api_token', ''), + ('jabber_status', '1'), + ('jabber_host', ''), + ('jabber_port', ''), + ('jabber_username', ''), + ('jabber_domain', ''), + ('jabber_password', ''), ('password_encrypt_key', '" . sha1(microtime()) . "'), ('alert_type', 'status'), ('log_status', '1'), @@ -171,6 +177,7 @@ class Installer ('log_sms', '1'), ('log_pushover', '1'), ('log_telegram', '1'), + ('log_jabber', '1'), ('log_retention_period', '365'), ('version', '" . PSM_VERSION . "'), ('version_update_check', '" . PSM_VERSION . "'), @@ -208,6 +215,7 @@ class Installer `pushover_key` varchar(255) NOT NULL, `pushover_device` varchar(255) NOT NULL, `telegram_id` varchar(255) NOT NULL, + `jabber` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, PRIMARY KEY (`user_id`), UNIQUE KEY `unique_username` (`user_name`) @@ -227,7 +235,7 @@ class Installer PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` ( `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `server_id` int(11) unsigned NOT NULL, - `type` enum('status','email','sms','pushover','telegram') NOT NULL, + `type` enum('status','email','sms','pushover','telegram', 'jabber') NOT NULL, `message` TEXT NOT NULL, `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`log_id`) @@ -263,6 +271,7 @@ class Installer `sms` enum('yes','no') NOT NULL default 'no', `pushover` enum('yes','no') NOT NULL default 'yes', `telegram` 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_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', `ssl_cert_expiry_days` mediumint(1) unsigned NOT NULL DEFAULT '0', @@ -345,10 +354,7 @@ class Installer if (version_compare($version_from, '3.4.2', '<')) { $this->upgrade342(); } - if (version_compare($version_from, '3.4.6-beta.1', '<')) { - $this->upgrade346(); - } - if (version_compare($version_from, '3.4.6-beta.2', '<')) { + if (version_compare($version_from, '3.4.6-beta.3', '<')) { $this->upgrade346(); } psm_update_conf('version', $version_to); @@ -676,20 +682,37 @@ class Installer ADD `ssl_cert_expiry_days` MEDIUMINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `warning_threshold_counter`"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `ssl_cert_expired_time` VARCHAR(255) NULL AFTER `ssl_cert_expiry_days`"; - - if ( - @psm_password_decrypt( - psm_get_conf('password_encrypt_key'), - psm_get_conf('email_smtp_password') - ) === false - ) { - // Prevents encrypting the password multiple times. - $queries[] = "UPDATE `" . PSM_DB_PREFIX . "config` + + if ( + @psm_password_decrypt( + psm_get_conf('password_encrypt_key'), + psm_get_conf('email_smtp_password') + ) === false + ) { + // Prevents encrypting the password multiple times. + $queries[] = "UPDATE `" . PSM_DB_PREFIX . "config` SET `value` = '" . - psm_password_encrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('email_smtp_password')) . - "' WHERE `key` = 'email_smtp_password'"; - $this->log('SMTP password is now encrypted.'); - } + psm_password_encrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('email_smtp_password')) . + "' WHERE `key` = 'email_smtp_password'"; + $this->log('SMTP password is now encrypted.'); + } + + $queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users` ADD `jabber` VARCHAR( 255 ) + NOT NULL AFTER `telegram_id`;'; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `jabber` ENUM( 'yes','no' ) + NOT NULL DEFAULT 'yes' AFTER `telegram`;"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . + "log` CHANGE `type` `type` ENUM( 'status', 'email', 'sms', 'pushover', 'telegram', 'jabber' ) + CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;"; + $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE + ('jabber_status', '0'), + ('log_jabber', '1'), + ('jabber_host', ''), + ('jabber_port', ''), + ('jabber_username', ''), + ('jabber_domain', ''), + ('jabber_password', '');"; + $this->execSQL($queries); } } diff --git a/src/psm/Util/Server/UpdateManager.php b/src/psm/Util/Server/UpdateManager.php index 92b37bad..2e3ee42c 100644 --- a/src/psm/Util/Server/UpdateManager.php +++ b/src/psm/Util/Server/UpdateManager.php @@ -69,7 +69,8 @@ class UpdateManager implements ContainerAwareInterface } $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`.`telegram`, + `s`.`jabber` FROM `" . PSM_DB_PREFIX . "servers` AS `s` {$sql_join} WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : ''); @@ -81,7 +82,8 @@ class UpdateManager implements ContainerAwareInterface foreach ($servers as $server) { $status_old = ($server['status'] == 'on') ? true : false; - $status_new = $updater->update($server['server_id']); + $status_new = $updater-> + update($server['server_id']); // notify the nerds if applicable $notifier->notify($server['server_id'], $status_old, $status_new); // clean-up time!! archive all records diff --git a/src/psm/Util/Server/Updater/StatusNotifier.php b/src/psm/Util/Server/Updater/StatusNotifier.php index 1e798742..5b0672a6 100644 --- a/src/psm/Util/Server/Updater/StatusNotifier.php +++ b/src/psm/Util/Server/Updater/StatusNotifier.php @@ -33,6 +33,7 @@ * @see \psm\Util\Server\Updater\Autorun */ namespace psm\Util\Server\Updater; +use Norgul\Xmpp\Options; use psm\Service\Database; class StatusNotifier @@ -68,6 +69,12 @@ class StatusNotifier */ protected $send_telegram = false; + /** + * Send Jabber? + * @var bool + */ + protected $send_jabber = false; + /** * Save log records? * @var boolean $save_log @@ -119,12 +126,13 @@ class StatusNotifier { $this->db = $db; - $this->send_emails = psm_get_conf('email_status'); - $this->send_sms = psm_get_conf('sms_status'); - $this->send_pushover = psm_get_conf('pushover_status'); - $this->send_telegram = psm_get_conf('telegram_status'); - $this->save_logs = psm_get_conf('log_status'); - $this->combine = psm_get_conf('combine_notifications'); + $this->send_emails = (bool)psm_get_conf('email_status'); + $this->send_sms = (bool)psm_get_conf('sms_status'); + $this->send_pushover = (bool)psm_get_conf('pushover_status'); + $this->send_telegram = (bool)psm_get_conf('telegram_status'); + $this->send_jabber = (bool)psm_get_conf('jabber_status'); + $this->save_logs = (bool)psm_get_conf('log_status'); + $this->combine = (bool)psm_get_conf('combine_notifications'); } /** @@ -143,6 +151,7 @@ class StatusNotifier !$this->send_sms && !$this->send_pushover && !$this->send_telegram && + !$this->send_jabber && !$this->save_logs ) { // seems like we have nothing to do. skip the rest @@ -168,6 +177,7 @@ class StatusNotifier 'sms', 'pushover', 'telegram', + 'jabber', 'last_online', 'last_offline', 'last_offline_duration', @@ -247,6 +257,10 @@ class StatusNotifier $this->combine ? $this->setCombi('telegram') : $this->notifyByTelegram($users); } + if ($this->send_jabber && $this->server['jaber'] == 'yes') { + $this->combine ? $this->setCombi('jabber') : $this->notifyByJabber($users); + } + return $notify; } @@ -548,6 +562,54 @@ class StatusNotifier } } + /** + * @param array $users + * @param array $combi + */ + protected function notifyByJabber($users, $combi = []) + { + // Remove users that have no jabber + foreach ($users as $k => $user) { + if (trim($user['jabber']) === '') { + unset($users[$k]); + } + } + + // Validation + if (empty($users)) { + return; + } + + // Message + $message = key_exists('message', $combi) ? + $combi['message'] : + psm_parse_msg($this->status_new, 'jabber_message', $this->server); + + // Log + if (psm_get_conf('log_jabber')) { + $log_id = psm_add_log($this->server_id, 'jabber', $message); + } + + $usersJabber = []; + foreach ($users as $user) { + // Log + if (!empty($log_id)) { + psm_add_log_user($log_id, $user['user_id']); + } + $usersJabber[] = $user['jabber']; + } + // Jabber + psm_jabber_send_message( + psm_get_conf('jabber_host'), + psm_get_conf('jabber_username'), + psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), + $usersJabber, + $message, + (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) + ); + } + /** * Get all users for the provided server id * @param int $server_id @@ -556,11 +618,12 @@ class StatusNotifier public function getUsers($server_id) { // 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`, - `u`.`pushover_device`, `u`.`telegram_id` - FROM `" . PSM_DB_PREFIX . "users` AS `u` - JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON ( + `u`.`pushover_device`, `u`.`telegram_id`, + `u`.`jabber` + FROM `' . PSM_DB_PREFIX . 'users` AS `u` + JOIN `' . PSM_DB_PREFIX . "users_servers` AS `us` ON ( `us`.`user_id`=`u`.`user_id` AND `us`.`server_id` = {$server_id} ) diff --git a/src/templates/default/module/config/config.tpl.html b/src/templates/default/module/config/config.tpl.html index a5c4086c..3f7064e5 100644 --- a/src/templates/default/module/config/config.tpl.html +++ b/src/templates/default/module/config/config.tpl.html @@ -27,6 +27,11 @@ role="tab" aria-controls="config-telegram" aria-selected="{% if telegram_active %}true{% else %}false{% endif %}">{{ label_tab_telegram }} +
    @@ -126,7 +131,7 @@ {{ macro.button_save("sms_submit", label_save) }}
    -
    +
    {{ label_settings_pushover }}

    {{ label_pushover_description|raw }}

    @@ -141,7 +146,7 @@ {{ macro.button_save("pushover_submit", label_save) }}
    -
    +
    {{ label_settings_telegram }}

    {{ label_telegram_description|raw }}

    @@ -156,6 +161,24 @@ {{ macro.button_save("telegram_submit", label_save) }}
    +
    +
    + {{ label_settings_jabber }} + + {{ macro.input_checkbox("jabber_status", "jabber_status[]", label_jabber_status, jabber_status_checked) }} + + {{ macro.input_checkbox("log_jabber", "log_jabber[]", label_log_jabber, log_jabber_checked) }} + + {{ macro.input_field("text", "jabber_host", null, "jabber_host", label_jabber_host, jabber_host, label_jabber_host, "255", "jabber_host_help", label_jabber_host_description) }} + {{ macro.input_field("number", "jabber_port", null, "jabber_port", label_jabber_port, jabber_port, label_jabber_port, "255", "jabber_port_help", label_jabber_port_description) }} + {{ macro.input_field("text", "jabber_username", null, "jabber_username", label_jabber_username, jabber_username, label_jabber_username, "255", 'jabber_username_help', label_jabber_username_description) }} + {{ macro.input_field("text", "jabber_domain", null, "jabber_domain", label_jabber_domain, jabber_domain, label_jabber_domain, "255", "jabber_domain_help", label_jabber_domain_description) }} + {{ macro.input_field("password", "jabber_password", null, "jabber_password", label_jabber_password, jabber_password, label_jabber_password, "255", "jabber_password_help", label_jabber_password_description) }} + {{ macro.button_test("testJabber", label_test) }} + {{ macro.input_hidden("test_jabber", "0") }} + {{ macro.button_save("jabber_submit", label_save) }} +
    +
    {{ macro.input_csrf() }} diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index f54920d0..110c1261 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -68,6 +68,12 @@ T {% endif %} + {% if server.jabber|lower == 'yes'%} + + + J + + {% endif %} {% if user_level == 10 %} diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index c46e72a8..38292434 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -142,6 +142,8 @@ {{ macro.input_select_monitoring("pushover", "pushover", label_send_pushover, edit_pushover_selected, label_yes, label_no, warning_pushover, label_warning_pushover) }} {{ 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("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }}
    diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index 05b9c984..ba6be918 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -331,6 +331,19 @@ {% endif %} +
  • + {{ label_jabber }}: + {% if jabber|lower == 'yes' %} + + + {% elseif jabber|lower == 'no' %} + + + {% else %} + + + {% endif %} +
  • diff --git a/src/templates/default/module/user/profile.tpl.html b/src/templates/default/module/user/profile.tpl.html index dbf9012e..93caa951 100644 --- a/src/templates/default/module/user/profile.tpl.html +++ b/src/templates/default/module/user/profile.tpl.html @@ -39,6 +39,12 @@ {{ 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_hidden("activate_telegram", "0") }} - {{ macro.button_save(null, label_save) }}
    + +
    + {{ label_jabber }} + + {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", jabber_description) }} +
    + {{ macro.button_save(null, label_save) }} \ No newline at end of file diff --git a/src/templates/default/module/user/user/update.tpl.html b/src/templates/default/module/user/user/update.tpl.html index 79661850..0e86d617 100644 --- a/src/templates/default/module/user/user/update.tpl.html +++ b/src/templates/default/module/user/user/update.tpl.html @@ -23,6 +23,8 @@ {{ macro.input_field("text", "pushover_device", null, "pushover_device", label_pushover_device, edit_value_pushover_device, null, "255") }} {{ macro.input_field("text", "telegram_id", null, "telegram_id", label_telegram_id, edit_value_telegram_id, null, "255") }} + + {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, edit_value_jabber, null, "255") }} {{ macro.input_select_multiple("server_id", "server_id[]", label_servers, label_search, servers, label_please_select) }} From 7968e876c4d7dc22cf2b27808ebb12e1fd464669 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Wed, 22 Apr 2020 15:53:42 +0200 Subject: [PATCH 41/77] Fixed doc --- docs/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.rst b/docs/faq.rst index 529960da..19a0db2b 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -153,7 +153,7 @@ What is the username of my bot? 3. A button will appear, this will direct you to your Telegram bot. How do I setup Jabber notifications from Google account? ------------------------- +-------------------------------------------------------- A few steps are required to get Jabber notifications working for Google account. You need to be an administrator for this part. From 58d73bda37067a2a3c88f484d9d558b9eb756f74 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Wed, 22 Apr 2020 15:57:56 +0200 Subject: [PATCH 42/77] Bumped version --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 266839e9..88485fa6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,9 +51,9 @@ copyright = u'2008-2017, Pepijn Over' # built documents. # # The short X.Y version. -version = '3.4.5' +version = '3.4.6' # The full version, including alpha/beta/rc tags. -release = version +release = '3.4.6-beta.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 6c5665d0cd616c8c0b686a48de23ce3172148d20 Mon Sep 17 00:00:00 2001 From: imsoftware Date: Wed, 22 Apr 2020 16:05:46 +0200 Subject: [PATCH 43/77] Added link to server at single view template (#890) --- src/templates/default/module/server/server/view.tpl.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index ba6be918..20218480 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -27,7 +27,11 @@
  • {{ label_domain }}:
    -
    {{ ip|raw }}
    +
    + + {{ ip|raw }} + +
  • {% if type|lower == 'service' %} From 02c746ae41ddf417bee165d65a70fdcbb4379f43 Mon Sep 17 00:00:00 2001 From: imsoftware Date: Fri, 1 May 2020 01:17:48 +0200 Subject: [PATCH 44/77] Set php5 support to 5.6+ (#891) See bug report for php 5.5.9: https://github.com/phpservermon/phpservermon/issues/889 Fixes #889. Co-authored-by: Tim --- README.rst | 2 +- docs/requirements.rst | 2 +- src/psm/Module/Install/Controller/InstallController.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index e7472654..7204806a 100644 --- a/README.rst +++ b/README.rst @@ -77,7 +77,7 @@ Requirements * Web server * MySQL database -* For PHP5: 5.5.9+ +* For PHP5: 5.6.0+ * For PHP7: 7.0.8+ * PHP cURL package * PHP PDO mysql driver diff --git a/docs/requirements.rst b/docs/requirements.rst index 636dde40..0a0f9838 100644 --- a/docs/requirements.rst +++ b/docs/requirements.rst @@ -5,7 +5,7 @@ Requirements * Web server * MySQL database -* For PHP5: 5.5.9+ +* For PHP5: 5.6.0+ * For PHP7: 7.0.8+ * PHP cURL package * PHP PDO mysql driver diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index 4dc7aa1d..cd1e38e0 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -75,11 +75,11 @@ class InstallController extends AbstractController $phpv = phpversion(); if ( - version_compare($phpv, '5.5.9', '<') || + version_compare($phpv, '5.6.0', '<') || (version_compare($phpv, '7.0.8', '<') && version_compare($phpv, '7.0.0', '>=')) ) { $errors++; - $this->addMessage('PHP 5.5.9+ or 7.0.8+ is required to run PHP Server Monitor. You\'re using ' . + $this->addMessage('PHP 5.6.0+ or 7.0.8+ is required to run PHP Server Monitor. You\'re using ' . $phpv . '.', 'error'); } else { $this->addMessage('PHP version: ' . $phpv, 'success'); From 76687d8c454e4b90250e54baa5cdfbb21be1f1df Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Fri, 1 May 2020 02:36:18 +0200 Subject: [PATCH 45/77] Bumped version to 3.5.0 --- CHANGELOG.rst | 5 + README.rst | 2 +- docs/conf.py | 4 +- src/includes/psmconfig.inc.php | 2 +- src/psm/Util/Install/Installer.php | 366 ++++++++++++++--------------- 5 files changed, 192 insertions(+), 187 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bd10a7d9..df3b2e05 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,11 @@ Not yet released ---------------- \- +v3.5.0 (released May 1, 2020) +----------------------------- + +* See https://github.com/phpservermon/phpservermon/compare/v3.4.5...v3.5.0 + v3.4.5 (released September 30, 2019) ------------------------------------ diff --git a/README.rst b/README.rst index 7204806a..5c453239 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ PHP Server Monitor :alt: Join the chat at https://gitter.im/erickrf/nlpnet :target: https://gitter.im/phpservermon/phpservermon -Version 3.4.5 +Version 3.5.0 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, diff --git a/docs/conf.py b/docs/conf.py index 88485fa6..20f6ef0c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,9 +51,9 @@ copyright = u'2008-2017, Pepijn Over' # built documents. # # The short X.Y version. -version = '3.4.6' +version = '3.5.0' # The full version, including alpha/beta/rc tags. -release = '3.4.6-beta.3' +release = '3.5.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/includes/psmconfig.inc.php b/src/includes/psmconfig.inc.php index 01101143..2491f172 100644 --- a/src/includes/psmconfig.inc.php +++ b/src/includes/psmconfig.inc.php @@ -30,7 +30,7 @@ /** * Current PSM version */ -define('PSM_VERSION', '3.4.6-beta.3'); +define('PSM_VERSION', '3.5.0'); /** * URL to check for updates. Will not be checked if turned off on config page. diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 573c9ed1..888af309 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -141,53 +141,53 @@ class Installer 'yes', 'bad','on', '0.0000000', '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 . "config` (`key`, `value`) VALUE - ('language', 'en_US'), - ('proxy', '0'), - ('proxy_url', ''), - ('proxy_user', ''), - ('proxy_password', ''), - ('email_status', '1'), - ('email_from_email', 'monitor@example.org'), - ('email_from_name', 'Server Monitor'), - ('email_smtp', ''), - ('email_smtp_host', ''), - ('email_smtp_port', ''), - ('email_smtp_security', ''), - ('email_smtp_username', ''), - ('email_smtp_password', ''), - ('sms_status', '0'), - ('sms_gateway', 'messagebird'), - ('sms_gateway_username', 'username'), - ('sms_gateway_password', 'password'), - ('sms_from', '1234567890'), - ('pushover_status', '0'), - ('pushover_api_token', ''), - ('telegram_status', '0'), - ('telegram_api_token', ''), - ('jabber_status', '1'), - ('jabber_host', ''), - ('jabber_port', ''), - ('jabber_username', ''), - ('jabber_domain', ''), - ('jabber_password', ''), - ('password_encrypt_key', '" . sha1(microtime()) . "'), - ('alert_type', 'status'), - ('log_status', '1'), - ('log_email', '1'), - ('log_sms', '1'), - ('log_pushover', '1'), - ('log_telegram', '1'), - ('log_jabber', '1'), - ('log_retention_period', '365'), - ('version', '" . PSM_VERSION . "'), - ('version_update_check', '" . PSM_VERSION . "'), - ('auto_refresh_servers', '0'), - ('show_update', '1'), - ('last_update_check', '0'), - ('cron_running', '0'), - ('cron_running_time', '0'), - ('cron_off_running', '0'), - ('cron_off_running_time', '0');"; + ('language', 'en_US'), + ('proxy', '0'), + ('proxy_url', ''), + ('proxy_user', ''), + ('proxy_password', ''), + ('email_status', '1'), + ('email_from_email', 'monitor@example.org'), + ('email_from_name', 'Server Monitor'), + ('email_smtp', ''), + ('email_smtp_host', ''), + ('email_smtp_port', ''), + ('email_smtp_security', ''), + ('email_smtp_username', ''), + ('email_smtp_password', ''), + ('sms_status', '0'), + ('sms_gateway', 'messagebird'), + ('sms_gateway_username', 'username'), + ('sms_gateway_password', 'password'), + ('sms_from', '1234567890'), + ('pushover_status', '0'), + ('pushover_api_token', ''), + ('telegram_status', '0'), + ('telegram_api_token', ''), + ('jabber_status', '1'), + ('jabber_host', ''), + ('jabber_port', ''), + ('jabber_username', ''), + ('jabber_domain', ''), + ('jabber_password', ''), + ('password_encrypt_key', '" . sha1(microtime()) . "'), + ('alert_type', 'status'), + ('log_status', '1'), + ('log_email', '1'), + ('log_sms', '1'), + ('log_pushover', '1'), + ('log_telegram', '1'), + ('log_jabber', '1'), + ('log_retention_period', '365'), + ('version', '" . PSM_VERSION . "'), + ('version_update_check', '" . PSM_VERSION . "'), + ('auto_refresh_servers', '0'), + ('show_update', '1'), + ('last_update_check', '0'), + ('cron_running', '0'), + ('cron_running_time', '0'), + ('cron_off_running', '0'), + ('cron_off_running_time', '0');"; $this->execSQL($queries); } @@ -198,46 +198,46 @@ class Installer { $tables = array( PSM_DB_PREFIX . 'config' => "CREATE TABLE `" . PSM_DB_PREFIX . "config` ( - `key` varchar(255) NOT NULL, - `value` varchar(255) NOT NULL, - PRIMARY KEY (`key`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", + `key` varchar(255) NOT NULL, + `value` varchar(255) NOT NULL, + PRIMARY KEY (`key`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'users' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "users` ( - `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `user_name` varchar(64) NOT NULL COMMENT 'user''s name, unique', - `password` varchar(255) NOT NULL COMMENT 'user''s password in salted and hashed format', - `password_reset_hash` char(40) DEFAULT NULL COMMENT 'user''s password reset code', - `password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request', - `rememberme_token` varchar(64) DEFAULT NULL COMMENT 'user''s remember-me cookie token', - `level` tinyint(2) unsigned NOT NULL DEFAULT '20', - `name` varchar(255) NOT NULL, - `mobile` varchar(15) NOT NULL, - `pushover_key` varchar(255) NOT NULL, - `pushover_device` varchar(255) NOT NULL, - `telegram_id` varchar(255) NOT NULL, - `jabber` varchar(255) NOT NULL, - `email` varchar(255) NOT NULL, + `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `user_name` varchar(64) NOT NULL COMMENT 'user''s name, unique', + `password` varchar(255) NOT NULL COMMENT 'user''s password in salted and hashed format', + `password_reset_hash` char(40) DEFAULT NULL COMMENT 'user''s password reset code', + `password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request', + `rememberme_token` varchar(64) DEFAULT NULL COMMENT 'user''s remember-me cookie token', + `level` tinyint(2) unsigned NOT NULL DEFAULT '20', + `name` varchar(255) NOT NULL, + `mobile` varchar(15) NOT NULL, + `pushover_key` varchar(255) NOT NULL, + `pushover_device` varchar(255) NOT NULL, + `telegram_id` varchar(255) NOT NULL, + `jabber` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, PRIMARY KEY (`user_id`), UNIQUE KEY `unique_username` (`user_name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'users_preferences' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "users_preferences` ( - `user_id` int(11) unsigned NOT NULL, - `key` varchar(255) NOT NULL, - `value` varchar(255) NOT NULL, + `user_id` int(11) unsigned NOT NULL, + `key` varchar(255) NOT NULL, + `value` varchar(255) NOT NULL, PRIMARY KEY (`user_id`, `key`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'users_servers' => "CREATE TABLE `" . PSM_DB_PREFIX . "users_servers` ( - `user_id` INT( 11 ) UNSIGNED NOT NULL , - `server_id` INT( 11 ) UNSIGNED NOT NULL , + `user_id` INT( 11 ) UNSIGNED NOT NULL , + `server_id` INT( 11 ) UNSIGNED NOT NULL , PRIMARY KEY ( `user_id` , `server_id` ) ) ENGINE = MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` ( - `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `server_id` int(11) unsigned NOT NULL, - `type` enum('status','email','sms','pushover','telegram', 'jabber') NOT NULL, - `message` TEXT NOT NULL, - `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, + `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `type` enum('status','email','sms','pushover','telegram', 'jabber') NOT NULL, + `message` TEXT NOT NULL, + `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`log_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'log_users' => "CREATE TABLE `" . PSM_DB_PREFIX . "log_users` ( @@ -246,44 +246,44 @@ class Installer PRIMARY KEY (`log_id`, `user_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'servers' => "CREATE TABLE `" . PSM_DB_PREFIX . "servers` ( - `server_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `ip` varchar(500) NOT NULL, - `port` int(5) NOT NULL, - `request_method` varchar(50) NULL, - `label` varchar(255) NOT NULL, - `type` enum('ping','service','website') NOT NULL default 'service', - `pattern` varchar(255) NOT NULL default '', - `pattern_online` enum('yes','no') NOT NULL default 'yes', - `post_field` varchar(255) NULL, - `redirect_check` enum('ok','bad') NOT NULL default 'bad', - `allow_http_status` varchar(255) NOT NULL default '', - `header_name` varchar(255) NOT NULL default '', - `header_value` varchar(255) NOT NULL default '', - `status` enum('on','off') NOT NULL default 'on', - `error` varchar(255) NULL, - `rtime` FLOAT(9, 7) NULL, - `last_online` datetime NULL, - `last_offline` datetime NULL, - `last_offline_duration` varchar(255) NULL, - `last_check` datetime NULL, - `active` enum('yes','no') NOT NULL default 'yes', - `email` enum('yes','no') NOT NULL default 'yes', - `sms` enum('yes','no') NOT NULL default 'no', - `pushover` enum('yes','no') NOT NULL default 'yes', - `telegram` 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_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', + `server_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `ip` varchar(500) NOT NULL, + `port` int(5) NOT NULL, + `request_method` varchar(50) NULL, + `label` varchar(255) NOT NULL, + `type` enum('ping','service','website') NOT NULL default 'service', + `pattern` varchar(255) NOT NULL default '', + `pattern_online` enum('yes','no') NOT NULL default 'yes', + `post_field` varchar(255) NULL, + `redirect_check` enum('ok','bad') NOT NULL default 'bad', + `allow_http_status` varchar(255) NOT NULL default '', + `header_name` varchar(255) NOT NULL default '', + `header_value` varchar(255) NOT NULL default '', + `status` enum('on','off') NOT NULL default 'on', + `error` varchar(255) NULL, + `rtime` FLOAT(9, 7) NULL, + `last_online` datetime NULL, + `last_offline` datetime NULL, + `last_offline_duration` varchar(255) NULL, + `last_check` datetime NULL, + `active` enum('yes','no') NOT NULL default 'yes', + `email` enum('yes','no') NOT NULL default 'yes', + `sms` enum('yes','no') NOT NULL default 'no', + `pushover` enum('yes','no') NOT NULL default 'yes', + `telegram` 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_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', `ssl_cert_expiry_days` mediumint(1) unsigned NOT NULL DEFAULT '0', `ssl_cert_expired_time` varchar(255) NULL, - `timeout` smallint(1) unsigned NULL DEFAULT NULL, - `website_username` varchar(255) DEFAULT NULL, - `website_password` varchar(255) DEFAULT NULL, - `last_error` varchar(255) DEFAULT NULL, - `last_error_output` TEXT, - `last_output` TEXT, - PRIMARY KEY (`server_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", + `timeout` smallint(1) unsigned NULL DEFAULT NULL, + `website_username` varchar(255) DEFAULT NULL, + `website_password` varchar(255) DEFAULT NULL, + `last_error` varchar(255) DEFAULT NULL, + `last_error_output` TEXT, + `last_output` TEXT, + PRIMARY KEY (`server_id`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'servers_uptime' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_uptime` ( `servers_uptime_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `server_id` int(11) unsigned NOT NULL, @@ -294,14 +294,14 @@ class Installer KEY `server_id` (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'servers_history' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_history` ( - `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `server_id` int(11) unsigned NOT NULL, - `date` date NOT NULL, - `latency_min` float(9,7) NOT NULL, - `latency_avg` float(9,7) NOT NULL, - `latency_max` float(9,7) NOT NULL, - `checks_total` int(11) unsigned NOT NULL, - `checks_failed` int(11) unsigned NOT NULL, + `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `date` date NOT NULL, + `latency_min` float(9,7) NOT NULL, + `latency_avg` float(9,7) NOT NULL, + `latency_max` float(9,7) NOT NULL, + `checks_total` int(11) unsigned NOT NULL, + `checks_failed` int(11) unsigned NOT NULL, PRIMARY KEY (`servers_history_id`), UNIQUE KEY `server_id_date` (`server_id`,`date`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", @@ -354,8 +354,8 @@ class Installer if (version_compare($version_from, '3.4.2', '<')) { $this->upgrade342(); } - if (version_compare($version_from, '3.4.6-beta.3', '<')) { - $this->upgrade346(); + if (version_compare($version_from, '3.5.0', '<')) { + $this->upgrade350(); } psm_update_conf('version', $version_to); } @@ -431,49 +431,49 @@ class Installer $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` CHANGE `user_id` `user_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` - ADD `user_name` varchar(64) COLLATE utf8_general_ci NOT NULL + ADD `user_name` varchar(64) COLLATE utf8_general_ci NOT NULL COMMENT 'user\'s name, unique' AFTER `user_id`, - ADD `password` varchar(255) COLLATE utf8_general_ci NOT NULL + ADD `password` varchar(255) COLLATE utf8_general_ci NOT NULL COMMENT 'user\'s password in salted and hashed format' AFTER `user_name`, - ADD `password_reset_hash` char(40) COLLATE utf8_general_ci DEFAULT NULL + ADD `password_reset_hash` char(40) COLLATE utf8_general_ci DEFAULT NULL COMMENT 'user\'s password reset code' AFTER `password`, - ADD `password_reset_timestamp` bigint(20) DEFAULT NULL + ADD `password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request' AFTER `password_reset_hash`, - ADD `rememberme_token` varchar(64) COLLATE utf8_general_ci DEFAULT NULL + ADD `rememberme_token` varchar(64) COLLATE utf8_general_ci DEFAULT NULL COMMENT 'user\'s remember-me cookie token' AFTER `password_reset_timestamp`, - ADD `level` TINYINT( 2 ) UNSIGNED NOT NULL DEFAULT '20' AFTER `rememberme_token`;"; + ADD `level` TINYINT( 2 ) UNSIGNED NOT NULL DEFAULT '20' AFTER `rememberme_token`;"; // make sure all current users are admins (previously we didnt have non-admins): $queries[] = "UPDATE `" . PSM_DB_PREFIX . "users` SET `user_name`=`email`, `level`=10;"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` ADD UNIQUE `unique_username` ( `user_name` );"; $queries[] = "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_uptime` ( - `servers_uptime_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `server_id` int(11) unsigned NOT NULL, - `date` datetime NOT NULL, - `status` tinyint(1) unsigned NOT NULL, - `latency` float(9,7) DEFAULT NULL, - PRIMARY KEY (`servers_uptime_id`), - KEY `server_id` (`server_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; + `servers_uptime_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `date` datetime NOT NULL, + `status` tinyint(1) unsigned NOT NULL, + `latency` float(9,7) DEFAULT NULL, + PRIMARY KEY (`servers_uptime_id`), + KEY `server_id` (`server_id`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; $queries[] = "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_history` ( - `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `server_id` int(11) unsigned NOT NULL, - `date` date NOT NULL, - `latency_min` float(9,7) NOT NULL, - `latency_avg` float(9,7) NOT NULL, - `latency_max` float(9,7) NOT NULL, - `checks_total` int(11) unsigned NOT NULL, - `checks_failed` int(11) unsigned NOT NULL, - PRIMARY KEY (`servers_history_id`), - UNIQUE KEY `server_id_date` (`server_id`,`date`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; + `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `date` date NOT NULL, + `latency_min` float(9,7) NOT NULL, + `latency_avg` float(9,7) NOT NULL, + `latency_max` float(9,7) NOT NULL, + `checks_total` int(11) unsigned NOT NULL, + `checks_failed` int(11) unsigned NOT NULL, + PRIMARY KEY (`servers_history_id`), + UNIQUE KEY `server_id_date` (`server_id`,`date`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; $queries[] = "CREATE TABLE `" . PSM_DB_PREFIX . "users_servers` ( - `user_id` INT( 11 ) UNSIGNED NOT NULL , - `server_id` INT( 11 ) UNSIGNED NOT NULL , - PRIMARY KEY ( `user_id` , `server_id` ) - ) ENGINE = MYISAM ;"; + `user_id` INT( 11 ) UNSIGNED NOT NULL , + `server_id` INT( 11 ) UNSIGNED NOT NULL , + PRIMARY KEY ( `user_id` , `server_id` ) + ) ENGINE = MYISAM ;"; $this->execSQL($queries); // from 3.0 all user-server relations are in a separate table @@ -525,11 +525,11 @@ class Installer $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `last_offline_duration` varchar(255) NULL;"; $queries[] = "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "users_preferences` ( - `user_id` int(11) unsigned NOT NULL, - `key` varchar(255) NOT NULL, - `value` varchar(255) NOT NULL, - PRIMARY KEY (`user_id`, `key`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; + `user_id` int(11) unsigned NOT NULL, + `key` varchar(255) NOT NULL, + `value` varchar(255) NOT NULL, + PRIMARY KEY (`user_id`, `key`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; $this->execSQL($queries); } @@ -546,10 +546,10 @@ class Installer $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `website_username` varchar(255) NULL, ADD `website_password` varchar(255) NULL AFTER `website_username`;"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE - ('proxy', '0'), - ('proxy_url', ''), - ('proxy_user', ''), - ('proxy_password', '');"; + ('proxy', '0'), + ('proxy_url', ''), + ('proxy_user', ''), + ('proxy_password', '');"; $this->execSQL($queries); @@ -603,9 +603,9 @@ class Installer "log` CHANGE `type` `type` ENUM( 'status', 'email', 'sms', 'pushover', 'telegram' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE - ('telegram_status', '0'), - ('log_telegram', '1'), - ('telegram_api_token', '');"; + ('telegram_status', '0'), + ('log_telegram', '1'), + ('telegram_api_token', '');"; $this->execSQL($queries); } @@ -673,9 +673,9 @@ class Installer } /** - * Upgrade for v3.4.6 release + * Upgrade for v3.5.0 release */ - protected function upgrade346() + protected function upgrade350() { $queries = array(); $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` @@ -683,19 +683,19 @@ class Installer $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `ssl_cert_expired_time` VARCHAR(255) NULL AFTER `ssl_cert_expiry_days`"; - if ( - @psm_password_decrypt( - psm_get_conf('password_encrypt_key'), - psm_get_conf('email_smtp_password') - ) === false - ) { - // Prevents encrypting the password multiple times. - $queries[] = "UPDATE `" . PSM_DB_PREFIX . "config` + if ( + @psm_password_decrypt( + psm_get_conf('password_encrypt_key'), + psm_get_conf('email_smtp_password') + ) === false + ) { + // Prevents encrypting the password multiple times. + $queries[] = "UPDATE `" . PSM_DB_PREFIX . "config` SET `value` = '" . - psm_password_encrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('email_smtp_password')) . - "' WHERE `key` = 'email_smtp_password'"; - $this->log('SMTP password is now encrypted.'); - } + psm_password_encrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('email_smtp_password')) . + "' WHERE `key` = 'email_smtp_password'"; + $this->log('SMTP password is now encrypted.'); + } $queries[] = 'ALTER TABLE `' . PSM_DB_PREFIX . 'users` ADD `jabber` VARCHAR( 255 ) NOT NULL AFTER `telegram_id`;'; @@ -705,13 +705,13 @@ class Installer "log` CHANGE `type` `type` ENUM( 'status', 'email', 'sms', 'pushover', 'telegram', 'jabber' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE - ('jabber_status', '0'), - ('log_jabber', '1'), - ('jabber_host', ''), - ('jabber_port', ''), - ('jabber_username', ''), - ('jabber_domain', ''), - ('jabber_password', '');"; + ('jabber_status', '0'), + ('log_jabber', '1'), + ('jabber_host', ''), + ('jabber_port', ''), + ('jabber_username', ''), + ('jabber_domain', ''), + ('jabber_password', '');"; $this->execSQL($queries); } From 424fca1eb7ee04ce3489b70891fdf9b7af41547c Mon Sep 17 00:00:00 2001 From: imsoftware Date: Wed, 6 May 2020 18:24:20 +0200 Subject: [PATCH 46/77] change http to https (#900) --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 5c453239..b6a29294 100644 --- a/README.rst +++ b/README.rst @@ -105,7 +105,7 @@ If you are familiar with Vagrant (https://www.vagrantup.com):: Documentation ------------- -The documentation is available in the docs folder or http://docs.phpservermonitor.org. +The documentation is available in the docs folder or https://docs.phpservermonitor.org. License @@ -122,7 +122,7 @@ 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/. +along with PHP Server Monitor. If not, see https://www.gnu.org/licenses/. Docker ------- From 7bee25cc1e11093526cebf83df6c248624cc4911 Mon Sep 17 00:00:00 2001 From: wienfuchs <44177781+wienfuchs@users.noreply.github.com> Date: Fri, 15 May 2020 16:55:57 +0200 Subject: [PATCH 47/77] Re-adding support PHP 5.5.9/7.0.x (#915) Resolves #908. --- README.rst | 2 +- docs/requirements.rst | 2 +- src/psm/Module/Install/Controller/InstallController.php | 4 ++-- src/psm/Module/User/UserEvents.php | 6 +++--- src/psm/Txtmsg/CMBulkSMS.php | 4 ++-- src/psm/Util/Module/Modal.php | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index b6a29294..fec739aa 100644 --- a/README.rst +++ b/README.rst @@ -77,7 +77,7 @@ Requirements * Web server * MySQL database -* For PHP5: 5.6.0+ +* For PHP5: 5.5.9+ * For PHP7: 7.0.8+ * PHP cURL package * PHP PDO mysql driver diff --git a/docs/requirements.rst b/docs/requirements.rst index 0a0f9838..636dde40 100644 --- a/docs/requirements.rst +++ b/docs/requirements.rst @@ -5,7 +5,7 @@ Requirements * Web server * MySQL database -* For PHP5: 5.6.0+ +* For PHP5: 5.5.9+ * For PHP7: 7.0.8+ * PHP cURL package * PHP PDO mysql driver diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index cd1e38e0..4dc7aa1d 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -75,11 +75,11 @@ class InstallController extends AbstractController $phpv = phpversion(); 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', '>=')) ) { $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'); } else { $this->addMessage('PHP version: ' . $phpv, 'success'); diff --git a/src/psm/Module/User/UserEvents.php b/src/psm/Module/User/UserEvents.php index 33767928..de5ca932 100644 --- a/src/psm/Module/User/UserEvents.php +++ b/src/psm/Module/User/UserEvents.php @@ -35,15 +35,15 @@ final class UserEvents /** * @var string */ - public const USER_ADD = 'user.add'; + const USER_ADD = 'user.add'; /** * @var string */ - public const USER_EDIT = 'user.edit'; + const USER_EDIT = 'user.edit'; /** * @var string */ - public const USER_DELETE = 'user.delete'; + const USER_DELETE = 'user.delete'; } diff --git a/src/psm/Txtmsg/CMBulkSMS.php b/src/psm/Txtmsg/CMBulkSMS.php index a009d252..9a20c126 100644 --- a/src/psm/Txtmsg/CMBulkSMS.php +++ b/src/psm/Txtmsg/CMBulkSMS.php @@ -67,10 +67,10 @@ class CMBulkSMS extends Core protected $messageBody; /** @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 */ - 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 diff --git a/src/psm/Util/Module/Modal.php b/src/psm/Util/Module/Modal.php index 76d27ee6..fba72822 100644 --- a/src/psm/Util/Module/Modal.php +++ b/src/psm/Util/Module/Modal.php @@ -32,9 +32,9 @@ namespace psm\Util\Module; class Modal implements ModalInterface { - public const MODAL_TYPE_OK = 0; - public const MODAL_TYPE_OKCANCEL = 1; - public const MODAL_TYPE_DANGER = 2; + const MODAL_TYPE_OK = 0; + const MODAL_TYPE_OKCANCEL = 1; + const MODAL_TYPE_DANGER = 2; /** * prefix used for modal dialog box elements From 7daab77f8d898b3972ab0e70e505da7df591a19d Mon Sep 17 00:00:00 2001 From: Michael <33117529+mtelgkamp@users.noreply.github.com> Date: Fri, 15 May 2020 17:22:54 +0200 Subject: [PATCH 48/77] Adjust required php extensions (#904) af5334a0 introduced the following requirements: - ext-hash - ext-json - ext-libxml - ext-openssl - ext-pcre - ext-sockets Maybe also the functionality that needs the extension could be mentioned, so someone that does not need jabber, could install with `--ignore-platform-reqs` when not having these extensions available. --- README.rst | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index fec739aa..11837483 100644 --- a/README.rst +++ b/README.rst @@ -79,10 +79,19 @@ Requirements * MySQL database * For PHP5: 5.5.9+ * For PHP7: 7.0.8+ -* PHP cURL package -* PHP PDO mysql driver -* PHP-XML +* PHP Extensions (modules) + * ext-curl + * ext-ctype + * ext-filter + * ext-hash + * ext-json + * ext-libxml + * ext-openssl + * ext-pdo + * ext-pcre + * ext-sockets + * ext-xml Install ------- From c0e0b260d5a67cd41615810190c2786b57991583 Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Sun, 17 May 2020 21:03:42 +0200 Subject: [PATCH 49/77] Indent to space --- src/includes/functions.inc.php | 2 +- .../Config/Controller/ConfigController.php | 76 ++++++------- .../Install/Controller/InstallController.php | 2 +- .../Server/Controller/LogController.php | 8 +- .../Server/Controller/ServerController.php | 10 +- .../User/Controller/ProfileController.php | 4 +- src/psm/Util/Server/UpdateManager.php | 18 ++-- .../Util/Server/Updater/StatusNotifier.php | 102 +++++++++--------- src/psm/Util/Server/Updater/StatusUpdater.php | 12 +-- 9 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 8fb1c449..c1754cdd 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -689,7 +689,7 @@ namespace { $client->add_cb('on_auth_success', function () use ($client, $receivers, $message) { JAXLLogger::info('got on_auth_success cb'); foreach ($receivers as $receiver) { - $client->send_chat_msg($receiver, $message); + $client->send_chat_msg($receiver, $message); } $client->send_end_stream(); }); diff --git a/src/psm/Module/Config/Controller/ConfigController.php b/src/psm/Module/Config/Controller/ConfigController.php index 4c6a7e5d..01216e2a 100644 --- a/src/psm/Module/Config/Controller/ConfigController.php +++ b/src/psm/Module/Config/Controller/ConfigController.php @@ -74,10 +74,10 @@ class ConfigController extends AbstractController 'sms_from', 'pushover_api_token', 'telegram_api_token', - 'jabber_host', - 'jabber_port', - 'jabber_username', - 'jabber_domain' + 'jabber_host', + 'jabber_port', + 'jabber_username', + 'jabber_domain' ); /** @@ -86,7 +86,7 @@ class ConfigController extends AbstractController */ protected $encryptedFields = [ 'email_smtp_password', - 'jabber_password' + 'jabber_password' ]; private $default_tab = 'general'; @@ -221,7 +221,7 @@ class ConfigController extends AbstractController protected function executeSave() { if (!empty($_POST)) { - // save new config + // save new config $clean = array( 'language' => $_POST['language'], 'sms_gateway' => $_POST['sms_gateway'], @@ -234,7 +234,7 @@ class ConfigController extends AbstractController 'log_retention_period' => intval(psm_POST('log_retention_period', 365)), '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'; } foreach ($this->fields as $input_key) { @@ -264,7 +264,7 @@ class ConfigController extends AbstractController } elseif (!empty($_POST['test_telegram'])) { $this->testTelegram(); } elseif (!empty($_POST['test_jabber'])) { - $this->testJabber(); + $this->testJabber(); } if ($language_refresh) { @@ -283,7 +283,7 @@ class ConfigController extends AbstractController } elseif (isset($_POST['telegram_submit']) || !empty($_POST['test_telegram'])) { $this->default_tab = 'telegram'; } elseif (isset($_POST['jabber_submit']) || !empty($_POST['test_jabber'])) { - $this->default_tab = 'jabber'; + $this->default_tab = 'jabber'; } } return $this->runAction('index'); @@ -408,24 +408,24 @@ class ConfigController extends AbstractController } } - /** - * Test Jabber. - */ + /** + * Test Jabber. + */ protected function testJabber() { - $user = $this->getUser()->getUser(); - psm_jabber_send_message( - psm_get_conf('jabber_host'), - psm_get_conf('jabber_username'), - psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), - [$user->jabber], - psm_get_lang('config', 'test_message'), - (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) - ); - // no message - async ... so just info - $this->addMessage(psm_get_lang('config', 'jabber_check'), 'info'); - // @todo possible to set message via ajax with callback ... + $user = $this->getUser()->getUser(); + psm_jabber_send_message( + psm_get_conf('jabber_host'), + psm_get_conf('jabber_username'), + psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), + [$user->jabber], + psm_get_lang('config', 'test_message'), + (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) + ); + // no message - async ... so just info + $this->addMessage(psm_get_lang('config', 'jabber_check'), 'info'); + // @todo possible to set message via ajax with callback ... } protected function getLabels() @@ -435,12 +435,12 @@ class ConfigController extends AbstractController 'label_tab_sms' => psm_get_lang('config', 'tab_sms'), 'label_tab_pushover' => psm_get_lang('config', 'tab_pushover'), '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_sms' => psm_get_lang('config', 'settings_sms'), 'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'), '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_log' => psm_get_lang('config', 'settings_log'), 'label_settings_proxy' => psm_get_lang('config', 'settings_proxy'), @@ -482,17 +482,17 @@ class ConfigController extends AbstractController '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_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_description' => psm_get_lang('config', 'jabber_host_description'), - 'label_jabber_port' => psm_get_lang('config', 'jabber_port'), - 'label_jabber_port_description' => psm_get_lang('config', 'jabber_port_description'), - 'label_jabber_username' => psm_get_lang('config', 'jabber_username'), - 'label_jabber_username_description' => psm_get_lang('config', 'jabber_username_description'), - 'label_jabber_domain' => psm_get_lang('config', 'jabber_domain'), - 'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'), - 'label_jabber_password' => psm_get_lang('config', 'jabber_password'), - 'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'), + 'label_jabber_host_description' => psm_get_lang('config', 'jabber_host_description'), + 'label_jabber_port' => psm_get_lang('config', 'jabber_port'), + 'label_jabber_port_description' => psm_get_lang('config', 'jabber_port_description'), + 'label_jabber_username' => psm_get_lang('config', 'jabber_username'), + 'label_jabber_username_description' => psm_get_lang('config', 'jabber_username_description'), + 'label_jabber_domain' => psm_get_lang('config', 'jabber_domain'), + 'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'), + 'label_jabber_password' => psm_get_lang('config', 'jabber_password'), + 'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'), 'label_alert_type' => psm_get_lang('config', 'alert_type'), 'label_alert_type_description' => psm_get_lang('config', 'alert_type_description'), 'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'), @@ -503,7 +503,7 @@ class ConfigController extends AbstractController 'label_log_sms' => psm_get_lang('config', 'log_sms'), 'label_log_pushover' => psm_get_lang('config', 'log_pushover'), '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_url' => psm_get_lang('config', 'alert_proxy_url'), 'label_auto_refresh' => psm_get_lang('config', 'auto_refresh'), diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index 4dc7aa1d..8acb471f 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -257,7 +257,7 @@ class InstallController extends AbstractController 'pushover_key' => '', 'pushover_device' => '', 'telegram_id' => '', - 'jabber' => '' + 'jabber' => '' ); $validator = $this->container->get('util.user.validator'); diff --git a/src/psm/Module/Server/Controller/LogController.php b/src/psm/Module/Server/Controller/LogController.php index 72685baf..8046af99 100644 --- a/src/psm/Module/Server/Controller/LogController.php +++ b/src/psm/Module/Server/Controller/LogController.php @@ -57,7 +57,7 @@ class LogController extends AbstractServerController 'label_sms' => psm_get_lang('log', 'sms'), 'label_pushover' => psm_get_lang('log', 'pushover'), '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_server' => psm_get_lang('servers', 'server'), 'label_type' => psm_get_lang('log', 'type'), @@ -161,9 +161,9 @@ class LogController extends AbstractServerController 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` - )"; + `us`.`user_id`={$this->getUser()->getUserId()} + AND `us`.`server_id`=`servers`.`server_id` + )"; } $entries = $this->db->query( 'SELECT ' . diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 16f0860d..1c2cb299 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -102,7 +102,7 @@ class ServerController extends AbstractServerController 'sms' => 'icon-mobile', 'pushover' => 'icon-pushover', 'telegram' => 'icon-telegram', - 'jabber' => 'icon-jabber' + 'jabber' => 'icon-jabber' ); $servers = $this->getServers(); @@ -236,7 +236,7 @@ class ServerController extends AbstractServerController 'edit_sms_selected' => $edit_server['sms'], 'edit_pushover_selected' => $edit_server['pushover'], 'edit_telegram_selected' => $edit_server['telegram'], - 'edit_jabber_selected' => $edit_server['jabber'], + 'edit_jabber_selected' => $edit_server['jabber'], )); } @@ -310,7 +310,7 @@ class ServerController extends AbstractServerController 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', 'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : '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:// if ( @@ -579,10 +579,10 @@ class ServerController extends AbstractServerController 'label_send_sms' => psm_get_lang('servers', 'send_sms'), 'label_send_pushover' => psm_get_lang('servers', 'send_pushover'), 'label_telegram' => psm_get_lang('servers', 'telegram'), - 'label_jabber' => psm_get_lang('servers', 'jabber'), + 'label_jabber' => psm_get_lang('servers', 'jabber'), 'label_pushover' => psm_get_lang('servers', 'pushover'), '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_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), diff --git a/src/psm/Module/User/Controller/ProfileController.php b/src/psm/Module/User/Controller/ProfileController.php index 09f88691..47efc335 100644 --- a/src/psm/Module/User/Controller/ProfileController.php +++ b/src/psm/Module/User/Controller/ProfileController.php @@ -90,8 +90,8 @@ class ProfileController extends AbstractController 'label_activate_telegram' => psm_get_lang('users', 'activate_telegram'), 'label_telegram_get_chat_id' => psm_get_lang('users', 'telegram_get_chat_id'), 'telegram_get_chat_id_url' => PSM_TELEGRAM_GET_ID_URL, - 'label_jabber' => psm_get_lang('users', 'jabber'), - 'label_jabber_description' => psm_get_lang('users', 'jabber_description'), + 'label_jabber' => psm_get_lang('users', 'jabber'), + 'label_jabber_description' => psm_get_lang('users', 'jabber_description'), 'label_email' => psm_get_lang('users', 'email'), 'label_save' => psm_get_lang('system', 'save'), 'form_action' => psm_build_url(array( diff --git a/src/psm/Util/Server/UpdateManager.php b/src/psm/Util/Server/UpdateManager.php index 2e3ee42c..e5429df6 100644 --- a/src/psm/Util/Server/UpdateManager.php +++ b/src/psm/Util/Server/UpdateManager.php @@ -53,9 +53,9 @@ class UpdateManager implements ContainerAwareInterface */ public function run($skip_perms = false, $status = null) { - if (false === in_array($status, ['on', 'off'], true)) { - $status = null; - } + if (false === in_array($status, ['on', 'off'], true)) { + $status = null; + } // check if we need to restrict the servers to a certain user $sql_join = ''; @@ -63,17 +63,17 @@ class UpdateManager implements ContainerAwareInterface if (!$skip_perms && $this->container->get('user')->getUserLevel() > PSM_USER_ADMIN) { // restrict by user_id $sql_join = "JOIN `" . PSM_DB_PREFIX . "users_servers` AS `us` ON ( - `us`.`user_id`={$this->container->get('user')->getUserId()} - AND `us`.`server_id`=`s`.`server_id` - )"; + `us`.`user_id`={$this->container->get('user')->getUserId()} + 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`, `s`.`header_value`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`,`s`.`pushover`,`s`.`telegram`, `s`.`jabber` - FROM `" . PSM_DB_PREFIX . "servers` AS `s` - {$sql_join} - WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : ''); + FROM `" . PSM_DB_PREFIX . "servers` AS `s` + {$sql_join} + WHERE `active`='yes' " . ($status !== null ? ' AND `status` = \'' . $status . '\'' : ''); $servers = $this->container->get('db')->query($sql); diff --git a/src/psm/Util/Server/Updater/StatusNotifier.php b/src/psm/Util/Server/Updater/StatusNotifier.php index 5b0672a6..d1db8ae7 100644 --- a/src/psm/Util/Server/Updater/StatusNotifier.php +++ b/src/psm/Util/Server/Updater/StatusNotifier.php @@ -69,10 +69,10 @@ class StatusNotifier */ protected $send_telegram = false; - /** - * Send Jabber? - * @var bool - */ + /** + * Send Jabber? + * @var bool + */ protected $send_jabber = false; /** @@ -258,7 +258,7 @@ class StatusNotifier } 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; @@ -562,52 +562,52 @@ class StatusNotifier } } - /** - * @param array $users - * @param array $combi - */ + /** + * @param array $users + * @param array $combi + */ protected function notifyByJabber($users, $combi = []) { - // Remove users that have no jabber - foreach ($users as $k => $user) { - if (trim($user['jabber']) === '') { - unset($users[$k]); - } - } + // Remove users that have no jabber + foreach ($users as $k => $user) { + if (trim($user['jabber']) === '') { + unset($users[$k]); + } + } - // Validation - if (empty($users)) { - return; - } + // Validation + if (empty($users)) { + return; + } - // Message - $message = key_exists('message', $combi) ? - $combi['message'] : - psm_parse_msg($this->status_new, 'jabber_message', $this->server); + // Message + $message = key_exists('message', $combi) ? + $combi['message'] : + psm_parse_msg($this->status_new, 'jabber_message', $this->server); - // Log - if (psm_get_conf('log_jabber')) { - $log_id = psm_add_log($this->server_id, 'jabber', $message); - } + // Log + if (psm_get_conf('log_jabber')) { + $log_id = psm_add_log($this->server_id, 'jabber', $message); + } - $usersJabber = []; - foreach ($users as $user) { - // Log - if (!empty($log_id)) { - psm_add_log_user($log_id, $user['user_id']); - } - $usersJabber[] = $user['jabber']; - } - // Jabber - psm_jabber_send_message( - psm_get_conf('jabber_host'), - psm_get_conf('jabber_username'), - psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), - $usersJabber, - $message, - (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) - ); + $usersJabber = []; + foreach ($users as $user) { + // Log + if (!empty($log_id)) { + psm_add_log_user($log_id, $user['user_id']); + } + $usersJabber[] = $user['jabber']; + } + // Jabber + psm_jabber_send_message( + psm_get_conf('jabber_host'), + psm_get_conf('jabber_username'), + psm_password_decrypt(psm_get_conf('password_encrypt_key'), psm_get_conf('jabber_password')), + $usersJabber, + $message, + (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) + ); } /** @@ -622,12 +622,12 @@ class StatusNotifier SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`, `u`.`pushover_key`, `u`.`pushover_device`, `u`.`telegram_id`, `u`.`jabber` - FROM `' . PSM_DB_PREFIX . 'users` AS `u` - JOIN `' . PSM_DB_PREFIX . "users_servers` AS `us` ON ( - `us`.`user_id`=`u`.`user_id` - AND `us`.`server_id` = {$server_id} - ) - "); + FROM `' . PSM_DB_PREFIX . 'users` AS `u` + JOIN `' . PSM_DB_PREFIX . "users_servers` AS `us` ON ( + `us`.`user_id`=`u`.`user_id` + AND `us`.`server_id` = {$server_id} + ) + "); return $users; } } diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 6d6ff34b..af3a8cdd 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -182,9 +182,9 @@ class StatusUpdater // Execute ping $pingCommand = 'ping6'; $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) { $pingCommand = 'ping'; - } + } $txt = exec($pingCommand . " -c " . $max_runs . " " . $serverIp . " 2>&1", $output); // Non-greedy match on filler $re1 = '.*?'; @@ -197,9 +197,9 @@ class StatusUpdater 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 (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; @@ -233,7 +233,7 @@ class StatusUpdater $starttime = microtime(true); $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]"; } $fp = @fsockopen($serverIp, $this->server['port'], $errno, $this->error, $timeout); From 586c01136e61944de780501a04e30cad81d5d22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ma=C5=82ek?= Date: Mon, 18 May 2020 00:28:15 +0200 Subject: [PATCH 50/77] SMSAPI gateway --- docs/credits.rst | 4 + src/includes/functions.inc.php | 3 + src/psm/Txtmsg/SMSAPI.php | 150 +++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100755 src/psm/Txtmsg/SMSAPI.php diff --git a/docs/credits.rst b/docs/credits.rst index 6786fb1d..75a1aadc 100644 --- a/docs/credits.rst +++ b/docs/credits.rst @@ -85,6 +85,10 @@ The following people have contributed to the development of PHP Server Monitor: * Nexmo SMS gateway +* Mateusz Małek - https://github.com/mateuszmalek + + * SMSAPI gateway + Translators +++++++++++ diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 8fb1c449..a4398029 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -779,6 +779,9 @@ namespace { case 'solutionsinfini': $sms = new \psm\Txtmsg\SolutionsInfini(); break; + case 'smsapi': + $sms = new \psm\Txtmsg\SMSAPI(); + break; } // copy login information from the config file diff --git a/src/psm/Txtmsg/SMSAPI.php b/src/psm/Txtmsg/SMSAPI.php new file mode 100755 index 00000000..e446c169 --- /dev/null +++ b/src/psm/Txtmsg/SMSAPI.php @@ -0,0 +1,150 @@ +. + * + * @package phpservermon + * @author Mateusz Małek + * @copyright Copyright (c) 2008-2017 Pepijn Over + * @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); + } +} From 72de1479fa92c72f6502a16b5a0a37e76a05697a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ma=C5=82ek?= Date: Mon, 18 May 2020 09:10:16 +0200 Subject: [PATCH 51/77] Add SMSAPI to list of supported SMS gateways --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 11837483..52c184f7 100644 --- a/README.rst +++ b/README.rst @@ -60,6 +60,7 @@ The following SMS gateways are currently available: * SolutionsInfini - * Plivo - * Callr - +* SMSAPI - From 875b0208b59c01f2bde27fdbfd0d2d309668f14c Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Mon, 18 May 2020 19:41:08 +0200 Subject: [PATCH 52/77] Indentation --- src/psm/Txtmsg/SMSAPI.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/psm/Txtmsg/SMSAPI.php b/src/psm/Txtmsg/SMSAPI.php index e446c169..83601e05 100755 --- a/src/psm/Txtmsg/SMSAPI.php +++ b/src/psm/Txtmsg/SMSAPI.php @@ -86,8 +86,7 @@ class SMSAPI extends Core // One user at a time. $recipients_chunk = array_chunk($this->recipients, 1); - foreach ($recipients_chunk as $recipient) - { + foreach ($recipients_chunk as $recipient) { try { $response = $this->processSendOperation($host, $recipient, $message); } catch (\RuntimeException $e) { From 489465389113d1e829adf968527045432ee5a035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ma=C5=82ek?= Date: Mon, 18 May 2020 19:42:24 +0200 Subject: [PATCH 53/77] Show recent status logs on server details page (#921) --- .../Server/Controller/ServerController.php | 51 +++++++++++++++++++ .../module/server/server/view.tpl.html | 29 +++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index 1c2cb299..28c03f8d 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -518,6 +518,15 @@ class ServerController extends AbstractServerController if (strlen($tpl_data['last_error_output']) > 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); } @@ -606,6 +615,10 @@ class ServerController extends AbstractServerController 'label_settings' => psm_get_lang('system', 'settings'), 'label_output' => psm_get_lang('servers', 'output'), '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 +640,42 @@ class ServerController extends AbstractServerController } 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; + } } diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index 20218480..7b22a0f0 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -354,6 +354,35 @@
    {{ html_history|raw }}
    + {% if log_entries %} +
    +
    +
    + {{ label_log_title }} +
    +
    +
    + + + + + + + + + {% for entry in log_entries %} + + + + + {% endfor %} + +
    {{ label_date }}{{ label_message }}
    {{ entry.message|raw }}
    +
    +
    +
    +
    + {% endif %} {% if graph.id == 'history_short' %} diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index 110c1261..8fd94464 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -9,7 +9,7 @@ {{ label_domain }} {{ label_port }} {{ label_type }} - {{ label_rtime }} + {{ label_rtime }} (ms) {{ label_last_online }} {{ label_last_offline }} {{ label_monitoring }} @@ -41,7 +41,7 @@
    {{ server.ip|raw }}
    {{ server.port }} {{ server.type }} - {{ server.rtime }} + {{ (server.rtime * 1000)|round(2) }}
    {{ server.last_online }}
    {{ server.last_offline }}
    diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index 7b22a0f0..f418b4ee 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -51,7 +51,7 @@
  • {{ label_rtime }}:
    -
    {{ rtime }} {{ label_seconds }}
    +
    {{ (rtime * 1000)|round(2) }} {{ label_milliseconds }}
  • diff --git a/src/templates/default/module/server/status/index.tpl.html b/src/templates/default/module/server/status/index.tpl.html index 7a564127..77a98877 100644 --- a/src/templates/default/module/server/status/index.tpl.html +++ b/src/templates/default/module/server/status/index.tpl.html @@ -37,7 +37,7 @@

    {{ label_last_online }}: {{ server.last_online_nice }}
    {{ label_last_offline }}: {{ server.last_offline_nice }} {{ server.last_offline_duration_nice }}
    - {{ label_rtime }}: {{ server.rtime }} + {{ label_rtime }}: {{ (server.rtime * 1000)|round(2) }} ms

    @@ -97,7 +97,7 @@ {{ server.label }} ({{ label_online }}) {{ server.last_online_nice }} {{ server.last_offline_nice }} {{ server.last_offline_duration_nice }} - {{ server.rtime }}s + {{ (server.rtime * 1000)|round(2) }} ms {% endfor %} From 7856de4bbbb22cb4bec416489c7e4f443e61f049 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 18 May 2020 20:43:13 +0200 Subject: [PATCH 58/77] Better fit for bigger screens (#875) Fixes #857. --- src/templates/default/main/body.tpl.html | 24 ++++++++++--------- .../module/server/server/view.tpl.html | 2 +- .../module/server/status/index.tpl.html | 8 +++---- .../default/static/css/style.min.css | 2 +- .../default/static/css/style.min.css.map | 2 +- src/templates/default/static/scss/style.scss | 4 ++++ 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/templates/default/main/body.tpl.html b/src/templates/default/main/body.tpl.html index 7a1c3523..86d01332 100644 --- a/src/templates/default/main/body.tpl.html +++ b/src/templates/default/main/body.tpl.html @@ -31,31 +31,33 @@ {{ html_modal|raw }} -
    +
    {% if not user_level and subtitle %}

    {{ subtitle }}

    {% endif %} -
    {{ header_accessories|raw }}
    +
    {{ header_accessories|raw }}
    {% for msg in messages %} {% endfor %} -
    +
    {{ html_sidebar|raw }}
    {{ html_content|raw }}
    diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index f418b4ee..be5906f4 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -1,6 +1,6 @@ {% import 'main/macros.tpl.html' as macro %} {{ macro.input_csrf() }} -
    +
    diff --git a/src/templates/default/module/server/status/index.tpl.html b/src/templates/default/module/server/status/index.tpl.html index 77a98877..6102ef64 100644 --- a/src/templates/default/module/server/status/index.tpl.html +++ b/src/templates/default/module/server/status/index.tpl.html @@ -1,10 +1,10 @@ {% import 'main/macros.tpl.html' as macro %} {{ macro.input_csrf() }} -
    +
    {% for server in servers_offline %} -
    +
    @@ -17,7 +17,7 @@
    {% endfor %} {% for server in servers_warning %} -
    +
    @@ -30,7 +30,7 @@
    {% endfor %} {% for server in servers_online %} -
    +
    diff --git a/src/templates/default/static/css/style.min.css b/src/templates/default/static/css/style.min.css index 5bc79370..a0236f19 100644 --- a/src/templates/default/static/css/style.min.css +++ b/src/templates/default/static/css/style.min.css @@ -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 */ \ No newline at end of file diff --git a/src/templates/default/static/css/style.min.css.map b/src/templates/default/static/css/style.min.css.map index e9d01194..39e49a9c 100644 --- a/src/templates/default/static/css/style.min.css.map +++ b/src/templates/default/static/css/style.min.css.map @@ -1,6 +1,6 @@ { "version": 3, - "mappings": "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", + "mappings": "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", "sources": [ "../scss/style.scss" ], diff --git a/src/templates/default/static/scss/style.scss b/src/templates/default/static/scss/style.scss index 6114ad76..35e7ea9b 100644 --- a/src/templates/default/static/scss/style.scss +++ b/src/templates/default/static/scss/style.scss @@ -24,6 +24,10 @@ body { margin-bottom: 80px; } +.container-fluid { + max-width: 1920px; +} + .footer { position: absolute; bottom: 0; From ea33ba07ca786a77669d386f2c8f73e792b4101e Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 18 May 2020 22:05:19 +0200 Subject: [PATCH 59/77] Updated ping check (#919) Check if transmitted and received packets is equal. --- src/psm/Util/Server/Updater/StatusUpdater.php | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index af3a8cdd..47d4abf7 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -179,36 +179,42 @@ class StatusUpdater $max_runs = 1; } $result = null; - // Execute ping + // Choose right ping version, ping6 for IPV6, ping for IPV4 $pingCommand = 'ping6'; $serverIp = $this->server['ip']; if (filter_var($serverIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) { $pingCommand = 'ping'; } + + // execute 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]; + + // 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); + $result = floatval($result[0][1]); + + $this->header = ""; + foreach ($output as $key => $value) { + $this->header .= $value . "\n"; + } $status = true; } else { $this->header = "-"; - $this->error = $output[0]; + foreach ($output as $key => $value) { + $this->header .= $value . "\n"; + } + $this->error = $output[count($output) - 2]; $status = false; } - //Divide by a thousand to convert to milliseconds + // To miliseconds $this->rtime = $result / 1000; // check if server is available and rerun if asked. From 96d0c3fa575710e873d36d5e0e2b9719df6f98e0 Mon Sep 17 00:00:00 2001 From: wienfuchs <44177781+wienfuchs@users.noreply.github.com> Date: Sun, 24 May 2020 23:31:19 +0200 Subject: [PATCH 60/77] use openssl_x509_parse to parse certinfo (avoid literal case conflict) (#931) --- src/psm/Util/Server/Updater/StatusUpdater.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 47d4abf7..3b071fcd 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -431,7 +431,9 @@ class StatusUpdater !empty($this->curl_info['certinfo']) && $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 = round((int)($cert_expiration_date - time()) / 86400); $latest_time = time() + (86400 * $server['ssl_cert_expiry_days']); From 07abc7d2946e9b460ba17d26b65d3b1aa6e7a4c0 Mon Sep 17 00:00:00 2001 From: wienfuchs <44177781+wienfuchs@users.noreply.github.com> Date: Sun, 24 May 2020 23:40:19 +0200 Subject: [PATCH 61/77] use OS specific ping count parameter (#932) * use OS specific ping count parameter * Reorganized and complied with PSR-12 Co-authored-by: TimZ99 --- src/psm/Util/Server/Updater/StatusUpdater.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 3b071fcd..b57d1af6 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -175,19 +175,28 @@ class StatusUpdater */ protected function updatePing($max_runs, $run = 1) { + // Settings if ($max_runs == null || $max_runs > 1) { $max_runs = 1; } - $result = null; - // Choose right ping version, ping6 for IPV6, ping for IPV4 - $pingCommand = 'ping6'; $serverIp = $this->server['ip']; + $pingCommand = 'ping6'; + $ping_count = " -c "; + + $result = null; + + // Choose right ping version, ping6 for IPV6, ping for IPV4 if (filter_var($serverIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) { $pingCommand = 'ping'; } + // Use -n instead of -c for Windows machines + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $ping_count = " -n "; + } + // execute PING - $txt = exec($pingCommand . " -c " . $max_runs . " " . $serverIp . " 2>&1", $output); + $txt = exec($pingCommand . $ping_count . $max_runs . " " . $serverIp . " 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); From f02d55635eff5f3404a429c2998a16c7838736e2 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 25 May 2020 14:39:30 +0200 Subject: [PATCH 62/77] Changed ping6 to ping -6 for windows (#936) Resolving #935. --- src/psm/Util/Server/Updater/StatusUpdater.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index b57d1af6..8b2155dc 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -179,24 +179,24 @@ class StatusUpdater if ($max_runs == null || $max_runs > 1) { $max_runs = 1; } - $serverIp = $this->server['ip']; - $pingCommand = 'ping6'; - $ping_count = " -c "; - + $server_ip = $this->server['ip']; + $ping_command = 'ping'; + $ping_count = "-c"; + $os_is_windows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; $result = null; // Choose right ping version, ping6 for IPV6, ping for IPV4 - if (filter_var($serverIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) { - $pingCommand = 'ping'; + if (filter_var($server_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) { + $ping_command = $os_is_windows ? 'ping -6' : 'ping6'; } // Use -n instead of -c for Windows machines - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - $ping_count = " -n "; + if ($os_is_windows) { + $ping_count = "-n"; } // execute PING - $txt = exec($pingCommand . $ping_count . $max_runs . " " . $serverIp . " 2>&1", $output); + $txt = exec($ping_command . " " . $ping_count . " " . $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); From 7deac0815afb010cce81e964fd710b8c7bcaab25 Mon Sep 17 00:00:00 2001 From: wienfuchs <44177781+wienfuchs@users.noreply.github.com> Date: Mon, 25 May 2020 18:10:10 +0200 Subject: [PATCH 63/77] changing Windows ping routine back to socket usage, leaving Linux changes made (#938) * use openssl_x509_parse to parse certinfo (avoid literal case conflict) * use OS specific ping (CLI/socket) * Moved Windows and non-Windows check to a private class Co-authored-by: TimZ99 --- src/psm/Util/Server/Updater/StatusUpdater.php | 135 ++++++++++++------ 1 file changed, 88 insertions(+), 47 deletions(-) diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index 8b2155dc..88f31ee6 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -176,55 +176,13 @@ class StatusUpdater protected function updatePing($max_runs, $run = 1) { // Settings - if ($max_runs == null || $max_runs > 1) { - $max_runs = 1; - } - $server_ip = $this->server['ip']; - $ping_command = 'ping'; - $ping_count = "-c"; + $max_runs = ($max_runs == null || $max_runs > 1) ? 1 : $max_runs; + $server_ip = escapeshellcmd($this->server['ip']); $os_is_windows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; - $result = null; - // Choose right ping version, ping6 for IPV6, ping for IPV4 - if (filter_var($server_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) { - $ping_command = $os_is_windows ? 'ping -6' : 'ping6'; - } - - // Use -n instead of -c for Windows machines - if ($os_is_windows) { - $ping_count = "-n"; - } - - // execute PING - $txt = exec($ping_command . " " . $ping_count . " " . $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); - $result = floatval($result[0][1]); - - $this->header = ""; - foreach ($output as $key => $value) { - $this->header .= $value . "\n"; - } - $status = true; - } else { - $this->header = "-"; - foreach ($output as $key => $value) { - $this->header .= $value . "\n"; - } - $this->error = $output[count($output) - 2]; - $status = false; - } - // To miliseconds - $this->rtime = $result / 1000; + $status = $os_is_windows ? + $this->pingFromWindowsMachine($server_ip, $max_runs) : + $this->pingFromNonWindowsMachine($server_ip, $max_runs); // check if server is available and rerun if asked. if (!$status && $run < $max_runs) { @@ -466,4 +424,87 @@ class StatusUpdater $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; + } } From 2a15b31ecddbeddd372c92b15d8ee4aa2d4fd5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ma=C5=82ek?= Date: Mon, 25 May 2020 18:12:43 +0200 Subject: [PATCH 64/77] Ability to pan & zoom on charts (#926) * Add ability to pan & zoom on charts * Added map * Added rangeMax and zoom speed Co-authored-by: TimZ99 --- docs/credits.rst | 1 + .../default/module/server/history.tpl.html | 40 +++++++++++++++++++ .../static/plugin/chartjs/plugin-zoom.min.js | 11 +++++ .../static/plugin/hammer/hammer.min.js | 7 ++++ .../static/plugin/hammer/hammer.min.js.map | 1 + 5 files changed, 60 insertions(+) create mode 100755 src/templates/default/static/plugin/chartjs/plugin-zoom.min.js create mode 100755 src/templates/default/static/plugin/hammer/hammer.min.js create mode 100644 src/templates/default/static/plugin/hammer/hammer.min.js.map diff --git a/docs/credits.rst b/docs/credits.rst index 75a1aadc..e1c89471 100644 --- a/docs/credits.rst +++ b/docs/credits.rst @@ -196,3 +196,4 @@ The following libraries are being used by PHP Server Monitor: * PHP-Pushover - https://github.com/kryap/php-pushover * Symfony - https://symfony.com * Random_compat - https://github.com/paragonie/random_compat +* Hammer.js - https://github.com/hammerjs/hammer.js \ No newline at end of file diff --git a/src/templates/default/module/server/history.tpl.html b/src/templates/default/module/server/history.tpl.html index 91027166..163c01d9 100644 --- a/src/templates/default/module/server/history.tpl.html +++ b/src/templates/default/module/server/history.tpl.html @@ -1,5 +1,7 @@ + + {% for graph in graphs %}
    Your browser does not support the canvas element. @@ -72,6 +74,25 @@ 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, + } + } } } }); @@ -133,6 +154,25 @@ 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, + } + } } } }); diff --git a/src/templates/default/static/plugin/chartjs/plugin-zoom.min.js b/src/templates/default/static/plugin/chartjs/plugin-zoom.min.js new file mode 100755 index 00000000..51b054d6 --- /dev/null +++ b/src/templates/default/static/plugin/chartjs/plugin-zoom.min.js @@ -0,0 +1,11 @@ +/*! + * @license + * chartjs-plugin-zoom + * http://chartjs.org/ + * Version: 0.7.7 + * + * Copyright 2020 Chart.js Contributors + * Released under the MIT license + * https://github.com/chartjs/chartjs-plugin-zoom/blob/master/LICENSE.md + */ +!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o(require("chart.js"),require("hammerjs")):"function"==typeof define&&define.amd?define(["chart.js","hammerjs"],o):(e=e||self).ChartZoom=o(e.Chart,e.Hammer)}(this,(function(e,o){"use strict";e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,o=o&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o;var t=e.helpers,n=e.Zoom=e.Zoom||{},a=n.zoomFunctions=n.zoomFunctions||{},i=n.panFunctions=n.panFunctions||{};function m(e,o){var n={};void 0!==e.options.pan&&(n.pan=e.options.pan),void 0!==e.options.zoom&&(n.zoom=e.options.zoom);var a=e.$zoom;o=a._options=t.merge({},[o,n]);var i=a._node,m=o.zoom&&o.zoom.enabled,r=o.zoom.drag;m&&!r?i.addEventListener("wheel",a._wheelHandler):i.removeEventListener("wheel",a._wheelHandler),m&&r?(i.addEventListener("mousedown",a._mouseDownHandler),i.ownerDocument.addEventListener("mouseup",a._mouseUpHandler)):(i.removeEventListener("mousedown",a._mouseDownHandler),i.removeEventListener("mousemove",a._mouseMoveHandler),i.ownerDocument.removeEventListener("mouseup",a._mouseUpHandler))}function r(e){var o=e.$zoom._originalOptions;t.each(e.scales,(function(e){o[e.id]||(o[e.id]=t.clone(e.options))})),t.each(o,(function(t,n){e.scales[n]||delete o[n]}))}function l(e,o,t){return void 0===e||("string"==typeof e?-1!==e.indexOf(o):"function"==typeof e&&-1!==e({chart:t}).indexOf(o))}function s(e,o){if(e.scaleAxes&&e.rangeMax&&!t.isNullOrUndef(e.rangeMax[e.scaleAxes])){var n=e.rangeMax[e.scaleAxes];o>n&&(o=n)}return o}function c(e,o){if(e.scaleAxes&&e.rangeMin&&!t.isNullOrUndef(e.rangeMin[e.scaleAxes])){var n=e.rangeMin[e.scaleAxes];o=c&&s<=u?(i.min=l,i.max=s):lu&&(a=u-r,i.max=u,i.min=m+a)}function v(e,o,t){var n=i[e.type];n&&n(e,o,t)}e.Zoom.defaults=e.defaults.global.plugins.zoom={pan:{enabled:!1,mode:"xy",speed:20,threshold:10},zoom:{enabled:!1,mode:"xy",sensitivity:3,speed:.1}},n.zoomFunctions.category=function(e,o,t,a){var i=e.chart.data.labels,m=e.minIndex,r=i.length-1,l=e.maxIndex,u=a.sensitivity,d=e.isHorizontal()?e.left+e.width/2:e.top+e.height/2,p=e.isHorizontal()?t.x:t.y;n.zoomCumulativeDelta=o>1?n.zoomCumulativeDelta+1:n.zoomCumulativeDelta-1,Math.abs(n.zoomCumulativeDelta)>u&&(n.zoomCumulativeDelta<0?(p>=d?m<=0?l=Math.min(r,l+1):m=Math.max(0,m-1):p=r?m=Math.max(0,m-1):l=Math.min(r,l+1)),n.zoomCumulativeDelta=0):n.zoomCumulativeDelta>0&&(p>=d?m=mm?l=Math.max(m,l-1):l),n.zoomCumulativeDelta=0),e.options.ticks.min=c(a,i[m]),e.options.ticks.max=s(a,i[l]))},n.zoomFunctions.time=function(e,o,t,n){u(e,o,t,n);var a=e.options;a.time&&(a.time.min&&(a.time.min=a.ticks.min),a.time.max&&(a.time.max=a.ticks.max))},n.zoomFunctions.linear=u,n.zoomFunctions.logarithmic=u,n.panFunctions.category=function(e,o,t){var a,i=e.chart.data.labels,m=i.length-1,r=Math.max(e.ticks.length,1),l=t.speed,u=e.minIndex,d=Math.round(e.width/(r*l));n.panCumulativeDelta+=o,u=n.panCumulativeDelta>d?Math.max(0,u-1):n.panCumulativeDelta<-d?Math.min(m-r+1,u+1):u,n.panCumulativeDelta=u!==e.minIndex?0:n.panCumulativeDelta,a=Math.min(m,u+r-1),e.options.ticks.min=c(t,i[u]),e.options.ticks.max=s(t,i[a])},n.panFunctions.time=function(e,o,t){f(e,o,t);var n=e.options;n.time&&(n.time.min&&(n.time.min=n.ticks.min),n.time.max&&(n.time.max=n.ticks.max))},n.panFunctions.linear=f,n.panFunctions.logarithmic=f,n.panCumulativeDelta=0,n.zoomCumulativeDelta=0;var h={id:"zoom",afterInit:function(e){e.resetZoom=function(){r(e);var o=e.$zoom._originalOptions;t.each(e.scales,(function(e){var t=e.options.time,n=e.options.ticks;o[e.id]?(t&&(t.min=o[e.id].time.min,t.max=o[e.id].time.max),n&&(n.min=o[e.id].ticks.min,n.max=o[e.id].ticks.max)):(t&&(delete t.min,delete t.max),n&&(delete n.min,delete n.max))})),e.update()}},beforeUpdate:function(e,o){m(e,o)},beforeInit:function(e,a){e.$zoom={_originalOptions:{}};var i=e.$zoom._node=e.ctx.canvas;m(e,a);var s=e.$zoom._options,c=s.pan&&s.pan.threshold;e.$zoom._mouseDownHandler=function(o){i.addEventListener("mousemove",e.$zoom._mouseMoveHandler),e.$zoom._dragZoomStart=o},e.$zoom._mouseMoveHandler=function(o){e.$zoom._dragZoomStart&&(e.$zoom._dragZoomEnd=o,e.update(0))},e.$zoom._mouseUpHandler=function(o){if(e.$zoom._dragZoomStart){i.removeEventListener("mousemove",e.$zoom._mouseMoveHandler);var t=e.$zoom._dragZoomStart,n=t.target.getBoundingClientRect().left,a=Math.min(t.clientX,o.clientX)-n,m=Math.max(t.clientX,o.clientX)-n,r=t.target.getBoundingClientRect().top,c=Math.min(t.clientY,o.clientY)-r,u=m-a,d=Math.max(t.clientY,o.clientY)-r-c;e.$zoom._dragZoomStart=null,e.$zoom._dragZoomEnd=null;var f=s.zoom&&s.zoom.threshold||0;if(!(u<=f&&d<=f)){var v=e.chartArea,h=e.$zoom._options.zoom,x=v.right-v.left,g=l(h.mode,"x",e)&&u?1+(x-u)/x:1,z=v.bottom-v.top,y=l(h.mode,"y",e);p(e,g,y&&d?1+(z-d)/z:1,{x:(a-v.left)/(1-u/x)+v.left,y:(c-v.top)/(1-d/z)+v.top},void 0,h.drag.animationDuration),"function"==typeof h.onZoomComplete&&h.onZoomComplete({chart:e})}}};var u=null;if(e.$zoom._wheelHandler=function(o){if(o.cancelable&&o.preventDefault(),void 0!==o.deltaY){var t=o.target.getBoundingClientRect(),n={x:o.clientX-t.left,y:o.clientY-t.top},a=e.$zoom._options.zoom,i=a.speed;o.deltaY>=0&&(i=-i),p(e,1+i,1+i,n),clearTimeout(u),u=setTimeout((function(){"function"==typeof a.onZoomComplete&&a.onZoomComplete({chart:e})}),250)}},o){var d,f=new o.Manager(i);f.add(new o.Pinch),f.add(new o.Pan({threshold:c}));var h=function(o){var t=1/d*o.scale,n=o.target.getBoundingClientRect(),a={x:o.center.x-n.left,y:o.center.y-n.top},i=Math.abs(o.pointers[0].clientX-o.pointers[1].clientX),m=Math.abs(o.pointers[0].clientY-o.pointers[1].clientY),r=i/m;p(e,t,t,a,r>.3&&r<1.7?"xy":i>m?"x":"y");var l=e.$zoom._options.zoom;"function"==typeof l.onZoomComplete&&l.onZoomComplete({chart:e}),d=o.scale};f.on("pinchstart",(function(){d=1})),f.on("pinch",h),f.on("pinchend",(function(e){h(e),d=null,n.zoomCumulativeDelta=0}));var x=null,g=null,z=!1,y=function(o){if(null!==x&&null!==g){z=!0;var n=o.deltaX-x,a=o.deltaY-g;x=o.deltaX,g=o.deltaY,function(e,o,n){r(e);var a=e.$zoom._options.pan;if(a.enabled){var i="function"==typeof a.mode?a.mode({chart:e}):a.mode;t.each(e.scales,(function(t){t.isHorizontal()&&l(i,"x",e)&&0!==o?(a.scaleAxes="x",v(t,o,a)):!t.isHorizontal()&&l(i,"y",e)&&0!==n&&(a.scaleAxes="y",v(t,n,a))})),e.update(0),"function"==typeof a.onPan&&a.onPan({chart:e})}}(e,n,a)}};f.on("panstart",(function(e){x=0,g=0,y(e)})),f.on("panmove",y),f.on("panend",(function(){x=null,g=null,n.panCumulativeDelta=0,setTimeout((function(){z=!1}),500);var o=e.$zoom._options.pan;"function"==typeof o.onPanComplete&&o.onPanComplete({chart:e})})),e.$zoom._ghostClickHandler=function(e){z&&e.cancelable&&(e.stopImmediatePropagation(),e.preventDefault())},i.addEventListener("click",e.$zoom._ghostClickHandler),e._mc=f}},beforeDatasetsDraw:function(e){var o=e.ctx;if(e.$zoom._dragZoomEnd){var t=function(e){for(var o=e.scales,t=Object.keys(o),n=0;n0&&(o.lineWidth=v.borderWidth,o.strokeStyle=v.borderColor||"rgba(225,225,225)",o.strokeRect(m,s,p,f)),o.restore()}},destroy:function(e){if(e.$zoom){var o=e.$zoom,t=o._node;t.removeEventListener("mousedown",o._mouseDownHandler),t.removeEventListener("mousemove",o._mouseMoveHandler),t.ownerDocument.removeEventListener("mouseup",o._mouseUpHandler),t.removeEventListener("wheel",o._wheelHandler),t.removeEventListener("click",o._ghostClickHandler),delete e.$zoom;var n=e._mc;n&&(n.remove("pinchstart"),n.remove("pinch"),n.remove("pinchend"),n.remove("panstart"),n.remove("pan"),n.remove("panend"),n.destroy())}}};return e.plugins.register(h),h})); \ No newline at end of file diff --git a/src/templates/default/static/plugin/hammer/hammer.min.js b/src/templates/default/static/plugin/hammer/hammer.min.js new file mode 100755 index 00000000..34a8c86f --- /dev/null +++ b/src/templates/default/static/plugin/hammer/hammer.min.js @@ -0,0 +1,7 @@ +/*! Hammer.JS - v2.0.7 - 2016-04-22 + * http://hammerjs.github.io/ + * + * Copyright (c) 2016 Jorik Tangelder; + * Licensed under the MIT license */ +!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};b.eventType!==Ea&&f.eventType!==Ga||(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ea|Fa)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ea)for(e=0;e-1&&d.splice(a,1)};setTimeout(e,cb)}}function U(a){for(var b=a.srcEvent.clientX,c=a.srcEvent.clientY,d=0;d=f&&db>=g)return!0}return!1}function V(a,b){this.manager=a,this.set(b)}function W(a){if(p(a,jb))return jb;var b=p(a,kb),c=p(a,lb);return b&&c?jb:b||c?b?kb:lb:p(a,ib)?ib:hb}function X(){if(!fb)return!1;var b={},c=a.CSS&&a.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(d){b[d]=c?a.CSS.supports("touch-action",d):!0}),b}function Y(a){this.options=la({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=nb,this.simultaneous={},this.requireFail=[]}function Z(a){return a&sb?"cancel":a&qb?"end":a&pb?"move":a&ob?"start":""}function $(a){return a==Ma?"down":a==La?"up":a==Ja?"left":a==Ka?"right":""}function _(a,b){var c=b.manager;return c?c.get(a):a}function aa(){Y.apply(this,arguments)}function ba(){aa.apply(this,arguments),this.pX=null,this.pY=null}function ca(){aa.apply(this,arguments)}function da(){Y.apply(this,arguments),this._timer=null,this._input=null}function ea(){aa.apply(this,arguments)}function fa(){aa.apply(this,arguments)}function ga(){Y.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ha(a,b){return b=b||{},b.recognizers=l(b.recognizers,ha.defaults.preset),new ia(a,b)}function ia(a,b){this.options=la({},ha.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=a,this.input=y(this),this.touchAction=new V(this,this.options.touchAction),ja(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function ja(a,b){var c=a.element;if(c.style){var d;g(a.options.cssProps,function(e,f){d=u(c.style,f),b?(a.oldCssProps[d]=c.style[d],c.style[d]=e):c.style[d]=a.oldCssProps[d]||""}),b||(a.oldCssProps={})}}function ka(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var la,ma=["","webkit","Moz","MS","ms","o"],na=b.createElement("div"),oa="function",pa=Math.round,qa=Math.abs,ra=Date.now;la="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;ch&&(b.push(a),h=b.length-1):e&(Ga|Ha)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Za={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},$a="touchstart",_a="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Za[a.type];if(b===Ea&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ga|Ha)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}}});var ab={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},bb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=ab[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}});var cb=2500,db=25;i(R,x,{handler:function(a,b,c){var d=c.pointerType==za,e=c.pointerType==Ba;if(!(e&&c.sourceCapabilities&&c.sourceCapabilities.firesTouchEvents)){if(d)S.call(this,b,c);else if(e&&U.call(this,c))return;this.callback(a,b,c)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var eb=u(na.style,"touchAction"),fb=eb!==d,gb="compute",hb="auto",ib="manipulation",jb="none",kb="pan-x",lb="pan-y",mb=X();V.prototype={set:function(a){a==gb&&(a=this.compute()),fb&&this.manager.element.style&&mb[a]&&(this.manager.element.style[eb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),W(a.join(" "))},preventDefaults:function(a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,jb)&&!mb[jb],f=p(d,lb)&&!mb[lb],g=p(d,kb)&&!mb[kb];if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}return g&&f?void 0:e||f&&c&Na||g&&c&Oa?this.preventSrc(b):void 0},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var nb=1,ob=2,pb=4,qb=8,rb=qb,sb=16,tb=32;Y.prototype={defaults:{},set:function(a){return la(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=_(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=_(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=_(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;qb>d&&b(c.options.event+Z(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=qb&&b(c.options.event+Z(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=tb)},canEmit:function(){for(var a=0;af?Ja:Ka,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ia:0>g?La:Ma,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return aa.prototype.attrTest.call(this,a)&&(this.state&ob||!(this.state&ob)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i(ca,aa,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&ob)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(da,Y,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[hb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ga|Ha)&&!f)this.reset();else if(a.eventType&Ea)this.reset(),this._timer=e(function(){this.state=rb,this.tryEmit()},b.time,this);else if(a.eventType&Ga)return rb;return tb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===rb&&(a&&a.eventType&Ga?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=ra(),this.manager.emit(this.options.event,this._input)))}}),i(ea,aa,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&ob)}}),i(fa,aa,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Na|Oa,pointers:1},getTouchAction:function(){return ba.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Na|Oa)?b=a.overallVelocity:c&Na?b=a.overallVelocityX:c&Oa&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&qa(b)>this.options.velocity&&a.eventType&Ga},emit:function(a){var b=$(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ga,Y,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ib]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance Date: Tue, 26 May 2020 01:06:57 +0530 Subject: [PATCH 65/77] Installer checks for needed PHP functions (#939) Closes #903. --- .../Install/Controller/InstallController.php | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index 8acb471f..f51de403 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -101,6 +101,53 @@ class InstallController extends AbstractController if (!in_array('mysql', \PDO::getAvailableDrivers())) { $errors++; $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')) { $this->addMessage( From 5ecdc75dcf3c156d6694ac261a6e04df560d6134 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 May 2020 16:47:48 +0000 Subject: [PATCH 66/77] Bump phpmailer/phpmailer from 6.1.3 to 6.1.6 (#941) --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 1ffbcc76..6ce79bb8 100644 --- a/composer.lock +++ b/composer.lock @@ -160,16 +160,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v6.1.3", + "version": "v6.1.6", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "a25ae38e03de4ee4031725498a600012364787c7" + "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a25ae38e03de4ee4031725498a600012364787c7", - "reference": "a25ae38e03de4ee4031725498a600012364787c7", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3", + "reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3", "shasum": "" }, "require": { @@ -218,7 +218,7 @@ } ], "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", From dd915ae97b99165c8d4fc138599354469300ca0e Mon Sep 17 00:00:00 2001 From: TimZ99 Date: Wed, 12 Aug 2020 12:16:50 +0200 Subject: [PATCH 67/77] Updated jQuery to 3.5.1 Fixes #972. jQuery below 3.5.0 is vulnerable to code injection even when inputs are sanitised. Please see: [CVE-2020-11022](https://nvd.nist.gov/vuln/detail/CVE-2020-11022) [CVE-2020-11023](https://nvd.nist.gov/vuln/detail/CVE-2020-11023) --- src/templates/default/main/body.tpl.html | 2 +- src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js | 2 -- src/templates/default/static/plugin/jquery/jquery-3.5.1.min.js | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js create mode 100644 src/templates/default/static/plugin/jquery/jquery-3.5.1.min.js diff --git a/src/templates/default/main/body.tpl.html b/src/templates/default/main/body.tpl.html index 7a1c3523..75cb8396 100644 --- a/src/templates/default/main/body.tpl.html +++ b/src/templates/default/main/body.tpl.html @@ -74,7 +74,7 @@ {% endblock %} {% endif %} - + diff --git a/src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js b/src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js deleted file mode 100644 index 49d1fcfb..00000000 --- a/src/templates/default/static/plugin/jquery/jquery-3.3.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w(" - + + diff --git a/src/templates/default/module/config/config.tpl.html b/src/templates/default/module/config/config.tpl.html index a9c4f6c0..ffb36a54 100644 --- a/src/templates/default/module/config/config.tpl.html +++ b/src/templates/default/module/config/config.tpl.html @@ -32,6 +32,11 @@ role="tab" aria-controls="config-jabber" aria-selected="{% if jabber_active %}true{% else %}false{% endif %}">{{ label_tab_jabber }} +
    +
    +
    + {{ label_settings_discord }} + + {{ macro.input_checkbox("discord_status", "discord_status[]", label_discord_status, discord_status_checked) }} + + {{ macro.input_checkbox("log_discord", "log_discord[]", label_log_discord, log_discord_checked) }} + {{ macro.button_test("testDiscord", label_test) }} + {{ macro.input_hidden("test_discord", "0") }} + {{ macro.button_save("discord_submit", label_save) }} +
    +
    {{ label_settings_pushover }} diff --git a/src/templates/default/module/server/server/list.tpl.html b/src/templates/default/module/server/server/list.tpl.html index c32c86b1..c0b62b89 100644 --- a/src/templates/default/module/server/server/list.tpl.html +++ b/src/templates/default/module/server/server/list.tpl.html @@ -63,19 +63,22 @@ {% endif %} {% if server.telegram|lower == 'yes' and config.telegram|lower%} - - - T - + {% endif %} {% if server.jabber|lower == 'yes'%} - - J - + + J + + {% endif %} + {% if server.discord|lower == 'yes' and config.discord|lower %} + {% endif %} {% if server.webhook|lower == 'yes' and config.webhook|lower %} - + + + W + {% endif %} {% if user_level == 10 %} diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index 0cefdd98..286a05d3 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -144,6 +144,8 @@ {{ 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("jabber", "jabber", label_send_jabber, edit_jabber_selected, label_yes, label_no, warning_jabber, label_warning_jabber) }} + + {{ macro.input_select_monitoring("discord", "discord", label_send_discord, edit_discord_selected, label_yes, label_no, warning_discord, label_warning_discord) }} {{ macro.input_select_monitoring("webhook", "webhook", label_send_webhook, edit_webhook_selected, label_yes, label_no, warning_webhook, label_warning_webhook) }}
    diff --git a/src/templates/default/module/server/server/view.tpl.html b/src/templates/default/module/server/server/view.tpl.html index 154ea26c..e6d37498 100644 --- a/src/templates/default/module/server/server/view.tpl.html +++ b/src/templates/default/module/server/server/view.tpl.html @@ -309,6 +309,19 @@ {% endif %} +
  • + {{ label_discord }}: + {% if discord|lower == 'yes' %} + + + {% elseif discord|lower == 'no' %} + + + {% else %} + + + {% endif %} +
  • {{ label_pushover }}: {% if pushover|lower == 'yes' %} diff --git a/src/templates/default/module/user/profile.tpl.html b/src/templates/default/module/user/profile.tpl.html index abed8ad7..3cb8f315 100644 --- a/src/templates/default/module/user/profile.tpl.html +++ b/src/templates/default/module/user/profile.tpl.html @@ -34,7 +34,7 @@

    {{ label_telegram_description|raw }}

    {{ 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) }} @@ -46,6 +46,11 @@ {{ macro.input_field("text", "jabber", null, "jabber", label_jabber, jabber, label_jabber, "255", "jabber_help", label_jabber_description) }} + +
    + {{ label_discord }} + {{ macro.input_field("text", "discord", null, "discord", label_discord, discord, "https://discordapp.com/api/webhooks/xxxxx", "255", "discord_help", label_discord_description) }} +
    {{ label_webhook }} @@ -56,4 +61,4 @@ {{ 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) }}
    {{ macro.button_save(null, label_save) }} - \ No newline at end of file + diff --git a/src/templates/default/module/user/user/update.tpl.html b/src/templates/default/module/user/user/update.tpl.html index bde98390..932700e1 100644 --- a/src/templates/default/module/user/user/update.tpl.html +++ b/src/templates/default/module/user/user/update.tpl.html @@ -17,6 +17,8 @@ {{ macro.input_field("email", "email", null, "email", label_email, edit_value_email, null, "255") }} {{ macro.input_field("tel", "mobile", null, "mobile", label_mobile, edit_value_mobile, null, "20") }} + + {{ macro.input_field("text", "discord", null, "discord", label_discord, edit_value_discord, null, "255") }} {{ macro.input_field("text", "webhook_url", null, "webhook_url", label_webhook_url, edit_value_webhook_url, null, "255") }} From ba0fa251e9f9dded91ec72bec02a12cb47c13592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Farr=C3=A9?= Date: Fri, 14 Aug 2020 17:56:13 +0200 Subject: [PATCH 77/77] Update Octopush.php (#975) With the low cost default value, SMS are sometimes received many hours after. For a monitoring software, this has no sense, we need to be sure to receive the alert by SMS instantly to repair the problem as quick as possible. Otherwise, SMS is useless, email is free and good enough. Moreover, the price difference between low cost and premium is small. --- src/psm/Txtmsg/Octopush.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/psm/Txtmsg/Octopush.php b/src/psm/Txtmsg/Octopush.php index 5d1731d0..f14eb464 100644 --- a/src/psm/Txtmsg/Octopush.php +++ b/src/psm/Txtmsg/Octopush.php @@ -59,7 +59,7 @@ class Octopush extends Core { $error = ""; $success = 1; - $smsType = "XXX"; //FR = premium, WWW = world, XXX = Low cost + $smsType = "FR"; //FR = premium, WWW = world, XXX = Low cost $recipients = join(',', $this->recipients);