initial code comit
62
system/action/index.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../settings.php');
|
||||
|
||||
$action = filter_input(INPUT_GET, 'do', FILTER_SANITIZE_STRING);
|
||||
|
||||
if ($action === 'reboot') {
|
||||
// echo shell_exec("systemctl halt -i");
|
||||
if (REBOOT_ENABLED) {
|
||||
echo $lang->translate('reboot_in_progress') . '<br>';
|
||||
echo shell_exec('sudo shutdown -r');
|
||||
} else {
|
||||
echo $lang->translate('reboot_prohibited') . '<br>';
|
||||
}
|
||||
} else if ($action === 'shutdown') {
|
||||
if (SHUTDOWN_ENABLED) {
|
||||
echo $lang->translate('shutdown_in_progress') . '<br>';
|
||||
echo shell_exec('sudo halt -p');
|
||||
} else {
|
||||
echo $lang->translate('shutdown_prohibited') . '<br>';
|
||||
}
|
||||
} else if ($action === 'setup') {
|
||||
$def_lang = filter_input(INPUT_GET, 'default_language', FILTER_SANITIZE_STRING);
|
||||
$dim_on_create = filter_input(INPUT_GET, 'dim_on_create', FILTER_SANITIZE_NUMBER_INT) == 1;
|
||||
$chk_f_rights = filter_input(INPUT_GET, 'chk_files_rights', FILTER_SANITIZE_NUMBER_INT) == 1;
|
||||
$max_hdd_temp = filter_input(INPUT_GET, 'max_hdd_temp', FILTER_SANITIZE_NUMBER_INT);
|
||||
$chk_hdd_temp_int = filter_input(INPUT_GET, 'chk_temp_interval', FILTER_SANITIZE_NUMBER_INT);
|
||||
$chk_smart_int = filter_input(INPUT_GET, 'chk_smart_interval', FILTER_SANITIZE_NUMBER_INT);
|
||||
$chk_users_online_int = filter_input(INPUT_GET, 'chk_users_online_interval', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
$user_cfg->set_value('lang', $def_lang);
|
||||
$user_cfg->set_value('dim_on_create', $dim_on_create);
|
||||
$user_cfg->set_value('check_files_rights', $chk_f_rights);
|
||||
$user_cfg->set_value('max_hdd_temp', $max_hdd_temp);
|
||||
$user_cfg->set_value('check_hdd_temp_interval', $chk_hdd_temp_int);
|
||||
$user_cfg->set_value('check_smart_interval', $chk_smart_int);
|
||||
$user_cfg->set_value('check_users_online_interval', $chk_users_online_int);
|
||||
|
||||
$uc_saved = $user_cfg->save();
|
||||
|
||||
/* Apps list */
|
||||
$enabled_apps = array();
|
||||
foreach ($_GET["app_caption"] as $item => $val) {
|
||||
if (isset($_GET["app_enabled"][$item]) && (bool)$_GET["app_enabled"][$item]) {
|
||||
$app_cap = filter_var($_GET["app_caption"][$item], FILTER_SANITIZE_STRING);
|
||||
$app_name = filter_var($_GET["app_name"][$item], FILTER_SANITIZE_STRING);
|
||||
$enabled_apps[$app_cap] = $app_name;
|
||||
}
|
||||
}
|
||||
$app = new \CAI\CAICP\Applications(CP_ROOT_REL);
|
||||
$app->set($enabled_apps);
|
||||
$apps_saved = $app->save();
|
||||
|
||||
if ($uc_saved && $apps_saved) {
|
||||
echo 'true';
|
||||
} else {
|
||||
echo 'false';
|
||||
}
|
||||
}
|
||||
11
system/apps/apps.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"Plex" : "plex",
|
||||
"Transmission" : "transmission",
|
||||
"Resilio sync" : "rslsync",
|
||||
"NextCloud" : "nextcloud",
|
||||
"OwnCloud" : "owncloud",
|
||||
"Files downloader" : "cai_downloader",
|
||||
"OpenFire" : "openfire",
|
||||
"phpMyAdmin" : "phpmyadmin",
|
||||
"phpPgAdmin" : "phppgadmin"
|
||||
}
|
||||
16
system/apps/cai_downloader/app.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"app_name" : "app_cai_downloader",
|
||||
"caption" : "Files downloader",
|
||||
"version" : "1.0.20170705",
|
||||
"author" : "Alexander I. Chebykin",
|
||||
"http_uri" : "system/apps/cai_downloader/",
|
||||
"use_http" : true,
|
||||
"https_uri" : "system/apps/cai_downloader/",
|
||||
"use_https" : true,
|
||||
"frame_support" : true,
|
||||
"require_php" : true,
|
||||
"require" : [
|
||||
{"data" : "php"},
|
||||
{"data" : "curl"}
|
||||
]
|
||||
}
|
||||
32
system/apps/cai_downloader/css/downloader.css
Normal file
@@ -0,0 +1,32 @@
|
||||
.full_width {width: 100%}
|
||||
.hidden {opacity: 0;}
|
||||
.td_label {width: 100px;}
|
||||
.del_rec {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#in_submit {margin: 10px auto;}
|
||||
#div_download,
|
||||
#div_log,
|
||||
.div_log_rec {transition: all 0.5s ease-out 0.1s;}
|
||||
|
||||
.div_log_rec span {margin-right: 20px;}
|
||||
|
||||
fieldset {
|
||||
border-width: 1px;
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 5px 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background: linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0, 0));
|
||||
}
|
||||
69
system/apps/cai_downloader/exec/index.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* CAI CP v.1
|
||||
*
|
||||
* @module : Download application
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2016-2017 Alexander I. Chebykin
|
||||
* @version : 1.0
|
||||
* @build date : 2017-07-17
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../../../settings.php');
|
||||
|
||||
/* Places to store files by type */
|
||||
$ParentDir = array('.gif' => 'images/_animations/',
|
||||
'.jpg' => 'images/', '.jpeg' => 'images/', '.png' => 'images/',
|
||||
'.tif' => 'images/', '.tiff' => 'images/',
|
||||
'.avi' => 'video/', '.flv' => 'video/', '.mkv' => 'video/',
|
||||
'.mp4' => 'video/', '.mpeg' => 'video/', '.mpg' => 'video/',
|
||||
'.exe' => 'soft/', '.msi' => 'soft/',
|
||||
'.7z' => 'archives/', '.iso' => 'archives/', '.rar' => 'archives/',
|
||||
'.tar' => 'archives/', '.zip' => 'archives/');
|
||||
/* Filter parameters */
|
||||
$Dir = str_replace(array('.', '/', '~', '\\', ' ', '%'),
|
||||
'_',
|
||||
filter_input(INPUT_POST, 'dir', FILTER_SANITIZE_STRING)
|
||||
);
|
||||
$Overwrite = (int)filter_input(INPUT_POST, 'overwrite', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
$URI = filter_input(INPUT_POST, 'uri', FILTER_SANITIZE_URL);
|
||||
|
||||
$SubstrPos = 0;
|
||||
$PDir = '';
|
||||
foreach ($ParentDir as $Key => $Val) {
|
||||
if (mb_stripos($URI, $Key) !== false){
|
||||
$SPos = mb_stripos($URI, $Key);
|
||||
if ($SubstrPos == 0) {
|
||||
$SubstrPos = $SPos;
|
||||
$PDir = $Val;
|
||||
} else {
|
||||
if ($SubstrPos < $Pos && $Pos > 0) {
|
||||
$SubstrPos = $Pos;
|
||||
$PDir = $Val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($Overwrite !== 1 && file_exists(str_replace('\ ', ' ', FILE_DOWNLOAD_DIR) . $PDir . $Dir . '/')) {
|
||||
$i = 1;
|
||||
while (file_exists(str_replace('\ ', ' ', FILE_DOWNLOAD_DIR) . $PDir . $Dir . '/' . $i)) {
|
||||
$i++;
|
||||
}
|
||||
$Dir .= '/' . $i;
|
||||
}
|
||||
|
||||
echo exec(sprintf('bash -c "%s > /dev/null 2>&1 &"',
|
||||
sprintf("./scripts/app.sh %s %s",
|
||||
FILE_DOWNLOAD_DIR . $PDir . $Dir,
|
||||
$URI)
|
||||
)
|
||||
);
|
||||
echo '[langDownloadStarted]';
|
||||
3
system/apps/cai_downloader/exec/scripts/app.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#! /bin/bash
|
||||
mkdir -p "$1" && cd "$1" && curl -L -S -O $2 >> download.log 2>&1 &
|
||||
# mkdir -p "$1" && cd "$1" && curl -L -O $2 > /dev/null 2>&1 &
|
||||
BIN
system/apps/cai_downloader/icon.png
Normal file
|
After Width: | Height: | Size: 332 KiB |
29
system/apps/cai_downloader/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Files downloader app for CAI CP</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="css/downloader.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="div_download" class="hidden">
|
||||
<form id="frm_submit" method="post" action="exec/">
|
||||
<table class="full_width">
|
||||
<tr><td class="td_label"><label id="lbl_uri" for="uri">[langURI]: </label></td><td><input class="full_width" name="uri" id="uri" type="url" placeholder="http://domain.local/image[1-10].jpg" autofocus required></td></tr>
|
||||
<tr><td class="td_label"><label id="lbl_dir" for="dir">[langDir]: </label></td><td><input class="full_width" name="dir" id="dir" type="text"></td></tr>
|
||||
</table>
|
||||
<input id="lang" name="lang" type="hidden" value="en">
|
||||
<input name="overwrite" id="overwrite" type="checkbox" value="1"><label id="lbl_overwrite" for="overwrite"> [langOverwrite]</label><br>
|
||||
<input id="in_submit" type="submit" value="[langGo]">
|
||||
</form>
|
||||
</div>
|
||||
<div id="div_log" class="hidden">
|
||||
<fieldset id="fs_log">
|
||||
<legend id="lgn_log">Log</legend>
|
||||
<div id="div_log_recs"></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<script src="js/downloader.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
206
system/apps/cai_downloader/js/downloader.js
Normal file
@@ -0,0 +1,206 @@
|
||||
// MIT License:
|
||||
//
|
||||
// Copyright (c) 2016-2017, Alexander I. Chebykin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* CAI CP v.1
|
||||
*
|
||||
* @module : Downloader app
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2016-2017 Alexander I. Chebykin
|
||||
* @version : 1.0
|
||||
* @build date : 2017-06-05
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Return GET parameter from parent page
|
||||
*
|
||||
* @param {string} key Key name
|
||||
*
|
||||
* returns {string}
|
||||
*/
|
||||
function $_PARENT_GET(key) {
|
||||
// var s = window.location.search;
|
||||
var s = (window.location !== window.parent.location)
|
||||
? document.referrer
|
||||
: document.location.href;
|
||||
|
||||
s = s.match(new RegExp(key + '=([^&=]+)'));
|
||||
|
||||
return s ? s[1] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return GET parameter
|
||||
*
|
||||
* @param {string} key Key name
|
||||
*
|
||||
* returns {string}
|
||||
*/
|
||||
function $_GET(key) {
|
||||
// var s = window.location.search;
|
||||
var s = document.referrer;
|
||||
|
||||
s = s.match(new RegExp(key + '=([^&=]+)'));
|
||||
|
||||
return s ? s[1] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download system constructor
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function DownloadSystem() {
|
||||
this.locales = 'en ru';
|
||||
this.lang = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Download system initialization
|
||||
*
|
||||
* @param {string} lang Language code. Ex: en, ru etc.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
DownloadSystem.prototype.init = function (lang) {
|
||||
var dl_instance = this,
|
||||
json_file = 'locale/',
|
||||
request = new XMLHttpRequest();
|
||||
|
||||
if (this.check_locale(lang)) {
|
||||
json_file += lang + '.json';
|
||||
} else {
|
||||
json_file += 'en.json';
|
||||
}
|
||||
|
||||
if (document.getElementById('lang') !== null) {
|
||||
document.getElementById('lang').value = lang;
|
||||
}
|
||||
|
||||
if ($_GET('overwrite') && (document.getElementById('overwrite') !== null)) {
|
||||
document.getElementById('overwrite').checked = true;
|
||||
}
|
||||
|
||||
request.open('GET', json_file);
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
dl_instance.lang = JSON.parse(this.responseText);
|
||||
|
||||
document.getElementById('lbl_uri').textContent = dl_instance.lang.uri + ': ';
|
||||
document.getElementById('lbl_dir').textContent = dl_instance.lang.dir + ': ';
|
||||
document.getElementById('lbl_overwrite').textContent = dl_instance.lang.overwrite;
|
||||
document.getElementById('lgn_log').textContent = dl_instance.lang.log;
|
||||
document.getElementById('in_submit').value = dl_instance.lang.go;
|
||||
document.getElementById('div_download').classList.toggle('hidden');
|
||||
document.getElementById('div_log').classList.toggle('hidden');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Check locale support
|
||||
*
|
||||
* @param {string} locale Locale code to check. Ex: en, ru etc.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
DownloadSystem.prototype.check_locale = function (locale) {
|
||||
return this.locales.indexOf(locale.toLowerCase()) !== -1;
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/**
|
||||
* Initialize download object
|
||||
*/
|
||||
var download = new DownloadSystem();
|
||||
|
||||
if ($_GET('lang')) {
|
||||
download.init($_GET('lang'));
|
||||
} else if ($_PARENT_GET('lang')) {
|
||||
download.init($_PARENT_GET('lang'));
|
||||
} else {
|
||||
download.init('en');
|
||||
}
|
||||
|
||||
document.getElementById('frm_submit').onsubmit = function () {
|
||||
var xhr = new XMLHttpRequest(),
|
||||
msg,
|
||||
cur_date = new Date();
|
||||
|
||||
xhr.onload = function () {
|
||||
var log_rec = document.createElement('div'),
|
||||
log_span = document.createElement('span'),
|
||||
img_del = document.createElement('img'),
|
||||
hr = document.createElement('hr');
|
||||
|
||||
log_rec.classList.add('div_log_rec');
|
||||
log_rec.classList.add('hidden');
|
||||
|
||||
img_del.classList.add('del_rec');
|
||||
img_del.src = '../../../gfx/buttons/delete.png';
|
||||
img_del.title = download.lang.del_log_rec;
|
||||
|
||||
img_del.addEventListener('click', function () {
|
||||
this.parentNode.parentNode.removeChild(this.parentNode);
|
||||
});
|
||||
|
||||
log_rec.appendChild(log_span);
|
||||
log_rec.appendChild(img_del);
|
||||
log_rec.appendChild(hr);
|
||||
|
||||
// document.getElementById('div_log_recs').appendChild(log_rec);
|
||||
document.getElementById('div_log_recs').insertBefore(log_rec,
|
||||
document.getElementById('div_log_recs').childNodes[0]);
|
||||
|
||||
if (xhr.responseText === '[langDownloadStarted]') {
|
||||
msg = download.lang.download_started;
|
||||
} else {
|
||||
msg = xhr.responseText;
|
||||
}
|
||||
|
||||
log_span.appendChild(document.createTextNode(
|
||||
cur_date.toLocaleString() + ': ' +
|
||||
document.getElementById('dir').value + ' (' +
|
||||
document.getElementById('uri').value + '): ' +
|
||||
msg
|
||||
)
|
||||
);
|
||||
|
||||
log_rec.classList.toggle('hidden');
|
||||
};
|
||||
|
||||
xhr.open(this.method, this.action, true);
|
||||
xhr.send(new FormData(this));
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}());
|
||||
9
system/apps/cai_downloader/locale/en.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"uri" : "URI",
|
||||
"dir" : "Directory",
|
||||
"overwrite" : "Overwrite",
|
||||
"go" : "Go!",
|
||||
"log" : "Log",
|
||||
"del_log_rec" : "Delete log record",
|
||||
"download_started" : "Download started"
|
||||
}
|
||||
9
system/apps/cai_downloader/locale/ru.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"uri" : "URI",
|
||||
"dir" : "Директория",
|
||||
"overwrite" : "Перезаписать",
|
||||
"go" : "Поехали!",
|
||||
"log" : "Журнал",
|
||||
"del_log_rec" : "Удалить запись журнала",
|
||||
"download_started" : "Загрузка начата"
|
||||
}
|
||||
4
system/apps/cai_downloader/readme/en.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Settings
|
||||
========
|
||||
Set $DataDir variable value to download dir in exec/index.php file.
|
||||
Grant write access for this directory to web server.
|
||||
4
system/apps/cai_downloader/readme/ru.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Настройка
|
||||
=========
|
||||
В файле exec/index.php задайте каталог для загрузки файлов в переменной $DataDir.
|
||||
Права на каталог должны позволять запись веб-серверу.
|
||||
16
system/apps/index.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../settings.php');
|
||||
|
||||
$action = filter_input(INPUT_GET, 'do', FILTER_SANITIZE_STRING);
|
||||
|
||||
if ($action === 'get_apps') {
|
||||
$apps = new \CAI\CAICP\Applications(CP_ROOT_REL);
|
||||
echo $apps->get_avail_json();
|
||||
} elseif ($action === 'get_enabled_apps') {
|
||||
$apps = new \CAI\CAICP\Applications(CP_ROOT_REL);
|
||||
echo $apps->get_enabled_json();
|
||||
}
|
||||
12
system/apps/nextcloud/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_nextcloud",
|
||||
"caption" : "NextCloud",
|
||||
"http_uri" : "",
|
||||
"use_http" : false,
|
||||
"https_uri" : "https://[server_name]/",
|
||||
"use_https" : true,
|
||||
"frame_support" : false,
|
||||
"require" : [
|
||||
{"data" : "php"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/nextcloud/icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
12
system/apps/openfire/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_openfire",
|
||||
"caption" : "OpenFire",
|
||||
"http_uri" : "http://[server_name]:9090/",
|
||||
"use_http" : true,
|
||||
"https_uri" : "https://[server_name]:9091/",
|
||||
"use_https" : true,
|
||||
"frame_support" : false,
|
||||
"require" : [
|
||||
{"data" : "openfire"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/openfire/icon.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
12
system/apps/owncloud/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_owncloud",
|
||||
"caption" : "OwnCloud",
|
||||
"http_uri" : "http://[server_name]/owncloud/",
|
||||
"use_http" : true,
|
||||
"https_uri" : "https://[server_name]/owncloud/",
|
||||
"use_https" : true,
|
||||
"frame_support" : true,
|
||||
"require" : [
|
||||
{"data" : "php"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/owncloud/icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
12
system/apps/phpmyadmin/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_phpmyadmin",
|
||||
"caption" : "phpMyAdmin",
|
||||
"http_uri" : "",
|
||||
"use_http" : true,
|
||||
"https_uri" : "https://[server_name]/phpMyAdmin/",
|
||||
"use_https" : true,
|
||||
"frame_support" : false,
|
||||
"require" : [
|
||||
{"data" : "php"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/phpmyadmin/icon.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
12
system/apps/phppgadmin/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_phppgadmin",
|
||||
"caption" : "phpPgAdmin",
|
||||
"http_uri" : "",
|
||||
"use_http" : true,
|
||||
"https_uri" : "https://[server_name]/phpPgAdmin/",
|
||||
"use_https" : true,
|
||||
"frame_support" : true,
|
||||
"require" : [
|
||||
{"data" : "php"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/phppgadmin/icon.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
12
system/apps/plex/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_plex",
|
||||
"caption" : "Plex",
|
||||
"http_uri" : "http://[server_name]:32400/web/index.html",
|
||||
"use_http" : false,
|
||||
"https_uri" : "https://[server_name]:32400/web/index.html",
|
||||
"use_https" : true,
|
||||
"frame_support" : false,
|
||||
"require" : [
|
||||
{"data" : "plexmediaserver"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/plex/icon.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
12
system/apps/rslsync/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_rslsync",
|
||||
"caption" : "Resilio sync",
|
||||
"http_uri" : "http://[server_name]:8888/",
|
||||
"use_http" : true,
|
||||
"https_uri" : "",
|
||||
"use_https" : true,
|
||||
"frame_support" : false,
|
||||
"require" : [
|
||||
{"data" : "rslsync"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/rslsync/icon.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
12
system/apps/transmission/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"app_name" : "app_transmission",
|
||||
"caption" : "Transmission",
|
||||
"http_uri" : "http://[server_name]:9091/",
|
||||
"use_http" : true,
|
||||
"https_uri" : "",
|
||||
"use_https" : false,
|
||||
"frame_support" : true,
|
||||
"require" : [
|
||||
{"data" : "transmission"}
|
||||
]
|
||||
}
|
||||
BIN
system/apps/transmission/icon.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
154
system/classes/CAI/CAICP/src/Applications.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* CAI CP v.0.9
|
||||
* Applications class
|
||||
*
|
||||
* build date 2017-07-05
|
||||
*
|
||||
* @package : System
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2017 Alexander I. Chebykin
|
||||
* @version : 0.9
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
namespace CAI\CAICP;
|
||||
|
||||
class Applications
|
||||
{
|
||||
protected $apps_avail = array();
|
||||
protected $apps_enabled = array();
|
||||
protected $cp_root = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $root_dir Control panel's root directory
|
||||
*/
|
||||
function __construct($root_dir)
|
||||
{
|
||||
$this->cp_root = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . $root_dir;
|
||||
$this->enum_enabled_apps();
|
||||
$this->enum_avail_apps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read available applications info
|
||||
*/
|
||||
private function enum_avail_apps()
|
||||
{
|
||||
$dir = opendir($this->cp_root . '/system/apps');
|
||||
while($file = readdir($dir)) {
|
||||
if (is_dir($this->cp_root . '/system/apps/' . $file)
|
||||
&& $file != '.' && $file != '..'
|
||||
&& file_exists($this->cp_root . '/system/apps/' . $file . '/app.json')) {
|
||||
$app_info = json_decode(file_get_contents($this->cp_root .
|
||||
'/system/apps/' .
|
||||
$file .
|
||||
'/app.json'),
|
||||
true);
|
||||
if (!array_key_exists('version', $app_info)) {
|
||||
$app_info['version'] = '';
|
||||
}
|
||||
if (!array_key_exists('author', $app_info)) {
|
||||
$app_info['author'] = '';
|
||||
}
|
||||
$this->apps_avail[$file] = array('caption' => $app_info['caption'],
|
||||
'version' => $app_info['version'],
|
||||
'author' => $app_info['author'],
|
||||
'enabled' => array_key_exists($app_info['caption'],
|
||||
$this->apps_enabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enabled applications list
|
||||
*
|
||||
* @return array enabled applications list
|
||||
*/
|
||||
public function enum_enabled_apps() {
|
||||
$this->apps_enabled = json_decode(file_get_contents($this->cp_root .
|
||||
'/system/apps/apps.json'),
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns available applications list
|
||||
*
|
||||
* @return array available applications list
|
||||
*/
|
||||
public function get_avail() {
|
||||
return $this->apps_avail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns available applications list in json format
|
||||
*
|
||||
* @return string available applications list in json format
|
||||
*/
|
||||
public function get_avail_json() {
|
||||
return html_entity_decode(json_encode($this->get_avail()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enabled applications list
|
||||
*
|
||||
* @return array enabled applications list
|
||||
*/
|
||||
public function get_enabled() {
|
||||
return $this->apps_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enabled applications list in json format
|
||||
*
|
||||
* @return string enabled applications list
|
||||
*/
|
||||
public function get_enabled_json() {
|
||||
return html_entity_decode(json_encode($this->get_enabled()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable apps
|
||||
*
|
||||
* @param array $values Array with apps
|
||||
*/
|
||||
public function enable($values)
|
||||
{
|
||||
$this->apps_enabled = $values;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable apps
|
||||
*
|
||||
* @param string $json Apps in JSON format
|
||||
*/
|
||||
public function enable_json($json)
|
||||
{
|
||||
$this->enable(json_decode($json, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set list of enabled applications
|
||||
*
|
||||
* @param array $values array with enabled applications
|
||||
*/
|
||||
public function set($values)
|
||||
{
|
||||
$this->apps_enabled = $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves enabled applications list
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
return file_put_contents($this->cp_root . '/system/apps/apps.json',
|
||||
html_entity_decode(json_encode($this->apps_enabled)));
|
||||
}
|
||||
}
|
||||
51
system/classes/CAI/CAICP/src/Localization.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* CAI CP v.0.9
|
||||
* Localization class
|
||||
*
|
||||
* build date : 2017-07-23
|
||||
*
|
||||
* @package : System
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2017 Alexander I. Chebykin
|
||||
* @version : 1.0
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
namespace CAI\CAICP;
|
||||
|
||||
class Localization
|
||||
{
|
||||
protected $cp_root;
|
||||
protected $lang;
|
||||
protected $locale;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $root_dir Control panel's root directory
|
||||
* @param string $settings Control panel settings
|
||||
*/
|
||||
function __construct($root_dir, $settings)
|
||||
{
|
||||
$this->cp_root = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . $root_dir;
|
||||
|
||||
$this->lang = filter_input(INPUT_GET, 'lang', FILTER_SANITIZE_STRING);
|
||||
if (!array_key_exists($this->lang, $settings['langs'])) {
|
||||
$this->lang = $settings['lang'];
|
||||
}
|
||||
if ($this->lang == '') {
|
||||
$this->lang = 'en';
|
||||
}
|
||||
$this->locale = json_decode(file_get_contents($this->cp_root .
|
||||
'/system/json/locale/' .
|
||||
$this->lang . '.json'),
|
||||
true);
|
||||
}
|
||||
|
||||
public function translate($id)
|
||||
{
|
||||
return $this->locale[$id];
|
||||
}
|
||||
}
|
||||
192
system/classes/CAI/CAICP/src/PSR4Autoloader.php
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace CAI\CAICP;
|
||||
|
||||
/**
|
||||
* @package PSR-4 autoloader
|
||||
* @copyright (c) PHP Framework Interop Group
|
||||
* @link http://www.php-fig.org/psr/psr-4/examples/ Source code
|
||||
*
|
||||
* An example of a general-purpose implementation that includes the optional
|
||||
* functionality of allowing multiple base directories for a single namespace
|
||||
* prefix.
|
||||
*
|
||||
* Given a foo-bar package of classes in the file system at the following
|
||||
* paths ...
|
||||
*
|
||||
* /path/to/packages/foo-bar/
|
||||
* src/
|
||||
* Baz.php # Foo\Bar\Baz
|
||||
* Qux/
|
||||
* Quux.php # Foo\Bar\Qux\Quux
|
||||
* tests/
|
||||
* BazTest.php # Foo\Bar\BazTest
|
||||
* Qux/
|
||||
* QuuxTest.php # Foo\Bar\Qux\QuuxTest
|
||||
*
|
||||
* ... add the path to the class files for the \Foo\Bar\ namespace prefix
|
||||
* as follows:
|
||||
*
|
||||
* <?php
|
||||
* // instantiate the loader
|
||||
* $loader = new \Example\Psr4AutoloaderClass;
|
||||
*
|
||||
* // register the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // register the base directories for the namespace prefix
|
||||
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
|
||||
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');
|
||||
*
|
||||
* The following line would cause the autoloader to attempt to load the
|
||||
* \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php:
|
||||
*
|
||||
* <?php
|
||||
* new \Foo\Bar\Qux\Quux;
|
||||
*
|
||||
* The following line would cause the autoloader to attempt to load the
|
||||
* \Foo\Bar\Qux\QuuxTest class from /path/to/packages/foo-bar/tests/Qux/QuuxTest.php:
|
||||
*
|
||||
* <?php
|
||||
* new \Foo\Bar\Qux\QuuxTest;
|
||||
*/
|
||||
class PSR4Autoloader
|
||||
{
|
||||
/**
|
||||
* An associative array where the key is a namespace prefix and the value
|
||||
* is an array of base directories for classes in that namespace.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $prefixes = array();
|
||||
|
||||
/**
|
||||
* Register loader with SPL autoloader stack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a base directory for a namespace prefix.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $base_dir A base directory for class files in the
|
||||
* namespace.
|
||||
* @param bool $prepend If true, prepend the base directory to the stack
|
||||
* instead of appending it; this causes it to be searched first rather
|
||||
* than last.
|
||||
* @return void
|
||||
*/
|
||||
public function addNamespace($prefix, $base_dir, $prepend = false)
|
||||
{
|
||||
// normalize namespace prefix
|
||||
$prefix = trim($prefix, '\\') . '\\';
|
||||
|
||||
// normalize the base directory with a trailing separator
|
||||
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
|
||||
|
||||
// initialize the namespace prefix array
|
||||
if (isset($this->prefixes[$prefix]) === false) {
|
||||
$this->prefixes[$prefix] = array();
|
||||
}
|
||||
|
||||
// retain the base directory for the namespace prefix
|
||||
if ($prepend) {
|
||||
array_unshift($this->prefixes[$prefix], $base_dir);
|
||||
} else {
|
||||
array_push($this->prefixes[$prefix], $base_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the class file for a given class name.
|
||||
*
|
||||
* @param string $class The fully-qualified class name.
|
||||
* @return mixed The mapped file name on success, or boolean false on
|
||||
* failure.
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
// the current namespace prefix
|
||||
$prefix = $class;
|
||||
|
||||
// work backwards through the namespace names of the fully-qualified
|
||||
// class name to find a mapped file name
|
||||
while (false !== $pos = strrpos($prefix, '\\')) {
|
||||
|
||||
// retain the trailing namespace separator in the prefix
|
||||
$prefix = substr($class, 0, $pos + 1);
|
||||
|
||||
// the rest is the relative class name
|
||||
$relative_class = substr($class, $pos + 1);
|
||||
|
||||
// try to load a mapped file for the prefix and relative class
|
||||
$mapped_file = $this->loadMappedFile($prefix, $relative_class);
|
||||
if ($mapped_file) {
|
||||
return $mapped_file;
|
||||
}
|
||||
|
||||
// remove the trailing namespace separator for the next iteration
|
||||
// of strrpos()
|
||||
$prefix = rtrim($prefix, '\\');
|
||||
}
|
||||
|
||||
// never found a mapped file
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the mapped file for a namespace prefix and relative class.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $relative_class The relative class name.
|
||||
* @return mixed Boolean false if no mapped file can be loaded, or the
|
||||
* name of the mapped file that was loaded.
|
||||
*/
|
||||
protected function loadMappedFile($prefix, $relative_class)
|
||||
{
|
||||
// are there any base directories for this namespace prefix?
|
||||
if (isset($this->prefixes[$prefix]) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// look through base directories for this namespace prefix
|
||||
foreach ($this->prefixes[$prefix] as $base_dir) {
|
||||
|
||||
// replace the namespace prefix with the base directory,
|
||||
// replace namespace separators with directory separators
|
||||
// in the relative class name, append with .php
|
||||
$file = $base_dir
|
||||
. str_replace('\\', '/', $relative_class)
|
||||
. '.php';
|
||||
|
||||
// if the mapped file exists, require it
|
||||
if ($this->requireFile($file)) {
|
||||
// yes, we're done
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// never found it
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a file exists, require it from the file system.
|
||||
*
|
||||
* @param string $file The file to require.
|
||||
* @return bool True if the file exists, false if not.
|
||||
*/
|
||||
protected function requireFile($file)
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
123
system/classes/CAI/CAICP/src/Settings.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* CAI CP v.0.9
|
||||
* Core class
|
||||
*
|
||||
* build date 2017-06-17
|
||||
*
|
||||
* @package : System
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2017 Alexander I. Chebykin
|
||||
* @version : 0.9
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
namespace CAI\CAICP;
|
||||
|
||||
class Settings
|
||||
{
|
||||
protected $user_settings = array();
|
||||
protected $cp_root = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $root_dir Control panel's root directory
|
||||
*/
|
||||
function __construct($root_dir)
|
||||
{
|
||||
$this->cp_root = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . $root_dir;
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read settings from disk
|
||||
*/
|
||||
private function load()
|
||||
{
|
||||
$this->user_settings = json_decode(
|
||||
file_get_contents($this->cp_root . '/system/json/settings.json'),
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings to disk
|
||||
*
|
||||
* @return false|written bytes count
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
return file_put_contents($this->cp_root . '/system/json/settings.json',
|
||||
html_entity_decode(json_encode($this->user_settings)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array with settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->user_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string with settings in JSON format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_json()
|
||||
{
|
||||
return html_entity_decode(json_encode($this->get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return option value
|
||||
*
|
||||
* @param string $option_name Option name
|
||||
*
|
||||
* @return variant|boolean
|
||||
*/
|
||||
public function get_value($option_name)
|
||||
{
|
||||
if (trim($option_name) !== '') {
|
||||
return $this::user_settings[$option_name];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all settings
|
||||
*
|
||||
* @param array $values Array with settings
|
||||
*/
|
||||
public function set($values)
|
||||
{
|
||||
$this->user_settings = $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all settings
|
||||
*
|
||||
* @param string $json Settings in JSON format
|
||||
*/
|
||||
public function set_json($json)
|
||||
{
|
||||
$this->set(json_decode($json, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set option value
|
||||
*
|
||||
* @param string $option_name Option name
|
||||
* @param variant $value New value
|
||||
*/
|
||||
public function set_value($option_name, $value)
|
||||
{
|
||||
if (trim($option_name) !== '') {
|
||||
$this->user_settings[$option_name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
system/help/css/about.css
Normal file
@@ -0,0 +1,32 @@
|
||||
.hidden {display: none;}
|
||||
.centered {text-align: center;}
|
||||
|
||||
.help_title {font-weight: bold;}
|
||||
|
||||
.help_ver, .span_ver,
|
||||
.span_ver_date {font-style: italic;}
|
||||
|
||||
.span_author,
|
||||
.span_author_ru {}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 5px 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background: linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0, 0));
|
||||
}
|
||||
|
||||
article {
|
||||
margin: 10px;
|
||||
}
|
||||
89
system/help/css/help.css
Normal file
@@ -0,0 +1,89 @@
|
||||
.hidden {display: none;}
|
||||
.centered {text-align: center;}
|
||||
|
||||
.help_title {font-weight: bold;}
|
||||
|
||||
.help_ver, .span_ver,
|
||||
.span_ver_date {font-style: italic;}
|
||||
|
||||
.tbl_wide {
|
||||
width: 100%;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
.tbl_wide .tbl_header {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.tbl_wide td {
|
||||
padding: 5px;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
|
||||
.mnu_selected {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.scrollable {overflow: auto;}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 5px 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0,0));
|
||||
background: linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.25),rgba(0,0,0, 0));
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 200px;
|
||||
box-shadow: 5px 5px 5px #ccc;
|
||||
position: fixed;
|
||||
padding: 2px;
|
||||
margin-left: 10px;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
nav ul {
|
||||
padding: 0;
|
||||
margin: 2px;
|
||||
list-style: none;
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
nav ul li {
|
||||
cursor: pointer;
|
||||
}
|
||||
nav ul li ul {
|
||||
padding: 0 0 0 2px;
|
||||
}
|
||||
nav ul li div {
|
||||
padding: 2px 2px 2px 4px;
|
||||
}
|
||||
nav ul li div:hover {
|
||||
background-color: #ddd;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
article {
|
||||
margin: 2px 2px 2px 225px;
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
|
||||
a, a:visited, a:hover {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {text-decoration: underline;}
|
||||
|
||||
#div_license {
|
||||
height: 150px;
|
||||
}
|
||||
13
system/help/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CAI CP: Help</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="css/help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
Loading...
|
||||
<script src="js/help.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
201
system/help/js/help.js
Normal file
@@ -0,0 +1,201 @@
|
||||
// MIT License:
|
||||
//
|
||||
// Copyright (c) 2016-2017, Alexander I. Chebykin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* CAI CP v.1
|
||||
*
|
||||
* @module : Help subsystem
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2016-2017 Alexander I. Chebykin
|
||||
* @version : 0.9
|
||||
* @build date : 2017-06-16
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Return GET parameter
|
||||
*
|
||||
* @param {string} key Key name
|
||||
*
|
||||
* returns {string}
|
||||
*/
|
||||
function $_GET(key) {
|
||||
var s = window.location.search;
|
||||
|
||||
s = s.match(new RegExp(key + '=([^&=]+)'));
|
||||
|
||||
return s ? s[1] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* HelpSystem constructor
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function HelpSystem() {
|
||||
this.locale = 'en';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {int} init_level Initialization level: 1 - select locale
|
||||
* 2 - redirect to localized resource
|
||||
* 3 - load version info
|
||||
* 4 - set event handlers
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
HelpSystem.prototype.init = function (init_level) {
|
||||
var help_instance = this;
|
||||
|
||||
switch (init_level) {
|
||||
case 1:
|
||||
if ($_GET('lang') !== '') {
|
||||
this.locale = $_GET('lang');
|
||||
} else {
|
||||
var request = new XMLHttpRequest(),
|
||||
res_data;
|
||||
|
||||
if (!~location.href.indexOf('locale')) {
|
||||
request.open('GET', '../json/settings.json');
|
||||
} else {
|
||||
request.open('GET', '../../../json/settings.json');
|
||||
}
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
res_data = JSON.parse(this.responseText);
|
||||
|
||||
help_instance.locale = res_data.lang;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
this.init(2);
|
||||
break;
|
||||
case 2:
|
||||
if (!~location.href.indexOf('locale')) {
|
||||
location.href = 'locale/' + this.locale + location.hash;
|
||||
return;
|
||||
} else {
|
||||
this.init(3);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
var request = new XMLHttpRequest(),
|
||||
res_data;
|
||||
|
||||
if (!~location.href.indexOf('locale')) {
|
||||
request.open('GET', '../json/version.json');
|
||||
} else {
|
||||
request.open('GET', '../../../json/version.json');
|
||||
}
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function (e) {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
res_data = JSON.parse(this.responseText);
|
||||
|
||||
var vers = document.getElementsByClassName('span_ver'),
|
||||
ver_dates = document.getElementsByClassName('span_ver_date');
|
||||
|
||||
for (var i = 0; i < vers.length; i++) {
|
||||
vers[i].textContent = res_data.version;
|
||||
}
|
||||
for (var i = 0; i < ver_dates.length; i++) {
|
||||
ver_dates[i].textContent = new Date(res_data.build_date).toLocaleDateString();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.init(4);
|
||||
break;
|
||||
case 4:
|
||||
var nav_list = document.getElementsByTagName('nav'),
|
||||
toc_lis = document.getElementById('menu_toc').getElementsByTagName('li');
|
||||
|
||||
// Show menu
|
||||
for (var i = 0; i < nav_list.length; i++) {
|
||||
nav_list[i].classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Add event listeners
|
||||
for (var i = 0; i < toc_lis.length; i++) {
|
||||
toc_lis[i].getElementsByTagName('div')[0].addEventListener('click', function (event) {
|
||||
help_instance.select_topic(this.parentElement.id.substr(4));
|
||||
});
|
||||
}
|
||||
|
||||
if (location.hash !== '') {
|
||||
help_instance.select_topic(location.hash.substr(1));
|
||||
} else {
|
||||
help_instance.select_topic('start');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} topic_id Topic identifier
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
HelpSystem.prototype.select_topic = function (topic_id) {
|
||||
var articles = document.getElementsByTagName('article'),
|
||||
toc_divs = document.getElementsByClassName('div_toc');
|
||||
|
||||
for (var j = 0; j < toc_divs.length; j++) {
|
||||
toc_divs[j].classList.remove('mnu_selected');
|
||||
}
|
||||
|
||||
document.getElementById('mnu_' + topic_id).getElementsByTagName('div')[0].classList.add('mnu_selected');
|
||||
|
||||
for (var j = 0; j < articles.length; j++) {
|
||||
if (articles[j].id === 'art_' + topic_id) {
|
||||
articles[j].classList.remove('hidden');
|
||||
} else {
|
||||
articles[j].classList.add('hidden');
|
||||
}
|
||||
}
|
||||
location.hash = topic_id;
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Initialize help object
|
||||
*/
|
||||
var help = new HelpSystem();
|
||||
|
||||
help.init(1);
|
||||
|
||||
});
|
||||
|
||||
}());
|
||||
230
system/help/locale/en/index.html
Normal file
@@ -0,0 +1,230 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CAI CP: Help</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../../css/help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="hidden">
|
||||
<ul id="menu_toc">
|
||||
<li id="mnu_start"><div class="div_toc mnu_selected">Tips and ticks</div><hr></li>
|
||||
<li id="mnu_sys_req"><div class="div_toc mnu_selected">System requirements</div><hr></li>
|
||||
<li id="mnu_setup"><div class="div_toc">Setting up</div><hr>
|
||||
<ul>
|
||||
<li id="mnu_security"><div class="div_toc">Security</div><hr></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="mnu_about"><div class="div_toc">About</div></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article id="art_start" class="hidden">
|
||||
<h1>Tips and ticks</h1>
|
||||
<ul>
|
||||
<li>Table witgets can be maximized by double click on header.</li>
|
||||
<li>You can switch between information widgets blocks with
|
||||
following hotkeys:
|
||||
<ul>
|
||||
<li><i>Ctrl + 1</i>: System</li>
|
||||
<li><i>Ctrl + 2</i>: System pulse</li>
|
||||
<li><i>Ctrl + 3</i>: Storage</li>
|
||||
<li><i>Ctrl + 4</i>: Network</li>
|
||||
<li><i>Ctrl + 5</i>: SMB</li>
|
||||
<li><i>Ctrl + Left arrow</i>: Previous block</li>
|
||||
<li><i>Ctrl + Right arrow</i>: Next block</li>
|
||||
</ul>
|
||||
Also You can use left or right swipe on header on devices
|
||||
with touchscreen.
|
||||
<hr>
|
||||
<ul>
|
||||
<li><i>Ctrl + F1</i>: This help</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article id="art_sys_req" class="hidden">
|
||||
<h1>System requirements</h1>
|
||||
<p>Control panel core uses following commands and utilities:</p>
|
||||
<ul>
|
||||
<li>gawk (GNU awk)</li>
|
||||
<li>grep</li>
|
||||
<li>hddtemp</li>
|
||||
<li>lsb-release</li>
|
||||
<li>sed</li>
|
||||
<li>smartmontools (smartctl)</li>
|
||||
<li>sysstat (iostat)</li>
|
||||
<li>php7</li>
|
||||
</ul>
|
||||
<p>
|
||||
Applications may have other dependencies.
|
||||
</p>
|
||||
</article>
|
||||
<article id="art_setup" class="hidden">
|
||||
<h1>Setting up</h1>
|
||||
<p>S.M.A.R.T. and HDD temperature monitoring widgets requires super
|
||||
user priviledges. You need to add webserver account to sudoers.
|
||||
Just run visudo command and add to User privilege specification
|
||||
section next lines:
|
||||
<pre>
|
||||
wwwrun ALL=NOPASSWD: /usr/sbin/smartctl
|
||||
wwwrun ALL=NOPASSWD: /usr/sbin/hddtemp
|
||||
</pre>
|
||||
</p>
|
||||
<p>SMB monitoring widgets requires super user priveledges. You need
|
||||
to add webserver account to sudoers. Just run visudo command and
|
||||
add to User privilege specification section next lines:
|
||||
<pre>
|
||||
wwwrun ALL=NOPASSWD: /usr/bin/smbstatus
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
Control panel configuration file is /system/json/settings.json.<br>
|
||||
Available options:
|
||||
<table class="tbl_wide">
|
||||
<tr class="tbl_header">
|
||||
<td>Option</td>
|
||||
<td>Possible values</td>
|
||||
<td>Description</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>lang</td>
|
||||
<td>ru<br>en<br>...</td>
|
||||
<td>Default languag. You can specify one of installed
|
||||
languages.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>langs</td>
|
||||
<td>"en" : "English"<br>
|
||||
"ru" : "Русский"<br>
|
||||
...
|
||||
</td>
|
||||
<td>Available languages.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dim_on_create</td>
|
||||
<td>true<br>false</td>
|
||||
<td>Widgets runs semi-transparent until data is loaded.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_files_rights</td>
|
||||
<td>true<br>false</td>
|
||||
<td>Check files and directories rights on startup.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_hdd_temp_interval</td>
|
||||
<td>0 .. 86400</td>
|
||||
<td>HDD temperature checking interval (in seconds).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_smart_interval</td>
|
||||
<td>0 .. 86400</td>
|
||||
<td>HDD S.M.A.R.T checking interval (in seconds).</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
You can find applications list in /system/apps/apps.json.
|
||||
Control panel checks dependencies and run applications if they
|
||||
are ok. You can manually disable application by removing string
|
||||
with it from this file.
|
||||
</p>
|
||||
</article>
|
||||
<article id="art_security" class="hidden">
|
||||
<h1>Security</h1>
|
||||
<ol>
|
||||
<li><p>You need to set owner to control panel files to wwwrun:www,
|
||||
all directories and .sh files must have 550 mask, other
|
||||
directories - 440 mask.</p>
|
||||
<p>You need to set 640 mask to /system/json/settings.json if
|
||||
You want to change some settings from WebUI.</p>
|
||||
<p>You can set rights by executing following commands:<br>
|
||||
<code>
|
||||
$ chown -R wwwrun:www /path/to/base/dir<br>
|
||||
$ chmod 440 $(find /path/to/base/dir -type f)<br>
|
||||
$ chmod 550 $(find /path/to/base/dir -type d)<br>
|
||||
$ chmod 550 $(find /path/to/base/dir -type f | grep .sh$)<br>
|
||||
$ chmod 640 /path/to/base/dir/system/json/settings.json<br>
|
||||
$ chmod 640 /path/to/base/dir/system/apps/apps.json
|
||||
</code>
|
||||
</p>
|
||||
</li>
|
||||
<li>Deny accss to .sh files by adding next options to
|
||||
<pre><span><</span>Directory><span><</span>/Directory></pre>
|
||||
block of Apache settings:
|
||||
<pre>
|
||||
<span><</span>FilesMatch "\.(sh)$">
|
||||
Require all denied
|
||||
<span><</span>/FilesMatch>
|
||||
</pre>
|
||||
</li>
|
||||
<li>Set password to restrict access. Basic autorization example:
|
||||
run Apache's utility htpasswd to generate password file
|
||||
.htpasswd. Add next lines to Apache's config file into
|
||||
<pre><span><</span>Directory><span><</span>/Directory></pre>
|
||||
section:
|
||||
<pre>
|
||||
AuthName "Restricted zone"
|
||||
AuthType Basic
|
||||
AuthUserFile [Путь к файлу .htpasswd]
|
||||
Require valid-user
|
||||
</pre>
|
||||
<p>Restart Apache.</p>
|
||||
<p>
|
||||
Attention! Basic authorization uses plain text to send
|
||||
passwords. Consider to use HTTPS to avoid password leak.
|
||||
</p>
|
||||
</li>
|
||||
<li><p>You need to add wwwrun user to sudoers if to enable
|
||||
shutdown or reboot server functions. Be carefully with this
|
||||
option!</p>
|
||||
<p>Run <code># visudo</code> and add following line to
|
||||
"User privilege specification":
|
||||
<code>wwwrun ALL=NOPASSWD: /sbin/shutdown</code>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</article>
|
||||
<article id="art_about" class="hidden">
|
||||
<h1>About</h1>
|
||||
<div class="help_title">CAI CP</div>
|
||||
<div class="help_ver">Version <span class="span_ver">_._</span>. Build date <span class="span_ver_date">__.__.____</span></div>
|
||||
<div>Author: <span class="span_author_ru">Alexander Chebykin</span></div>
|
||||
<div>License: MIT
|
||||
<div id="div_license" class="scrollable">
|
||||
<pre>
|
||||
MIT License
|
||||
-----------
|
||||
|
||||
Copyright (c) 2016-2017, Alexander I. Chebykin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>This product partially based on
|
||||
<a href="https://github.com/afaqurk/linux-dash" target="_blank">
|
||||
Linux Dash
|
||||
</a> project.
|
||||
</p>
|
||||
</article>
|
||||
<script src="../../js/help.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
268
system/help/locale/ru/index.html
Normal file
@@ -0,0 +1,268 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CAI CP: Help</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../../css/help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="hidden">
|
||||
<ul id="menu_toc">
|
||||
<li id="mnu_start"><div class="div_toc mnu_selected">Советы по использованию</div><hr></li>
|
||||
<li id="mnu_sys_req"><div class="div_toc">Системные требования</div><hr></li>
|
||||
<li id="mnu_setup"><div class="div_toc">Настройка</div><hr>
|
||||
<ul>
|
||||
<li id="mnu_security"><div class="div_toc">Безопасность</div><hr></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="mnu_about"><div class="div_toc">О панели управления</div></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article id="art_start" class="hidden">
|
||||
<h1>Советы по использованию</h1>
|
||||
<ul>
|
||||
<li>Табличные виджеты можно распахнуть на весь экран двойным
|
||||
щелчком по заголовку.</li>
|
||||
<li>Для переключения по информационным блокам используйте
|
||||
следующие комбинации клавиш:
|
||||
<ul>
|
||||
<li><i>Ctrl + 1</i>: Система</li>
|
||||
<li><i>Ctrl + 2</i>: Пульс системы</li>
|
||||
<li><i>Ctrl + 3</i>: Файловое хранилище</li>
|
||||
<li><i>Ctrl + 4</i>: Сеть</li>
|
||||
<li><i>Ctrl + 5</i>: SMB</li>
|
||||
<li><i>Ctrl + Влево</i>: Предыдущий блок</li>
|
||||
<li><i>Ctrl + Вправо</i>: Следующий блок</li>
|
||||
</ul>
|
||||
Также вы можете переключаться между блоками, проведя влево
|
||||
или вправо по заголовку на устройствах с сенсорным экраном.
|
||||
<hr>
|
||||
<ul>
|
||||
<li><i>Ctrl + F1</i>: Справка</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article id="art_sys_req" class="hidden">
|
||||
<h1>Системные требования</h1>
|
||||
<p>Ядро системы использует следующие команды и утилиты:</p>
|
||||
<ul>
|
||||
<li>gawk (GNU awk)</li>
|
||||
<li>grep</li>
|
||||
<li>hddtemp</li>
|
||||
<li>lsb-release</li>
|
||||
<li>sed</li>
|
||||
<li>smartmontools (smartctl)</li>
|
||||
<li>sysstat (iostat)</li>
|
||||
<li>php7</li>
|
||||
</ul>
|
||||
<p>
|
||||
Различные приложения могут требовать наличие других программ и утилит.
|
||||
</p>
|
||||
</article>
|
||||
<article id="art_setup" class="hidden">
|
||||
<h1>Настройка</h1>
|
||||
<p>Для мониторинга S.M.A.R.T. и температуры дисков требуется
|
||||
разрешить выполнение smartctl и hddtemp веб-сервером. Для этого
|
||||
запустите редактор sudo командой visudo и добавьте в раздел User
|
||||
privilege specification следующие строки:
|
||||
<pre>
|
||||
wwwrun ALL=NOPASSWD: /usr/sbin/smartctl
|
||||
wwwrun ALL=NOPASSWD: /usr/sbin/hddtemp
|
||||
</pre>
|
||||
</p>
|
||||
<p>Для мониторинга ресурсов SMB требуется разрешить выполнение
|
||||
smbstatus веб-сервером. Для этого запустите редактор sudo
|
||||
командой visudo и добавьте в раздел User privilege specification
|
||||
следующие строки:
|
||||
<pre>
|
||||
wwwrun ALL=NOPASSWD: /usr/bin/smbstatus
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
Конфигурация панели управления задаётся в файле /system/json/settings.json.<br>
|
||||
Параметры:
|
||||
<table class="tbl_wide">
|
||||
<tr class="tbl_header">
|
||||
<td>Параметр</td>
|
||||
<td>Возможные значения</td>
|
||||
<td>Описание</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>lang</td>
|
||||
<td>ru<br>en<br>...</td>
|
||||
<td>Язык по умолчанию. Может быть указан один из
|
||||
доступных языков.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>langs</td>
|
||||
<td>"en" : "English"<br>
|
||||
"ru" : "Русский"<br>
|
||||
...
|
||||
</td>
|
||||
<td>Доступные языки.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dim_on_create</td>
|
||||
<td>true<br>false</td>
|
||||
<td>Виджеты отображаются полупрозрачными пока не
|
||||
загрузятся данные.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_files_rights</td>
|
||||
<td>true<br>false</td>
|
||||
<td>При запуске проводится проверка правильности
|
||||
установленных прав на файлы и каталоги.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_hdd_temp_interval</td>
|
||||
<td>0 .. 86400</td>
|
||||
<td>Интервал (в секундах) проверки температуры жёстких
|
||||
дисков.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>check_smart_interval</td>
|
||||
<td>0 .. 86400</td>
|
||||
<td>Интервал (в секундах) проверки состояния S.M.A.R.T.
|
||||
жёстких дисков.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
Список загружаемых приложений находится в файле /system/apps/apps.json.
|
||||
Панель управления проверяет зависимости приложений и отключает
|
||||
те, что не могут быть запущены на данном сервере. Если вы хотите
|
||||
принудительно отключить какое-либо приложение, удалите строку
|
||||
с его названием из данного файла.
|
||||
</p>
|
||||
</article>
|
||||
<article id="art_security" class="hidden">
|
||||
<h1>Безопасность</h1>
|
||||
<ol>
|
||||
<li><p>Назначьте владельцем файлов и каталогов wwwrun:www, всем
|
||||
каталогам и файлам .sh назначьте права по маске 550,
|
||||
остальным файлам - 440.</p>
|
||||
<p>Если хотите иметь возможность управлять некоторыми
|
||||
параметрами из веб-интерфейса, установите маску 640 файлу
|
||||
/system/json/settings.json.</p>
|
||||
<p>Для этого выполните следующие команды:<br>
|
||||
<code>
|
||||
$ chown -R wwwrun:www /path/to/base/dir<br>
|
||||
$ chmod 440 $(find /path/to/base/dir -type f)<br>
|
||||
$ chmod 550 $(find /path/to/base/dir -type d)<br>
|
||||
$ chmod 550 $(find /path/to/base/dir -type f | grep .sh$)<br>
|
||||
$ chmod 640 /path/to/base/dir/system/json/settings.json<br>
|
||||
$ chmod 640 /path/to/base/dir/system/apps/apps.json
|
||||
</code>
|
||||
</p>
|
||||
</li>
|
||||
<li>Запретите доступ через веб к файлам с расширением .sh, для
|
||||
этого в конфигурационный файл Apache в блок
|
||||
<pre><span><</span>Directory><span><</span>/Directory></pre>
|
||||
добавьте следующие строки:
|
||||
<pre>
|
||||
<span><</span>FilesMatch "\.(sh)$">
|
||||
Require all denied
|
||||
<span><</span>/FilesMatch>
|
||||
</pre>
|
||||
</li>
|
||||
<li>Установите пароль на доступ к панели управления. Пример для
|
||||
настройки базовой аутентификации: с помощью утилиты htpasswd
|
||||
(входит в комплект сервера Apache) создайте содержащий пароль
|
||||
файл .htpasswd. В конфигурационный файл Apache добавьте в блок
|
||||
<pre><span><</span>Directory><span><</span>/Directory></pre> следующие строки:
|
||||
<pre>
|
||||
AuthName "Restricted zone"
|
||||
AuthType Basic
|
||||
AuthUserFile [Путь к файлу .htpasswd]
|
||||
Require valid-user
|
||||
</pre>
|
||||
<p>После этого перезагрузите сервер Apache.</p>
|
||||
<p>
|
||||
Обратите внимание, что в рассмотренном случае используется
|
||||
базовая аутентификация, при её использовании пароль
|
||||
передаётся в открытом виде, для защиты передаваемой
|
||||
информации настройте доступ по протоколу HTTPS.
|
||||
</p>
|
||||
</li>
|
||||
<li><p>Если хотите включить возможность перезагрузки и отключения
|
||||
сервера, следует добавить пользователя wwwrun в sudoers.
|
||||
Будьте осторожны с данной возможностью!</p>
|
||||
<p>Запустите <code># visudo</code> и добавьте следующую
|
||||
строку в блок "User privilege specification":
|
||||
<code>wwwrun ALL=NOPASSWD: /sbin/shutdown</code>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</article>
|
||||
<article id="art_about" class="hidden">
|
||||
<h1>О панели управления</h1>
|
||||
<div class="help_title">CAI CP</div>
|
||||
<div class="help_ver">Версия <span class="span_ver">_._</span> от <span class="span_ver_date">__.__.____</span></div>
|
||||
<div>Автор: <span class="span_author_ru">Александр Чебыкин</span></div>
|
||||
<div>Лицензия: MIT
|
||||
<div id="div_license" class="scrollable">
|
||||
<pre>
|
||||
Лицензия MIT
|
||||
------------
|
||||
|
||||
Copyright (c) 2016-2017, Александр Чебыкин
|
||||
|
||||
Данная лицензия разрешает лицам, получившим копию данного программного
|
||||
обеспечения и сопутствующей документации (в дальнейшем именуемыми
|
||||
«Программное Обеспечение»), безвозмездно использовать Программное Обеспечение
|
||||
без ограничений, включая неограниченное право на использование, копирование,
|
||||
изменение, слияние, публикацию, распространение, сублицензирование и/или
|
||||
продажу копий Программного Обеспечения, а также лицам, которым предоставляется
|
||||
данное Программное Обеспечение, при соблюдении следующих условий:
|
||||
|
||||
Указанное выше уведомление об авторском праве и данные условия должны быть
|
||||
включены во все копии или значимые части данного Программного Обеспечения.
|
||||
|
||||
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО
|
||||
ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ
|
||||
ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ,
|
||||
НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
|
||||
ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ
|
||||
ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА
|
||||
ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ
|
||||
ОБЕСПЕЧЕНИЕМ.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
MIT License
|
||||
-----------
|
||||
|
||||
Copyright (c) 2016-2017, Alexander I. Chebykin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>Данный продукт частично основан на
|
||||
<a href="https://github.com/afaqurk/linux-dash" target="_blank">
|
||||
Linux Dash
|
||||
</a>.
|
||||
</p>
|
||||
</article>
|
||||
<script src="../../js/help.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
9
system/json/general_settings/index.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../../settings.php');
|
||||
|
||||
echo html_entity_decode(json_encode($settings));
|
||||
30
system/json/index.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
$filtered_widget = filter_input(INPUT_GET, 'widget', FILTER_SANITIZE_STRING);
|
||||
$filtered_param = preg_replace('/[^a-zA-Z0-9]+/',
|
||||
'',
|
||||
filter_input(INPUT_GET,
|
||||
'param',
|
||||
FILTER_SANITIZE_STRING)
|
||||
);
|
||||
|
||||
if ($filtered_widget !== '') {
|
||||
if ($filtered_param !== '') {
|
||||
echo shell_exec(sprintf('../scripts/json_api_nix.sh %s %s',
|
||||
$filtered_widget,
|
||||
$filtered_param
|
||||
)
|
||||
);
|
||||
} else {
|
||||
echo shell_exec(sprintf('../scripts/json_api_nix.sh %s',
|
||||
$filtered_widget
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
echo '{}';
|
||||
}
|
||||
70
system/json/locale/en.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"_lang" : "English",
|
||||
"about" : "About",
|
||||
"application" : "Application",
|
||||
"applications" : "Applications",
|
||||
"attention" : "Attention!",
|
||||
"author" : "Author",
|
||||
"check_files_rights" : "Check files rights",
|
||||
"check_hdd_temp_int" : "HDD temperature check interval",
|
||||
"check_smart_int" : "HDD S.M.A.R.T. check interval",
|
||||
"check_users_online_int" : "Online users check interval",
|
||||
"control_panel" : "Control panel",
|
||||
"ctrl_click_hint" : "Ctrl + mouse click to open in new window...",
|
||||
"cpu_info" : "CPU",
|
||||
"default_language" : "Default language",
|
||||
"dim_on_create" : "Dim widgets while creating",
|
||||
"drv_smart_info" : "S.M.A.R.T.",
|
||||
"drv_temp_info" : "Drives temperature",
|
||||
"enbld" : "Enbl",
|
||||
"error" : "Error occured",
|
||||
"fs_check" : "File structure check",
|
||||
"fs_errors" : "Attention! Files structure misconfiguration detected. Click this record to view details.",
|
||||
"fs_info" : "File system",
|
||||
"general_info" : "OS version and uptime",
|
||||
"general_settings" : "General settings",
|
||||
"hdd_overheat" : "HDD overheat detected:",
|
||||
"hdd_smart_error" : "S.M.A.R.T.: HDD error detected",
|
||||
"help" : "Help",
|
||||
"information" : "Information",
|
||||
"iostat_info" : "I/O statistics",
|
||||
"max_hdd_temp" : "Max HDD temperature",
|
||||
"memory_info" : "Memory",
|
||||
"monitoring" : "Monitoring",
|
||||
"net_arp_cache_info" : "ARP cache table",
|
||||
"net_band_info" : "Network bandwidth",
|
||||
"net_conn_info" : "Network connections",
|
||||
"net_down_info" : "Download transfer rate",
|
||||
"net_ip_addr_info" : "Host's IP-addresses",
|
||||
"net_ip_route_info" : "IP routing table",
|
||||
"net_lstn_socks_info" : "Listening server sockets",
|
||||
"net_mcast_info" : "Multicast group membership",
|
||||
"net_unix_socks_info" : "Active unix domain sockets",
|
||||
"net_up_info" : "Upload transfer rate",
|
||||
"network" : "Network",
|
||||
"new_user_connected" : "New user login detected",
|
||||
"proc_info" : "Processes",
|
||||
"reboot" : "Reboot",
|
||||
"reboot_confirm" : "Do You really want to reboot server?",
|
||||
"reboot_in_progress" : "Reboot in progress",
|
||||
"reboot_prohibited" : "Reboot prohibited!",
|
||||
"save" : "Save",
|
||||
"secs" : "seconds",
|
||||
"settings" : "Settings",
|
||||
"settings_saved" : "Настройки сохранены",
|
||||
"shutdown" : "Shutdown",
|
||||
"shutdown_confirm" : "Do You really want to shutdown server?",
|
||||
"shutdown_in_progress" : "Shutdown in progress",
|
||||
"shutdown_prohibited" : "Shutdown prohibited!",
|
||||
"smb" : "SMB",
|
||||
"smb_locks_info" : "SMB locks",
|
||||
"smb_proc_info" : "SMB processes",
|
||||
"smb_shares_info" : "SMB shares",
|
||||
"storage" : "Storage",
|
||||
"swap_info" : "Swap",
|
||||
"system" : "System",
|
||||
"system_pulse" : "System pulse",
|
||||
"transmission_info" : "Transmission",
|
||||
"users_online_info" : "Users online",
|
||||
"version" : "Version"
|
||||
}
|
||||
70
system/json/locale/ru.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"_lang" : "Русский",
|
||||
"about" : "О панели управления",
|
||||
"application" : "Приложение",
|
||||
"applications" : "Приложения",
|
||||
"attention" : "Внимание!",
|
||||
"author" : "Автор",
|
||||
"check_files_rights" : "Проверять права доступа к файлам",
|
||||
"check_hdd_temp_int" : "Интервал проверки температуры дисков",
|
||||
"check_smart_int" : "Интервал проверки S.M.A.R.T.",
|
||||
"check_users_online_int" : "Интервал проверки подключений пользователей",
|
||||
"control_panel" : "Панель управления",
|
||||
"ctrl_click_hint" : "Ctrl + щелчок мыши для открытия в новом окне...",
|
||||
"cpu_info" : "ЦПУ",
|
||||
"default_language" : "Язык по умолчанию",
|
||||
"dim_on_create" : "Затемнять виджеты пока они создаются",
|
||||
"drv_smart_info" : "S.M.A.R.T.",
|
||||
"drv_temp_info" : "Температура дисков",
|
||||
"enbld" : "Вкл",
|
||||
"error" : "Возникла ошибка",
|
||||
"fs_check" : "Проверка файловой структуры",
|
||||
"fs_errors" : "Внимание! Обнаружены связанные с файловой структурой ошибки, щёлкните по данному сообщению для просмотра отчёта.",
|
||||
"fs_info" : "Файловая система",
|
||||
"general_info" : "Версия ОС и время работы",
|
||||
"general_settings" : "Основные настройки",
|
||||
"hdd_overheat" : "Обнаружен перегрев диска",
|
||||
"hdd_smart_error" : "S.M.A.R.T.: Обнаружена ошибка диска",
|
||||
"help" : "Справка",
|
||||
"information" : "Информация",
|
||||
"iostat_info" : "Статистика ввода/вывода",
|
||||
"max_hdd_temp" : "Максимально допустимая температура дисков",
|
||||
"memory_info" : "Память",
|
||||
"monitoring" : "Мониторинг",
|
||||
"net_arp_cache_info" : "Таблица ARP-кэша",
|
||||
"net_band_info" : "Пропускная способность",
|
||||
"net_conn_info" : "Сетевые соединения",
|
||||
"net_down_info" : "Скорость загрузки",
|
||||
"net_ip_addr_info" : "IP-адреса хоста",
|
||||
"net_ip_route_info" : "Таблица маршрутизации",
|
||||
"net_lstn_socks_info" : "Прослушиваемые серверные сокеты",
|
||||
"net_mcast_info" : "Мультикаст-группы",
|
||||
"net_unix_socks_info" : "Активные сокеты unix",
|
||||
"net_up_info" : "Скорость отдачи",
|
||||
"network" : "Сеть",
|
||||
"new_user_connected" : "Подключился новый пользователь",
|
||||
"proc_info" : "Процессы",
|
||||
"reboot" : "Перезагрузка",
|
||||
"reboot_in_progress" : "Сервер перезагружается",
|
||||
"reboot_confirm" : "Вы действительно хотите перезагрузить сервер?",
|
||||
"reboot_prohibited" : "Перезагрузка сервера запрещена!",
|
||||
"save" : "Сохранить",
|
||||
"secs" : "секунд",
|
||||
"settings" : "Настройки",
|
||||
"settings_saved" : "Настройки сохранены",
|
||||
"shutdown" : "Завершение работы",
|
||||
"shutdown_confirm" : "Вы действительно хотите выключить сервер?",
|
||||
"shutdown_in_progress" : "Сервер завершает работу",
|
||||
"shutdown_prohibited" : "Завершение работы сервера запрещено!",
|
||||
"smb" : "SMB",
|
||||
"smb_locks_info" : "Блокировки SMB",
|
||||
"smb_proc_info" : "Процессы SMB",
|
||||
"smb_shares_info" : "Ресурсы SMB",
|
||||
"storage" : "Файловое хранилище",
|
||||
"swap_info" : "Подкачка",
|
||||
"system" : "Система",
|
||||
"system_pulse" : "Пульс системы",
|
||||
"transmission_info" : "Transmission",
|
||||
"users_online_info" : "Подключенные пользователи",
|
||||
"version" : "Версия"
|
||||
}
|
||||
13
system/json/settings.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"dim_on_create" : true,
|
||||
"check_files_rights" : true,
|
||||
"check_users_online_interval" : 60,
|
||||
"check_hdd_temp_interval" : 300,
|
||||
"check_smart_interval" : 3600,
|
||||
"max_hdd_temp" : 45,
|
||||
"lang" : "ru",
|
||||
"langs" : {
|
||||
"en" : "English",
|
||||
"ru" : "Русский"
|
||||
}
|
||||
}
|
||||
4
system/json/version.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version" : "0.9 beta",
|
||||
"build_date" : "2018-08-25"
|
||||
}
|
||||
171
system/scripts/check_files.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../settings.php');
|
||||
|
||||
$files = array( 'index.html' => 440,
|
||||
'LICENSE' => 440,
|
||||
'css' => 550,
|
||||
'css/core.css' => 440,
|
||||
'css/core.min.css' => 440,
|
||||
'gfx' => 550,
|
||||
'gfx/bg.jpg' => 440,
|
||||
'gfx/menu.png' => 440,
|
||||
'gfx/buttons' => 550,
|
||||
'gfx/buttons/delete.png' => 440,
|
||||
'gfx/distros' => 550,
|
||||
'gfx/distros/apple.png' => 440,
|
||||
'gfx/distros/arch.png' => 440,
|
||||
'gfx/distros/bsd.png' => 440,
|
||||
'gfx/distros/debian.png' => 440,
|
||||
'gfx/distros/fedora.png' => 440,
|
||||
'gfx/distros/linux.png' => 440,
|
||||
'gfx/distros/opensuse.png' => 440,
|
||||
'gfx/distros/ubuntu.png' => 440,
|
||||
'gfx/distros/unknown.png' => 440,
|
||||
'gfx/flags' => 550,
|
||||
'gfx/flags/russian-16x16.png' => 440,
|
||||
'gfx/flags/uk-16x16.png' => 440,
|
||||
'gfx/icons' => 550,
|
||||
'gfx/icons/about.png' => 440,
|
||||
'gfx/icons/help.png' => 440,
|
||||
'gfx/icons/loading.gif' => 440,
|
||||
'gfx/icons/network.png' => 440,
|
||||
'gfx/icons/server.png' => 440,
|
||||
'gfx/icons/settings.png' => 440,
|
||||
'gfx/icons/samba.png' => 440,
|
||||
'gfx/icons/storage.png' => 440,
|
||||
'gfx/icons/sysinfo.png' => 440,
|
||||
'js' => 550,
|
||||
'js/core.js' => 440,
|
||||
'js/smoothie.js' => 440,
|
||||
'system' => 550,
|
||||
'system/settings.php' => 440,
|
||||
'system/action' => 550,
|
||||
'system/action/index.php' => 440,
|
||||
'system/apps' => 550,
|
||||
'system/apps/apps.json' => 640,
|
||||
'system/apps/cai_downloader' => 550,
|
||||
'system/apps/cai_downloader/app.json' => 440,
|
||||
'system/apps/cai_downloader/icon.png' => 440,
|
||||
'system/apps/cai_downloader/index.html' => 440,
|
||||
'system/apps/cai_downloader/css' => 550,
|
||||
'system/apps/cai_downloader/css/downloader.css' => 440,
|
||||
'system/apps/cai_downloader/exec' => 550,
|
||||
'system/apps/cai_downloader/exec/index.php' => 440,
|
||||
'system/apps/cai_downloader/exec/scripts' => 550,
|
||||
'system/apps/cai_downloader/exec/scripts/app.sh' => 550,
|
||||
'system/apps/cai_downloader/js' => 550,
|
||||
'system/apps/cai_downloader/js/downloader.js' => 440,
|
||||
'system/apps/cai_downloader/locale' => 550,
|
||||
'system/apps/cai_downloader/locale/en.json' => 440,
|
||||
'system/apps/cai_downloader/locale/ru.json' => 440,
|
||||
'system/apps/nextcloud' => 550,
|
||||
'system/apps/nextcloud/app.json' => 440,
|
||||
'system/apps/nextcloud/icon.png' => 440,
|
||||
'system/apps/openfire' => 550,
|
||||
'system/apps/openfire/app.json' => 440,
|
||||
'system/apps/openfire/icon.png' => 440,
|
||||
'system/apps/owncloud' => 550,
|
||||
'system/apps/owncloud/app.json' => 440,
|
||||
'system/apps/owncloud/icon.png' => 440,
|
||||
'system/apps/phpmyadmin' => 550,
|
||||
'system/apps/phpmyadmin/app.json' => 440,
|
||||
'system/apps/phpmyadmin/icon.png' => 440,
|
||||
'system/apps/phppgadmin' => 550,
|
||||
'system/apps/phppgadmin/app.json' => 440,
|
||||
'system/apps/phppgadmin/icon.png' => 440,
|
||||
'system/apps/plex' => 550,
|
||||
'system/apps/plex/app.json' => 440,
|
||||
'system/apps/plex/icon.png' => 440,
|
||||
'system/apps/rslsync' => 550,
|
||||
'system/apps/rslsync/app.json' => 440,
|
||||
'system/apps/rslsync/icon.png' => 440,
|
||||
'system/apps/transmission' => 550,
|
||||
'system/apps/transmission/app.json' => 440,
|
||||
'system/apps/transmission/icon.png' => 440,
|
||||
'system/classes' => 550,
|
||||
'system/classes/CAI' => 550,
|
||||
'system/classes/CAI/CAICP' => 550,
|
||||
'system/classes/CAI/CAICP/src' => 550,
|
||||
'system/classes/CAI/CAICP/src/Applications.php' => 440,
|
||||
'system/classes/CAI/CAICP/src/Localization.php' => 440,
|
||||
'system/classes/CAI/CAICP/src/PSR4Autoloader.php' => 440,
|
||||
'system/classes/CAI/CAICP/src/Settings.php' => 440,
|
||||
'system/help' => 550,
|
||||
'system/help/index.html' => 440,
|
||||
'system/help/css' => 550,
|
||||
'system/help/css/help.css' => 440,
|
||||
'system/help/js' => 550,
|
||||
'system/help/js/help.js' => 440,
|
||||
'system/help/locale' => 550,
|
||||
'system/help/locale/en' => 550,
|
||||
'system/help/locale/en/index.html' => 440,
|
||||
'system/help/locale/ru' => 550,
|
||||
'system/help/locale/ru/index.html' => 440,
|
||||
'system/json' => 550,
|
||||
'system/json/index.php' => 440,
|
||||
'system/json/settings.json' => 640,
|
||||
'system/json/version.json' => 440,
|
||||
'system/json/general_settings' => 550,
|
||||
'system/json/general_settings/index.php' => 440,
|
||||
'system/json/locale' => 550,
|
||||
'system/json/locale/en.json' => 440,
|
||||
'system/json/locale/ru.json' => 440,
|
||||
'system/scripts' => 550,
|
||||
'system/scripts/check_files.php' => 440,
|
||||
'system/scripts/index.php' => 440,
|
||||
'system/scripts/json_api_nix.sh' => 550,
|
||||
'system/scripts/json_transmission.php' => 440,
|
||||
'system/scripts/json_transmission.sh' => 550,
|
||||
'system/scripts/smart_temp.sh' => 550,
|
||||
'system/scripts/trim.awk' => 440,
|
||||
'system/ui' => 550,
|
||||
'system/ui/forms' => 550,
|
||||
'system/ui/forms/settings' => 550,
|
||||
'system/ui/forms/settings/index.html' => 440,
|
||||
'system/ui/forms/settings/css' => 550,
|
||||
'system/ui/forms/settings/css/styles.css' => 440,
|
||||
'system/ui/forms/settings/js' => 550,
|
||||
'system/ui/forms/settings/js/settings.js' => 440
|
||||
);
|
||||
$script_response = array();
|
||||
$err_count = 0;
|
||||
|
||||
foreach ($files as $key => $value) {
|
||||
if (!file_exists($cp_root . '/' . $key)) {
|
||||
$err_count += 1;
|
||||
|
||||
$script_response[] = array( 'file' => $key,
|
||||
'exists' => 0,
|
||||
'mask_required' => 0,
|
||||
'mask_actual' => 0);
|
||||
} else {
|
||||
$file_owner = posix_getpwuid(fileowner($cp_root . '/' . $key))['name'];
|
||||
$file_group = posix_getgrgid(filegroup($cp_root . '/' . $key))['name'];
|
||||
$file_mask = (int)substr(sprintf('%o',
|
||||
fileperms($cp_root . '/' . $key)
|
||||
),
|
||||
-3);
|
||||
|
||||
if (($value != $file_mask) ||
|
||||
($file_group != FILE_GROUP) ||
|
||||
$file_owner != FILE_OWNER) {
|
||||
$err_count += 1;
|
||||
|
||||
$script_response[] = array( 'file' => $key,
|
||||
'exists' => 1,
|
||||
'mask_required' => $value,
|
||||
'mask_actual' => $file_mask,
|
||||
'owner_required' => FILE_OWNER,
|
||||
'owner_actual' => $file_owner,
|
||||
'group_required' => FILE_GROUP,
|
||||
'group_actual' => $file_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo html_entity_decode(json_encode($script_response));
|
||||
30
system/scripts/index.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
$filtered_widget = filter_input(INPUT_GET, 'widget', FILTER_SANITIZE_STRING);
|
||||
$filtered_param = preg_replace('/[^a-zA-Z0-9]+/',
|
||||
'',
|
||||
filter_input(INPUT_GET,
|
||||
'param',
|
||||
FILTER_SANITIZE_STRING)
|
||||
);
|
||||
|
||||
if ($filtered_widget !== '') {
|
||||
if ($filtered_param !== '') {
|
||||
echo shell_exec(sprintf('./json_api_nix.sh %s %s',
|
||||
$filtered_widget,
|
||||
$filtered_param
|
||||
)
|
||||
);
|
||||
} else {
|
||||
echo shell_exec(sprintf('./json_api_nix.sh %s',
|
||||
$filtered_widget
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
echo '{}';
|
||||
}
|
||||
938
system/scripts/json_api_nix.sh
Normal file
@@ -0,0 +1,938 @@
|
||||
#!/bin/bash
|
||||
|
||||
# MIT License:
|
||||
#
|
||||
# Copyright (c) 2016-2018, Alexander I. Chebykin
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
#################################################################
|
||||
# CAI CP v.0.9.1
|
||||
#
|
||||
# @module : Bash script module
|
||||
# @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
# @copyright : Copyright (c) 2016-2018 Alexander I. Chebykin
|
||||
# @version : 0.9.1
|
||||
# @build date : 2018-08-23
|
||||
# @license : MIT
|
||||
# @link : https://github.com/CAI79/CAI-CP
|
||||
#################################################################
|
||||
|
||||
skeleton() {
|
||||
cmd_arp=`which arp`
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_date=`which date`
|
||||
cmd_df=`which df`
|
||||
cmd_free=`which free`
|
||||
cmd_grep=`which grep`
|
||||
cmd_hostname=`which hostname`
|
||||
cmd_iostat=`which iostat`
|
||||
cmd_ip=`which ip`
|
||||
cmd_lsb_release=`which lsb_release`
|
||||
cmd_lscpu=`which lscpu`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_ps=`which ps`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smartctl=`which smartctl`
|
||||
cmd_smbstatus=`which smbstatus`
|
||||
cmd_sort=`which sort`
|
||||
cmd_ss=`which ss`
|
||||
cmd_uname=`which uname`
|
||||
cmd_w=`which w`
|
||||
|
||||
result=$()
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
_print_parsed() {
|
||||
while read data; do
|
||||
# echo -n "$data" | sed -r "s/\"/\\\\\"/g" | tr -d "\n";
|
||||
echo -n "$data" | tr -d "\n";
|
||||
done;
|
||||
}
|
||||
|
||||
#########################
|
||||
# Common info functions #
|
||||
#########################
|
||||
cpu() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
|
||||
result=$({ $cmd_cat /proc/stat; sleep "1"; $cmd_cat /proc/stat; } \
|
||||
| $cmd_awk '/^cpu* / {usr=$2-usr; sys=$4-sys; idle=$5-idle; iow=$6-iow} END \
|
||||
{total=usr+sys+idle+iow; printf "%.2f\n", (total-idle)*100/total}' \
|
||||
| $cmd_awk -F " " '{print "{\n \"cpu\": " $1 "\n}"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# CPU(s) count
|
||||
cpu_count() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_grep=`which grep`
|
||||
cmd_lscpu=`which lscpu`
|
||||
|
||||
result=$($cmd_lscpu \
|
||||
| $cmd_grep '^CPU(s):' \
|
||||
| $cmd_awk '{ print "{\n\t\"cpu(s)\": " $2 "\n}" }')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# CPU(s) load information
|
||||
cpu_load() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_grep=`which grep`
|
||||
cmd_lscpu=`which lscpu`
|
||||
|
||||
cpus=$($cmd_lscpu \
|
||||
| $cmd_grep '^CPU(s):' \
|
||||
| $cmd_awk '{ print $2 }')
|
||||
|
||||
i=0
|
||||
|
||||
while [ $i -lt $cpus ]
|
||||
do
|
||||
if [ "$i" -ne 0 ]; then
|
||||
result="$result,"
|
||||
fi
|
||||
result+=$(
|
||||
{ $cmd_cat /proc/stat; sleep "1"; $cmd_cat /proc/stat; } \
|
||||
| $cmd_awk '/^cpu'$i' / {usr=$2-usr; sys=$4-sys; idle=$5-idle; iow=$6-iow} END \
|
||||
{total=usr+sys+idle+iow; printf "%.2f\n", (total-idle)*100/total}' \
|
||||
| $cmd_awk -F " " '{print "\n \"cpu'$i'\": " int($1) "\n"}'
|
||||
)
|
||||
(( i++ ))
|
||||
done
|
||||
echo "{$result}" | _print_parsed
|
||||
}
|
||||
|
||||
# CPU information
|
||||
cpu_info() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_lscpu=`which lscpu`
|
||||
|
||||
result=$($cmd_lscpu \
|
||||
| $cmd_awk -F: '{print "\""$1"\": \""$2"\"," }'\
|
||||
)
|
||||
|
||||
echo "[{" ${result%?} "}]" | _print_parsed
|
||||
}
|
||||
|
||||
# General OS information
|
||||
general_info() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_date=`which date`
|
||||
cmd_hostname=`which hostname`
|
||||
cmd_lsb_release=`which lsb_release`
|
||||
cmd_sed=`which sed`
|
||||
cmd_uname=`which uname`
|
||||
|
||||
function displaytime {
|
||||
local T=$1
|
||||
local D=$((T/60/60/24))
|
||||
local H=$((T/60/60%24))
|
||||
local M=$((T/60%60))
|
||||
local S=$((T%60))
|
||||
[[ $D > 0 ]] && printf '%d days ' $D
|
||||
[[ $H > 0 ]] && printf '%d hours ' $H
|
||||
[[ $M > 0 ]] && printf '%d minutes ' $M
|
||||
[[ $D > 0 || $H > 0 || $M > 0 ]] && printf 'and '
|
||||
printf '%d seconds\n' $S
|
||||
}
|
||||
|
||||
lsbRelease=$($cmd_lsb_release -ds | $cmd_sed -e 's/^"//' -e 's/"$//')
|
||||
uname=$($cmd_uname -r | $cmd_sed -e 's/^"//' -e 's/"$//')
|
||||
os=`echo $lsbRelease $uname`
|
||||
hostname=$($cmd_hostname)
|
||||
uptime_seconds=$($cmd_cat /proc/uptime | $cmd_awk '{print $1}')
|
||||
server_time=$($cmd_date)
|
||||
|
||||
echo "[{ \"OS\": \"$os\", \
|
||||
\"Hostname\": \"$hostname\", \
|
||||
\"Uptime\": \" $(displaytime ${uptime_seconds%.*}) \", \
|
||||
\"Server Time\": \"$server_time\" }]" \
|
||||
| _print_parsed
|
||||
}
|
||||
|
||||
# OS distriboutive info
|
||||
os_distr() {
|
||||
cmd_lsb_release=`which lsb_release`
|
||||
cmd_sed=`which sed`
|
||||
cmd_uname=`which uname`
|
||||
|
||||
lsbRelease=$($cmd_lsb_release -ds | $cmd_sed -e 's/^"//' -e 's/"$//')
|
||||
osFamily=$($cmd_uname)
|
||||
|
||||
echo "{ \"Distr\": \"$lsbRelease\", \
|
||||
\"Family\": \"$osFamily\" }" \
|
||||
| _print_parsed
|
||||
}
|
||||
|
||||
# Running processes list
|
||||
processes() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_ps=`which ps`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_ps -eafw \
|
||||
| $cmd_sed -e '1d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"uid\": \"%s\", \
|
||||
\n\t\t\"pid\": %s, \
|
||||
\n\t\t\"ppid\": %s, \
|
||||
\n\t\t\"c\": %s, \
|
||||
\n\t\t\"stime\": \"%s\", \
|
||||
\n\t\t\"tty\": \"%s\", \
|
||||
\n\t\t\"time\": \"%s\", \
|
||||
\n\t\t\"cmd\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Server name
|
||||
srv_name() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_uname=`which uname`
|
||||
|
||||
result=$($cmd_uname -n | $cmd_awk '{ print "{\n\t\"server_name\": \"" $1 "\"\n}" }')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
##############################
|
||||
# File system info functions #
|
||||
##############################
|
||||
|
||||
# File system info
|
||||
fs() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_df=`which df`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_df -h -T \
|
||||
| $cmd_sed -e '1d' \
|
||||
| $cmd_sort -k1,1 -k7,7 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"fs\": \"%s\", \
|
||||
\n\t\t\"type\": \"%s\", \
|
||||
\n\t\t\"size\": \"%s\", \
|
||||
\n\t\t\"used\": \"%s\", \
|
||||
\n\t\t\"free\": \"%s\", \
|
||||
\n\t\t\"percent\": \"%s\", \
|
||||
\n\t\t\"mount\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7)} \
|
||||
END{print "\n]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# HDD S.M.A.R.T. status
|
||||
hdd_smart() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smartctl=`which smartctl`
|
||||
|
||||
result=$(sudo $cmd_smartctl --scan \
|
||||
| $cmd_awk '{printf("%s ", $1)} {system("sudo smartctl -H \"" $1 "\" \
|
||||
| sed -n '5p'")}' \
|
||||
| $cmd_sed -e '/^$/d' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"drive\": \"%s\",\n\t\t\"status\": \"%s\"\n\t}", $1, $NF)} \
|
||||
END \
|
||||
{print "\n]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# HDD temperature info
|
||||
hdd_temp() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_smartctl=`which smartctl`
|
||||
|
||||
path=`pwd`
|
||||
|
||||
result=$($cmd_smartctl --scan \
|
||||
| $cmd_awk '{system("./smart_temp.sh \"" $1 "\"")}' \
|
||||
| $cmd_awk -F: 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{FS=": "} \
|
||||
{printf("\t\t\"drive\": \"%s\", \
|
||||
\n\t\t\"model\": \"%s\", \
|
||||
\n\t\t\"temperature\": \"%s\"\n\t}", $1, $2, $3)} \
|
||||
END\
|
||||
{print "\n]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# IO statistics
|
||||
io_stat() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_iostat=`which iostat`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_iostat \
|
||||
| $cmd_sed -e '1,6d;/^$/d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"device\": \"%s\", \
|
||||
\n\t\t\"tps\": %s, \
|
||||
\n\t\t\"kB_read/s\": %s, \
|
||||
\n\t\t\"kB_wrtn/s\": %s, \
|
||||
\n\t\t\"kB_read\": %s, \
|
||||
\n\t\t\"kB_wrtn\": %s\n\t}", $1, $2, $3, $4, $5, $6)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
#########################
|
||||
# Memory info functions #
|
||||
#########################
|
||||
|
||||
# General memory information
|
||||
mem_info() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_cat /proc/meminfo \
|
||||
| $cmd_awk -F: 'BEGIN {print "{"} {print "\"" $1 "\": \"" $2 "\"," } END {print "}"}' \
|
||||
| $cmd_sed 'N;$s/,\n/\n/;P;D')
|
||||
|
||||
echo "[" ${result%?} "}]" | _print_parsed
|
||||
}
|
||||
|
||||
# Memory usage information
|
||||
#
|
||||
# Based on Linux Dash codebase: https://github.com/afaqurk/linux-dash
|
||||
#
|
||||
# References:
|
||||
# Calculations: http://zcentric.com/2012/05/29/mapping-procmeminfo-to-output-of-free-command/
|
||||
# Fields: https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
mem() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_grep=`which grep`
|
||||
|
||||
memInfoFile="/proc/meminfo"
|
||||
|
||||
memInfo=`$cmd_cat $memInfoFile | $cmd_grep 'MemTotal\|MemFree\|Buffers\|Cached'`
|
||||
|
||||
echo $memInfo \
|
||||
| $cmd_awk '{print "{ \"total\": " ($2/1024) ", \"used\": " ( ($2-($5+$8+$11))/1024 ) " }" }' \
|
||||
| _print_parsed
|
||||
}
|
||||
|
||||
# Swap memory info
|
||||
swap() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_free=`which free`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
# result=$($cmd_free -m \
|
||||
# | $cmd_sed -e '1d' -e '2d' -e '3d' \
|
||||
# | $cmd_awk 'BEGIN \
|
||||
# {print "{"} \
|
||||
# {if (NR > 1) print ","} \
|
||||
# {printf("\n\t\"total\": %s, \n\t\"used\": %s", $2, $3)} \
|
||||
# END{print "\n}"}')
|
||||
result=$($cmd_free -m \
|
||||
| $cmd_sed '/Swap:/!d' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "{"} \
|
||||
{if (NR > 1) print ","} \
|
||||
{printf("\n\t\"total\": %s, \n\t\"used\": %s", $2, $3)} \
|
||||
END{print "\n}"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
##########################
|
||||
# Network info functions #
|
||||
##########################
|
||||
|
||||
# ARP cache table
|
||||
#
|
||||
# Based on Linux Dash codebase: https://github.com/afaqurk/linux-dash
|
||||
arp_cache() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
if hash arp 2>/dev/null; then cmd_arp=`which arp`
|
||||
else cmd_arp="ip neigh"
|
||||
fi
|
||||
|
||||
result=$($cmd_arp | \
|
||||
$cmd_awk 'BEGIN {print "["} NR>1 \
|
||||
{if ( NF==6 ) {print "{ \"addr\": \"" $1 "\", " \
|
||||
"\"hw_type\": \"" $2 "\", " \
|
||||
"\"hw_addr\": \"" $3 "\", " \
|
||||
"\"flags\": \"" $4 "\", " \
|
||||
"\"mask\": \"" $5 "\" , " \
|
||||
"\"iface\": \"" $6 "\" }, "} \
|
||||
if ( NF==5 ) {print "{ \"addr\": \"" $1 "\", " \
|
||||
"\"hw_type\": \"" $2 "\", " \
|
||||
"\"hw_addr\": \"" $3 "\", " \
|
||||
"\"flags\": \"" $4 "\", " \
|
||||
"\"mask\": \"\", " \
|
||||
"\"iface\": \"" $5 "\" }, "} \
|
||||
if ( NF==4 ) {print "{ \"addr\": \"" $1 "\", " \
|
||||
"\"hw_type\": \"" $2 "\", " \
|
||||
"\"hw_addr\": \"" $3 "\", " \
|
||||
"\"flags\": \"\", " \
|
||||
"\"mask\": \"\", " \
|
||||
"\"iface\": \"" $4 "\" }, "} \
|
||||
if ( NF==3 ) {print "{ \"addr\": \"" $1 "\", " \
|
||||
"\"hw_type\": \"\", " \
|
||||
"\"hw_addr\": \"" $2 "\", " \
|
||||
"\"flags\": \"\", " \
|
||||
"\"mask\": \"\", " \
|
||||
"\"iface\": \"" $3 "\" }, "} \
|
||||
} \
|
||||
END {print "]"}' \
|
||||
| $cmd_sed 'N;$s/},/}/;P;D')
|
||||
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# IP addresses
|
||||
#
|
||||
# Based on Linux Dash codebase: https://github.com/afaqurk/linux-dash
|
||||
ip_addr() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_grep=`which grep`
|
||||
cmd_ifconfig=`which ifconfig`
|
||||
cmd_tr=`which tr`
|
||||
cmd_dig=`which dig`
|
||||
|
||||
externalIp=`$cmd_dig +short myip.opendns.com @resolver1.opendns.com`
|
||||
|
||||
$cmd_ifconfig \
|
||||
| $cmd_grep -B1 "inet addr" \
|
||||
| $cmd_awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' \
|
||||
| $cmd_awk -v exIp="$externalIp" -F: 'BEGIN {print "["} { print "{ \"interface\": \"" $1 "\", \"ip\": \"" $3 "\" },"} END {print "{ \"interface\": \"external\", \"ip\": \""exIp"\" } ]"}' \
|
||||
| $cmd_tr -d '\r\n'
|
||||
}
|
||||
|
||||
# Network bandwith
|
||||
net_band() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_cat=`which cat`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_cat /proc/net/dev \
|
||||
| $cmd_awk 'BEGIN\
|
||||
{print "["} NR>2 \
|
||||
{print "{ \"interface\": \"" $1 "\"," " \"tx\": " $2 "," " \"rx\": " $10 " }," } \
|
||||
END\
|
||||
{print "]"}' \
|
||||
| $cmd_sed 'N;$s/,\n/\n/;P;D')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Network connections
|
||||
net_conn() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
cmd_ss=`which ss`
|
||||
|
||||
result=$($cmd_ss \
|
||||
| $cmd_sed -e '1d;/u_str/d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"netid\": \"%s\", \
|
||||
\n\t\t\"state\": \"%s\", \
|
||||
\n\t\t\"rcvq\": %s, \
|
||||
\n\t\t\"sendq\": %s, \
|
||||
\n\t\t\"local\": \"%s\", \
|
||||
\n\t\t\"peer\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6)} \
|
||||
END{print "\n]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Download transfer rate
|
||||
#
|
||||
# Based on Linux Dash codebase: https://github.com/afaqurk/linux-dash
|
||||
net_download_transfer_rate() {
|
||||
files=(/sys/class/net/*)
|
||||
pos=$(( ${#files[*]} - 1 ))
|
||||
last=${files[$pos]}
|
||||
|
||||
json_output="{"
|
||||
|
||||
for interface in "${files[@]}"
|
||||
do
|
||||
basename=$(basename "$interface")
|
||||
|
||||
# find the number of bytes transfered for this interface
|
||||
in1=$(cat /sys/class/net/"$basename"/statistics/rx_bytes)
|
||||
|
||||
# wait a second
|
||||
sleep 1
|
||||
|
||||
# check same interface again
|
||||
in2=$(cat /sys/class/net/"$basename"/statistics/rx_bytes)
|
||||
|
||||
# get the difference (transfer rate)
|
||||
in_bytes=$((in2 - in1))
|
||||
|
||||
# convert transfer rate to KB
|
||||
in_kbytes=$((in_bytes / 1024))
|
||||
|
||||
# convert transfer rate to KB
|
||||
json_output="$json_output \"$basename\": $in_kbytes"
|
||||
|
||||
# if it is not the last line
|
||||
if [[ ! $interface == $last ]]
|
||||
then
|
||||
# add a comma to the line (JSON formatting)
|
||||
json_output="$json_output,"
|
||||
fi
|
||||
done
|
||||
|
||||
# close the JSON object & print to screen
|
||||
echo "$json_output}" | _print_parsed
|
||||
}
|
||||
|
||||
# Upload transfer rate
|
||||
#
|
||||
# Based on Linux Dash codebase: https://github.com/afaqurk/linux-dash
|
||||
net_upload_transfer_rate() {
|
||||
files=(/sys/class/net/*)
|
||||
pos=$(( ${#files[*]} - 1 ))
|
||||
last=${files[$pos]}
|
||||
|
||||
json_output="{"
|
||||
|
||||
for interface in "${files[@]}"
|
||||
do
|
||||
basename=$(basename "$interface")
|
||||
|
||||
# find the number of bytes transfered for this interface
|
||||
out1=$(cat /sys/class/net/"$basename"/statistics/tx_bytes)
|
||||
|
||||
# wait a second
|
||||
sleep 1
|
||||
|
||||
# check same interface again
|
||||
out2=$(cat /sys/class/net/"$basename"/statistics/tx_bytes)
|
||||
|
||||
# get the difference (transfer rate)
|
||||
out_bytes=$((out2 - out1))
|
||||
|
||||
# convert transfer rate to KB
|
||||
out_kbytes=$((out_bytes / 1024))
|
||||
|
||||
# convert transfer rate to KB
|
||||
json_output="$json_output \"$basename\": $out_kbytes"
|
||||
|
||||
# if it is not the last line
|
||||
if [[ ! $interface == $last ]]
|
||||
then
|
||||
# add a comma to the line (JSON formatting)
|
||||
json_output="$json_output,"
|
||||
fi
|
||||
done
|
||||
|
||||
# close the JSON object & print to screen
|
||||
echo "$json_output}" | _print_parsed
|
||||
}
|
||||
|
||||
# Online users info
|
||||
users_online() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smbstatus=`which smbstatus`
|
||||
cmd_sort=`which sort`
|
||||
cmd_w=`which w`
|
||||
|
||||
result=$($cmd_w \
|
||||
| $cmd_sed -e '1,2d' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"user\": \"%s\", \
|
||||
\n\t\t\"tty\": \"%s\", \
|
||||
\n\t\t\"from\": \"%s\", \
|
||||
\n\t\t\"login\": \"%s\", \
|
||||
\n\t\t\"idle\": \"%s\", \
|
||||
\n\t\t\"jcpu\": \"%s\", \
|
||||
\n\t\t\"pcpu\": \"%s\", \
|
||||
\n\t\t\"what\": \"%s %s %s\"\n\t}", \
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)} \
|
||||
END \
|
||||
{print "\n]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# IP routing table
|
||||
ip_route() {
|
||||
if hash netstat 2>/dev/null; then ip_route_netstat
|
||||
else ip_route_ip
|
||||
fi
|
||||
}
|
||||
|
||||
# IP routing table (ip)
|
||||
ip_route_ip() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_ip=`which ip`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_ip r \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{\"route\": \""} \
|
||||
{print } \
|
||||
{print "\"\n\t}"} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# IP routing table (netstat)
|
||||
ip_route_netstat() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_netstat -r \
|
||||
| $cmd_sed -e '1,2d' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"destination\": \"%s\", \
|
||||
\n\t\t\"gateway\": \"%s\", \
|
||||
\n\t\t\"genmask\": \"%s\", \
|
||||
\n\t\t\"flags\": \"%s\", \
|
||||
\n\t\t\"mss\": %s, \
|
||||
\n\t\t\"window\": %s, \
|
||||
\n\t\t\"irtt\": %s, \
|
||||
\n\t\t\"iface\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Multicast groups
|
||||
net_multicast() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_netstat -g \
|
||||
| $cmd_sed -e '1,3d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"interface\": \"%s\", \
|
||||
\n\t\t\"refcnt\": %s, \
|
||||
\n\t\t\"group\": \"%s\"\n\t}", $1, $2, $3)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Listening sockets
|
||||
listen_socks() {
|
||||
if hash netstat 2>/dev/null; then listen_socks_netstat
|
||||
else listen_socks_ss
|
||||
fi
|
||||
}
|
||||
|
||||
# Listening sockets (ss)
|
||||
listen_socks_ss() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_ss=`which ss`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_ss -ltn \
|
||||
| $cmd_sed -e '1d' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"state\": \"%s\", \
|
||||
\n\t\t\"recv-q\": %s, \
|
||||
\n\t\t\"send-q\": %s, \
|
||||
\n\t\t\"local address:port\": \"%s\", \
|
||||
\n\t\t\"peer addr:port\": \"%s\"\n\t}", $1, $2, $3, $4, $5)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Listening sockets (netstat)
|
||||
listen_socks_netstat() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_sed=`which sed`
|
||||
|
||||
result=$($cmd_netstat -l \
|
||||
| $cmd_sed -n '/tcp/p;/udp/p;/raw/p' \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"proto\": \"%s\", \
|
||||
\n\t\t\"recv-q\": %s, \
|
||||
\n\t\t\"send-q\": %s, \
|
||||
\n\t\t\"localaddr\": \"%s\", \
|
||||
\n\t\t\"foreignaddr\": \"%s\", \
|
||||
\n\t\t\"state\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Active unix domain sockets
|
||||
active_unix_socks() {
|
||||
if hash netstat 2>/dev/null; then active_unix_socks_netstat
|
||||
else active_unix_socks_ss
|
||||
fi
|
||||
}
|
||||
|
||||
# Active unix domain sockets (ss)
|
||||
active_unix_socks_ss() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_ss=`which ss`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_ss -x \
|
||||
| $cmd_sed -e '1d' \
|
||||
| $cmd_sort -k6 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"netid\": \"%s\", \
|
||||
\n\t\t\"state\": \"%s\", \
|
||||
\n\t\t\"recv-q\": %s, \
|
||||
\n\t\t\"send-q\": %s, \
|
||||
\n\t\t\"local address:port\": \"%s:%s\", \
|
||||
\n\t\t\"peer address:port\": \"%s:%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Active unix domain sockets (netstat)
|
||||
active_unix_socks_netstat() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_netstat=`which netstat`
|
||||
cmd_sed=`which sed`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$($cmd_netstat -l \
|
||||
| $cmd_sed -n '/unix/p' \
|
||||
| $cmd_sort -k6 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"proto\": \"%s\", \
|
||||
\n\t\t\"refcnt\": %s, \
|
||||
\n\t\t\"flags\": \"%s%s%s\", \
|
||||
\n\t\t\"type\": \"%s\", \
|
||||
\n\t\t\"state\": \"%s\", \
|
||||
\n\t\t\"i-node\": \"%s\", \
|
||||
\n\t\t\"path\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8, $9)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# Check is application installed or not
|
||||
check_app() {
|
||||
cmd_awk=`which awk`
|
||||
|
||||
result=$(whereis -S /opt -f $1 \
|
||||
| $cmd_awk -F: '{if(length($2)==0) { installed="false"; } else { installed="true"; } \
|
||||
print \
|
||||
"{ \
|
||||
\"binary\": \""$1"\", \
|
||||
\"location\": \""$2"\", \
|
||||
\"installed\": "installed" \
|
||||
}"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# SMB processes
|
||||
smb_proc() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smbstatus=`which smbstatus`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$(sudo $cmd_smbstatus -pf \
|
||||
| $cmd_sed -e '1,4d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"pid\": %s, \
|
||||
\n\t\t\"username\": \"%s\", \
|
||||
\n\t\t\"group\": \"%s\", \
|
||||
\n\t\t\"machine\": \"%s\", \
|
||||
\n\t\t\"protocol ver\": \"%s\", \
|
||||
\n\t\t\"encryption\": \"%s\", \
|
||||
\n\t\t\"signing\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# SMB shares
|
||||
smb_shares() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smbstatus=`which smbstatus`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$(sudo $cmd_smbstatus -Sf \
|
||||
| $cmd_sed -e '1,3d;/^\s*$/d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"service\": \"%s\", \
|
||||
\n\t\t\"pid\": %s, \
|
||||
\n\t\t\"machine\": \"%s\", \
|
||||
\n\t\t\"connected at\": \"%s %s %s %s %s %s\", \
|
||||
\n\t\t\"encryption\": \"%s\", \
|
||||
\n\t\t\"signing\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
# SMB locked files
|
||||
smb_locks() {
|
||||
cmd_awk=`which awk`
|
||||
cmd_sed=`which sed`
|
||||
cmd_smbstatus=`which smbstatus`
|
||||
cmd_sort=`which sort`
|
||||
|
||||
result=$(sudo $cmd_smbstatus -Lf \
|
||||
| $cmd_sed -e '1,3d;/^\s*$/d' \
|
||||
| $cmd_sort -k1 \
|
||||
| $cmd_awk 'BEGIN \
|
||||
{print "["} \
|
||||
{if (NR > 1) print ","} \
|
||||
{fname = ""} \
|
||||
{ftime = ""} \
|
||||
{for (i = 8; i < NF - 4; i++) fname = fname" "$i} \
|
||||
{for (i = NF - 4; i < NF; i++) ftime = ftime" "$i} \
|
||||
{print "\t{"} \
|
||||
{printf("\t\t\"pid\": %s, \
|
||||
\n\t\t\"uid\": %s, \
|
||||
\n\t\t\"deny mode\": \"%s\", \
|
||||
\n\t\t\"access\": \"%s\", \
|
||||
\n\t\t\"r/w\": \"%s\", \
|
||||
\n\t\t\"oplock\": \"%s\", \
|
||||
\n\t\t\"share path\": \"%s\", \
|
||||
\n\t\t\"name\": \"%s\", \
|
||||
\n\t\t\"time\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, fname, ftime)} \
|
||||
END \
|
||||
{print "\n\t]"}')
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result | _print_parsed
|
||||
fi
|
||||
}
|
||||
|
||||
function_name="$1"
|
||||
parameter="$2"
|
||||
|
||||
${function_name} ${parameter}
|
||||
15
system/scripts/json_transmission.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
require_once('../settings.php');
|
||||
|
||||
if (W_TRANSMISSION_ENABLED) {
|
||||
echo shell_exec('./json_transmission.sh ' . W_TRANSMISSION_HOST . ' '
|
||||
. W_TRANSMISSION_NAME . ' '
|
||||
. W_TRANSMISSION_PASS);
|
||||
} else {
|
||||
echo '[]';
|
||||
}
|
||||
2
system/scripts/json_transmission.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#! /bin/bash
|
||||
transmission-remote $1 -n $2:$3 -l | sed '$d' | sed -e '1d' | awk '@include "trim.awk";{{printf("%s;%s;%s;%s;%s;%s;%s;%s;%s;", $1, $2, $3, $4, $5, $6, $7, $8, $9)} {$1=$2=$3=$4=$5=$6=$7=$8=$9=""; print trim($0)}}' | awk -F ";" 'BEGIN{print "["}{if (NR > 1) print ","}{print "\t{"}{printf("\t\t\"ID\": \"%s\",\n\t\t\"Done\": \"%s\",\n\t\t\"Have\": \"%s %s\",\n\t\t\"ETA\": \"%s\",\n\t\t\"Up\": \"%s\",\n\t\t\"Down\": \"%s\",\n\t\t\"Ratio\": \"%s\",\n\t\t\"Status\": \"%s\",\n\t\t\"Name\": \"%s\"\n\t}", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10)}END{print "\n]"}'
|
||||
18
system/scripts/smart_temp.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
cmd_awk=`which awk`
|
||||
cmd_grep=`which grep`
|
||||
cmd_hddtemp=`which hddtemp`
|
||||
cmd_smartctl=`which smartctl`
|
||||
|
||||
drvtemp=$(sudo $cmd_hddtemp $1)
|
||||
hdd=$(echo "$drvtemp" | $cmd_awk -F: '{print $1}')
|
||||
model=$(echo "$drvtemp" | $cmd_awk -F: '{print $2}')
|
||||
result=$(sudo $cmd_smartctl -a $1 | $cmd_grep "Current Drive Temperature" | $cmd_awk '{print $4"°"$5}')
|
||||
|
||||
if [ -z "$result" ];
|
||||
then
|
||||
result=$(echo "$drvtemp" | $cmd_awk -F: '{print $3}')
|
||||
fi
|
||||
|
||||
echo $hdd: $model: $result
|
||||
3
system/scripts/trim.awk
Normal file
@@ -0,0 +1,3 @@
|
||||
function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s }
|
||||
function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s }
|
||||
function trim(s) { return rtrim(ltrim(s)); }
|
||||
43
system/settings.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/* ----- Begin of settings block ----- */
|
||||
|
||||
/* Security check constants */
|
||||
const FILE_OWNER = 'wwwrun';
|
||||
const FILE_GROUP = 'www';
|
||||
|
||||
/* Shutdown and reboot options */
|
||||
const SHUTDOWN_ENABLED = false;
|
||||
const REBOOT_ENABLED = false;
|
||||
|
||||
/* Control panel directory relative to server root */
|
||||
const CP_ROOT_REL = '';
|
||||
|
||||
/* Wrere downloadable file must be stored */
|
||||
const FILE_DOWNLOAD_DIR = '';
|
||||
|
||||
/* Transmission widget */
|
||||
const W_TRANSMISSION_ENABLED = false;
|
||||
const W_TRANSMISSION_HOST = '127.0.0.1';
|
||||
const W_TRANSMISSION_NAME = 'transmission';
|
||||
const W_TRANSMISSION_PASS = 'transmission';
|
||||
|
||||
/* ----- End of settings block ----- */
|
||||
|
||||
/* Don't change lines below */
|
||||
$cp_root = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . CP_ROOT_REL;
|
||||
|
||||
$settings = array('shutdown_enabled' => SHUTDOWN_ENABLED,
|
||||
'reboot_enabled' => REBOOT_ENABLED,
|
||||
'w_transmisson_enabled' => W_TRANSMISSION_ENABLED);
|
||||
|
||||
/* Configure autoloader */
|
||||
require_once($cp_root . '/system/classes/CAI/CAICP/src/PSR4Autoloader.php');
|
||||
|
||||
$autoloader = new \CAI\CAICP\PSR4Autoloader;
|
||||
$autoloader->register();
|
||||
$autoloader->addNamespace('CAI\CAICP', $cp_root . '/system/classes/CAI/CAICP/src');
|
||||
//$Autoloader->addNamespace('CAI\CAICP', $cp_root . '/system/classes/CAI/CAICP/tests');
|
||||
|
||||
/* Create system objects */
|
||||
$user_cfg = new \CAI\CAICP\Settings(CP_ROOT_REL);
|
||||
$lang = new \CAI\CAICP\Localization(CP_ROOT_REL, $user_cfg->get());
|
||||
79
system/ui/forms/settings/css/styles.css
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Common classes block */
|
||||
.hidden {
|
||||
/* visibility: hidden; */
|
||||
display: none;
|
||||
}
|
||||
.full_width {
|
||||
width: 100%;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Elements block */
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 600px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
/* background: url(../gfx/bg.jpg) repeat fixed; */
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.25), rgba(0,0,0,0));
|
||||
background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.25), rgba(0,0,0,0));
|
||||
background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.25), rgba(0,0,0,0));
|
||||
background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.25), rgba(0,0,0,0));
|
||||
background: linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.25), rgba(0,0,0,0));
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: solid 1px #ccc;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 5px;
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
|
||||
/* Language selector */
|
||||
input, select {border: solid 1px #999;}
|
||||
|
||||
.select_lang {
|
||||
border : 0;
|
||||
background-color : transparent;
|
||||
}
|
||||
.select_lang option {
|
||||
color: #000;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
/*
|
||||
select#gender option[value="male"] { background-image:url(male.png); }
|
||||
select#gender option[value="female"] { background-image:url(female.png); }
|
||||
select#gender option[value="others"] { background-image:url(others.png); }
|
||||
*/
|
||||
.input_ru {
|
||||
background-image: url('../gfx/flags/russian-16x16.png');
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: scroll;
|
||||
background-position: 2px center;
|
||||
padding-left: 21px;
|
||||
margin-left: 1px;
|
||||
}
|
||||
.input_en {
|
||||
background-image: url('../gfx/flags/uk-16x16.png');
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: scroll;
|
||||
background-position: 2px center;
|
||||
padding-left: 21px;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
#in_submit {margin-top: 5px};
|
||||
103
system/ui/forms/settings/index.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CAI CP Settings</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="css/styles.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<form id="frm_submit" method="get" action="../../../action/" class="hidden">
|
||||
<input type="hidden" name="do" value="setup">
|
||||
<fieldset id="fs_general">
|
||||
<legend id="fsl_general"></legend>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<span id="lbl_default_language">[lang_default_language]: </span>
|
||||
</td>
|
||||
<td>
|
||||
<select id="default_language" name="default_language" class="select_lang"></select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="dim_on_create" id="lbl_dim_on_create">[lang_dim_on_create]: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" value="1" name="dim_on_create" id="dim_on_create">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="check_files_rights" id="lbl_check_files_rights">[lang_check_files_rights]: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" value="1" name="chk_files_rights" id="chk_files_rights">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<fieldset id="fs_monitoring">
|
||||
<legend id="fsl_monitoring"></legend>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<span id="lbl_max_hdd_temp">[lang_max_hdd_temp]: </span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" id="max_hdd_temp" name="max_hdd_temp" min="30" max="100">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span id="lbl_check_hdd_temp_interval">[lang_check_temp_int]: </span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" id="chk_temp_interval" name="chk_temp_interval" min="0" max="86400"> <span id="lbl_temp_secs">[lang_secs]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span id="lbl_check_smart_interval">[lang_check_smart_int]: </span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" id="chk_smart_interval" name="chk_smart_interval" min="0" max="86400"> <span id="lbl_smart_secs">[lang_secs]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span id="lbl_check_users_online_interval">[lang_check_users_online_int]: </span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" id="chk_users_online_interval" name="chk_users_online_interval" min="0" max="86400"> <span id="lbl_users_online_secs">[lang_secs]</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<fieldset id="fs_apps">
|
||||
<legend id="fsl_apps"></legend>
|
||||
<table id="tbl_apps" class="full_width">
|
||||
<tr class="bold">
|
||||
<td>
|
||||
<span id="lbl_enabled">[lang_enabled]</span>
|
||||
</td>
|
||||
<td>
|
||||
<span id="lbl_app_name">[lang_app_name]</span>
|
||||
</td>
|
||||
<td>
|
||||
<span id="lbl_app_ver">[lang_app_ver]</span>
|
||||
</td>
|
||||
<td>
|
||||
<span id="lbl_app_author">[lang_app_author]: </span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<input id="in_submit" type="submit" value="[lang_save]">
|
||||
</form>
|
||||
</div>
|
||||
<script src="js/settings.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
278
system/ui/forms/settings/js/settings.js
Normal file
@@ -0,0 +1,278 @@
|
||||
// MIT License:
|
||||
//
|
||||
// Copyright (c) 2016-2017, Alexander I. Chebykin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* CAI CP v.0.9
|
||||
*
|
||||
* @module : Configuration subsystem
|
||||
* @author : Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
* @copyright : Copyright (c) 2016-2017 Alexander I. Chebykin
|
||||
* @version : 0.9
|
||||
* @build date : 2017-07-23
|
||||
* @license : MIT
|
||||
* @link : https://github.com/CAI79/CAI-CP
|
||||
******************************************************************/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Return GET parameter
|
||||
*
|
||||
* @param {string} key Key name
|
||||
*
|
||||
* returns {string}
|
||||
*/
|
||||
function $_GET(key) {
|
||||
var s = window.location.search;
|
||||
|
||||
s = s.match(new RegExp(key + '=([^&=]+)'));
|
||||
|
||||
return s ? s[1] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* SetupSystem constructor
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function SetupSystem() {
|
||||
this.locale = 'en';
|
||||
this.langs = [];
|
||||
this.tranlation = [];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {int} init_level Initialization level: 1 - configure language
|
||||
* 2 - do localization
|
||||
* 3 - load languages list
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
SetupSystem.prototype.init = function (init_level) {
|
||||
var setup_instance = this,
|
||||
request = new XMLHttpRequest(),
|
||||
res_data;
|
||||
|
||||
switch (init_level) {
|
||||
case 1: // Configure language
|
||||
if ($_GET('lang') !== '') {
|
||||
this.locale = $_GET('lang');
|
||||
} else {
|
||||
request.open('GET', '../../../json/settings.json');
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
res_data = JSON.parse(this.responseText);
|
||||
setup_instance.locale = res_data.lang;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
this.init(2);
|
||||
break;
|
||||
case 2: // Do localization
|
||||
request.open('GET', '../../../json/locale/' + this.locale + '.json');
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
res_data = JSON.parse(this.responseText);
|
||||
setup_instance.tranlation = res_data;
|
||||
|
||||
document.getElementById('lbl_dim_on_create').textContent = res_data.dim_on_create;
|
||||
document.getElementById('lbl_default_language').textContent = res_data.default_language;
|
||||
document.getElementById('lbl_check_files_rights').textContent = res_data.check_files_rights;
|
||||
document.getElementById('lbl_check_hdd_temp_interval').textContent = res_data.check_hdd_temp_int;
|
||||
document.getElementById('lbl_check_users_online_interval').textContent = res_data.check_users_online_int;
|
||||
document.getElementById('lbl_max_hdd_temp').textContent = res_data.max_hdd_temp;
|
||||
document.getElementById('lbl_check_smart_interval').textContent = res_data.check_smart_int;
|
||||
document.getElementById('lbl_temp_secs').textContent = res_data.secs;
|
||||
document.getElementById('lbl_smart_secs').textContent = res_data.secs;
|
||||
document.getElementById('lbl_users_online_secs').textContent = res_data.secs;
|
||||
document.getElementById('fsl_general').textContent = res_data.general_settings;
|
||||
document.getElementById('fsl_monitoring').textContent = res_data.monitoring;
|
||||
document.getElementById('fsl_apps').textContent = res_data.applications;
|
||||
document.getElementById('lbl_enabled').textContent = res_data.enbld;
|
||||
document.getElementById('lbl_app_name').textContent = res_data.application;
|
||||
document.getElementById('lbl_app_ver').textContent = res_data.version;
|
||||
document.getElementById('lbl_app_author').textContent = res_data.author;
|
||||
document.getElementById('in_submit').value = res_data.save;
|
||||
|
||||
document.getElementById("frm_submit").classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
};
|
||||
this.init(3);
|
||||
break;
|
||||
case 3: // Load languages list
|
||||
request.open('GET', '../../../json/settings.json');
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
var select_lang = document.getElementById('default_language');
|
||||
|
||||
res_data = JSON.parse(this.responseText);
|
||||
|
||||
document.getElementById('dim_on_create').checked = res_data.dim_on_create;
|
||||
document.getElementById('chk_files_rights').checked = res_data.check_files_rights;
|
||||
document.getElementById('chk_temp_interval').value = res_data.check_hdd_temp_interval;
|
||||
document.getElementById('chk_smart_interval').value = res_data.check_smart_interval;
|
||||
document.getElementById('chk_users_online_interval').value = res_data.check_users_online_interval;
|
||||
document.getElementById('max_hdd_temp').value = res_data.max_hdd_temp;
|
||||
|
||||
setup_instance.langs = res_data.langs;
|
||||
|
||||
for (var language in res_data.langs) {
|
||||
var opt_lang = document.createElement('option');
|
||||
|
||||
opt_lang.value = language;
|
||||
opt_lang.appendChild(document.createTextNode(res_data.langs[language]));
|
||||
|
||||
if (res_data.lang === language) {
|
||||
opt_lang.selected = true;
|
||||
} else if (!$_GET('lang') && setup_instance.locale === language){
|
||||
opt_lang.selected = true;
|
||||
}
|
||||
|
||||
select_lang.appendChild(opt_lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.init(4);
|
||||
break;
|
||||
case 4: // Load apps list
|
||||
request.open('GET', '../../../apps/?do=get_apps');
|
||||
request.send();
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status === 200) {
|
||||
var apps_table = document.getElementById('tbl_apps'),
|
||||
apps_tr,
|
||||
apps_td,
|
||||
apps_name,
|
||||
apps_caption,
|
||||
apps_check,
|
||||
i = 0;
|
||||
res_data = JSON.parse(this.responseText);
|
||||
for (var app_info in res_data) {
|
||||
apps_tr = document.createElement('tr');
|
||||
apps_td = document.createElement('td');
|
||||
|
||||
apps_caption = document.createElement('input');
|
||||
apps_caption.type = 'hidden';
|
||||
apps_caption.name = 'app_caption[' + i + ']';
|
||||
apps_caption.value = res_data[app_info].caption;
|
||||
apps_td.appendChild(apps_caption);
|
||||
|
||||
apps_name = document.createElement('input');
|
||||
apps_name.type = 'hidden';
|
||||
apps_name.name = 'app_name[' + i + ']';
|
||||
apps_name.value = app_info;
|
||||
apps_td.appendChild(apps_name);
|
||||
|
||||
apps_check = document.createElement('input');
|
||||
apps_check.type = 'checkbox';
|
||||
apps_check.name = 'app_enabled[' + i + ']';
|
||||
apps_check.value = '1';
|
||||
apps_check.checked = res_data[app_info].enabled;
|
||||
|
||||
apps_td.appendChild(apps_check);
|
||||
apps_tr.appendChild(apps_td);
|
||||
apps_td = document.createElement('td');
|
||||
apps_td.appendChild(document.createTextNode(res_data[app_info].caption));
|
||||
apps_tr.appendChild(apps_td);
|
||||
apps_td = document.createElement('td');
|
||||
apps_td.appendChild(document.createTextNode(res_data[app_info].version));
|
||||
apps_tr.appendChild(apps_td);
|
||||
apps_td = document.createElement('td');
|
||||
apps_td.appendChild(document.createTextNode(res_data[app_info].author));
|
||||
apps_tr.appendChild(apps_td);
|
||||
apps_table.appendChild(apps_tr);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Initialize setup object
|
||||
*/
|
||||
var setup = new SetupSystem();
|
||||
|
||||
setup.init(1);
|
||||
|
||||
document.getElementById('frm_submit').onsubmit = function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.responseText === 'true') {
|
||||
alert(setup.tranlation.settings_saved);
|
||||
window.top.location.reload(true);
|
||||
} else {
|
||||
alert(setup.tranlation.error);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.method.toLowerCase() === 'post') {
|
||||
xhr.open (this.method, this.action, true);
|
||||
xhr.send (new FormData (this));
|
||||
} else {
|
||||
var element,
|
||||
el_type,
|
||||
file,
|
||||
search = '';
|
||||
for (var i = 0; i < this.elements.length; i++) {
|
||||
element = this.elements[i];
|
||||
if (!element.hasAttribute('name')) { continue; }
|
||||
el_type = element.nodeName.toLowerCase() === 'input' ?
|
||||
element.getAttribute('type').toLowerCase() : 'text';
|
||||
if (el_type === 'file') {
|
||||
for (file = 0; file < element.files.length;
|
||||
search += '&' + escape(element.name) + '=' + escape(element.files[file++].name));
|
||||
} else if ((el_type !== 'radio' && el_type !== 'checkbox') || element.checked) {
|
||||
search += '&' + escape(element.name) + '=' + escape(element.value);
|
||||
}
|
||||
}
|
||||
xhr.open('get', this.action.replace(/(?:\?.*)?$/, search.replace(/^&/, '?')), true);
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
}());
|
||||