initial code comit
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
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.
|
||||
1
_config.yml
Normal file
@ -0,0 +1 @@
|
||||
theme: jekyll-theme-slate
|
||||
430
css/core.css
Normal file
@ -0,0 +1,430 @@
|
||||
/* Common classes block */
|
||||
.wide {width: 100%;}
|
||||
.hidden {
|
||||
/* visibility: hidden; */
|
||||
display: none;
|
||||
}
|
||||
.div_clear {
|
||||
clear: both;
|
||||
height: 1px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.div_maximized {
|
||||
width: calc(100% - 10px) !important;
|
||||
height: calc(100% - 90px) !important;
|
||||
}
|
||||
.div_maximized_content {
|
||||
max-height: calc(100% - 30px) !important;
|
||||
}
|
||||
.loading_div {
|
||||
background: url(../gfx/ico_loading.gif) no-repeat center center;
|
||||
}
|
||||
.slightly_visible {
|
||||
opacity: 0.25;
|
||||
}
|
||||
th,
|
||||
.table_header {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.top_right_hint {
|
||||
text-align: right;
|
||||
font-weight: normal;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.distro_logo {
|
||||
max-height: 140px;
|
||||
max-width: 380px;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
header {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/* Page block */
|
||||
#app_header {min-width: 600px;}
|
||||
#s_header {
|
||||
position: absolute;
|
||||
margin: 14px auto 0 55px;
|
||||
top: 0;
|
||||
font-family: Courier;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#page_content {
|
||||
margin: 70px 10px 0 10px;
|
||||
height: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Attention block */
|
||||
#div_attention {
|
||||
position: absolute;
|
||||
right: 100px;
|
||||
top: 4px;
|
||||
}
|
||||
#div_attention img {width: 30px;}
|
||||
#div_attention_content {
|
||||
right: 0;
|
||||
width: 400px;
|
||||
}
|
||||
#ul_attention {
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
border-color: #fff;
|
||||
}
|
||||
#ul_attention li{
|
||||
margin: 1px;
|
||||
float: left;
|
||||
position: relative;
|
||||
list-style: none;
|
||||
}
|
||||
#ul_attention a {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 8px 8px 6px 8px;
|
||||
border: solid 1px transparent;
|
||||
border-radius: 25px;
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
#ul_attention a:hover {
|
||||
box-shadow: inset 0 0 10px rgba(0,0,0,0.5);
|
||||
}
|
||||
#ul_attention .current a,
|
||||
#ul_attention li:hover a {
|
||||
background-color: #fff;
|
||||
border: solid 1px #000;
|
||||
}
|
||||
#ul_attention li:hover > #div_attention_content {
|
||||
visibility: visible;
|
||||
opacity: 0.95;
|
||||
}
|
||||
#ul_attention #div_attention_content {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
min-height: 40px;
|
||||
max-height: calc(100vh - 80px);
|
||||
max-width: calc(100vw - 80px);
|
||||
overflow: auto;
|
||||
padding: 5px;
|
||||
border: 1px solid #000;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
z-index: 1000;
|
||||
margin-top: -1px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
|
||||
/* Navigation block */
|
||||
#ul_menu {
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
border-color: #fff;
|
||||
}
|
||||
#ul_menu li {
|
||||
margin: 1px;
|
||||
float: left;
|
||||
position: relative;
|
||||
list-style: none;
|
||||
}
|
||||
#ul_menu a {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 8px 8px 6px 8px;
|
||||
border: solid 1px transparent;
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
#ul_menu a:hover {
|
||||
box-shadow: inset 0 0 10px rgba(0,0,0,0.5);
|
||||
}
|
||||
#ul_menu .current a,
|
||||
#ul_menu li:hover > a {
|
||||
background-color: #fff;
|
||||
border: solid 1px #000;
|
||||
}
|
||||
#ul_menu li:hover > #div_menu {
|
||||
visibility: visible;
|
||||
opacity: 0.95;
|
||||
}
|
||||
#ul_menu li img {
|
||||
width: 25px;
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
#ul_menu li:hover > a img {
|
||||
-webkit-filter: invert(0) !important;
|
||||
filter: invert(0) !important;
|
||||
}
|
||||
#ul_menu #div_menu {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
min-width: 700px;
|
||||
min-height: 100px;
|
||||
max-height: calc(100vh - 80px);
|
||||
max-width: calc(100vw - 80px);
|
||||
overflow: auto;
|
||||
padding: 5px;
|
||||
border: 1px solid #000;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
z-index: 1000;
|
||||
margin-top: -1px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
#ul_menu #div_menu a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.div_menu_block {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.div_menu_block_caption {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Menu item */
|
||||
.div_m_item {
|
||||
float: left;
|
||||
min-height: 120px;
|
||||
width: 100px;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.div_m_item:hover {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
transition: all 0.5s ease-out 0.1s;
|
||||
}
|
||||
.div_m_item_footer {
|
||||
text-align: center;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.menu_icon {
|
||||
height: 64px !important;
|
||||
width: 64px !important;
|
||||
border-width: 0;
|
||||
-webkit-filter: invert(0) !important;
|
||||
filter: invert(0) !important;
|
||||
}
|
||||
|
||||
/* Widget div block */
|
||||
.div_widget {
|
||||
border: solid #888 1px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 5px;
|
||||
vertical-align: top;
|
||||
/* float: left; */
|
||||
/* min-width: 900px; */
|
||||
min-height: 100px;
|
||||
width: 600px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.div_widget_type_a {
|
||||
border: solid #888 1px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 5px;
|
||||
vertical-align: top;
|
||||
/* float: left; */
|
||||
/* min-width: 900px; */
|
||||
min-height: 328px;
|
||||
width: 400px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.div_widget_type_b {
|
||||
border: solid #888 1px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 5px;
|
||||
vertical-align: top;
|
||||
/* float: left; */
|
||||
/* min-width: 900px; */
|
||||
min-height: 330px;
|
||||
width: 600px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.div_widget_full_width {
|
||||
border: solid #888 1px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 5px;
|
||||
vertical-align: top;
|
||||
/* float: left; */
|
||||
/* min-width: 900px; */
|
||||
min-height: 330px;
|
||||
width: calc(100% - 10px);
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.div_w_head {
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px 4px 0 0;
|
||||
color: #fff;
|
||||
/* background-color: rgba(10, 110, 180, 0.5); */
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
box-shadow: inset 0 0 4px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.div_w_content_container {
|
||||
overflow: auto;
|
||||
max-height: 300px; /* 500 */
|
||||
}
|
||||
|
||||
/* Info table block */
|
||||
/*.tbl_info {float: left !important;} */
|
||||
.tbl_info table {
|
||||
border-spacing: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
.tbl_info th {
|
||||
color: #fff;
|
||||
background-color: #555;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
}
|
||||
.tbl_info td {padding: 2px 5px;}
|
||||
.tbl_info .even_line {background-color: #ccc;}
|
||||
|
||||
/* Canvas block */
|
||||
.canvas_info {
|
||||
width: 400px;
|
||||
min-height: 209px;
|
||||
background-color: #000;
|
||||
}
|
||||
.canvas_legend {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
margin: 0 5px 5px 5px;
|
||||
}
|
||||
|
||||
.app_widget {
|
||||
display: inherit !important;
|
||||
/* float: inherit !important; */
|
||||
height: calc(100% - 100px);
|
||||
width: calc(100% - 10px) !important;
|
||||
}
|
||||
.app_widget .div_w_content,
|
||||
.app_widget .div_w_content_container {
|
||||
height: calc(100% - 18px);
|
||||
overflow: hidden !important;
|
||||
max-height: inherit !important;
|
||||
}
|
||||
.app_widget iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Language selector */
|
||||
input, select {border: solid 1px #999;}
|
||||
|
||||
.select_lang {
|
||||
/* margin-left: 0 !important;
|
||||
border: solid 1px #999;
|
||||
float: right; */
|
||||
position : absolute;
|
||||
top : 22px;
|
||||
right : 20px;
|
||||
padding : 0 5px 0 20px;
|
||||
border : 0;
|
||||
color : #fff;
|
||||
background-color : transparent;
|
||||
-webkit-appearance : none;
|
||||
-moz-appearance : none;
|
||||
appearance : none;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
2
css/core.min.css
vendored
Normal file
BIN
gfx/bg.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
gfx/buttons/delete.png
Normal file
|
After Width: | Height: | Size: 807 B |
BIN
gfx/buttons/hires/delete.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
gfx/distros/apple.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
gfx/distros/arch.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
gfx/distros/bsd.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
gfx/distros/debian.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
gfx/distros/fedora.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
gfx/distros/hires/apple.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
gfx/distros/hires/arch.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
gfx/distros/hires/bsd.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
gfx/distros/hires/debian.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
gfx/distros/hires/fedora.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
gfx/distros/hires/linux.svg.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
gfx/distros/hires/opensuse.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
gfx/distros/hires/ubuntu.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
gfx/distros/linux.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
gfx/distros/opensuse.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
gfx/distros/ubuntu.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
gfx/distros/unknown.png
Normal file
|
After Width: | Height: | Size: 126 B |
BIN
gfx/flags/russian-16x16.png
Normal file
|
After Width: | Height: | Size: 352 B |
BIN
gfx/flags/uk-16x16.png
Normal file
|
After Width: | Height: | Size: 847 B |
BIN
gfx/hires/menu.png
Normal file
|
After Width: | Height: | Size: 370 KiB |
BIN
gfx/icons/about.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
gfx/icons/attention.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
gfx/icons/help.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
gfx/icons/hires/ico-about.png
Normal file
|
After Width: | Height: | Size: 243 KiB |
BIN
gfx/icons/hires/ico-attention.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
gfx/icons/hires/ico-help.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
gfx/icons/hires/ico-help2.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
gfx/icons/hires/ico-network.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
gfx/icons/hires/ico-reboot.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
gfx/icons/hires/ico-reboot2.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
gfx/icons/hires/ico-server.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
gfx/icons/hires/ico-settings.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
gfx/icons/hires/ico-settings2.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
gfx/icons/hires/ico-shutdown.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
gfx/icons/hires/ico-storage.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
gfx/icons/hires/ico-sysinfo.png
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
gfx/icons/hires/ico_loading.gif
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
gfx/icons/hires/network2.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
gfx/icons/hires/samba.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
gfx/icons/loading.gif
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
gfx/icons/network.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
gfx/icons/reboot.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
gfx/icons/samba.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
gfx/icons/server.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
gfx/icons/settings.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
gfx/icons/shutdown.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
gfx/icons/storage.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
gfx/icons/sysinfo.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
gfx/menu.png
Normal file
|
After Width: | Height: | Size: 356 B |
38
index.dev.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Control panel</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=0.8, user-scalable=yes, maximum-scale=1.0"/>
|
||||
<link rel="stylesheet" href="css/core.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<header id="app_header">
|
||||
<nav>
|
||||
<ul id="ul_menu">
|
||||
<li><a href="#"><img alt="Menu" src="gfx/menu.png"></a>
|
||||
<div id="div_menu">
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div id="s_header">Loading...</div>
|
||||
<div id="div_attention" class="hidden">
|
||||
<ul id="ul_attention">
|
||||
<li><a href="#"><img alt="Attention" src="gfx/icons/attention.png"></a>
|
||||
<div id="div_attention_content"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
<div id="page_content">
|
||||
<noscript class="no_script_message">
|
||||
<img src="gfx/flags/russian-16x16.png" alt="Русский"> Панель управления не работает с отключенным JavaScript.
|
||||
<hr>
|
||||
<img src="gfx/flags/uk-16x16.png" alt="English"> Control panel can't operate with disabled JavaScript.
|
||||
</noscript>
|
||||
</div>
|
||||
<script src="js/smoothie.js"></script>
|
||||
<script src="js/core.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
2
index.html
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
<!doctype html><html><head><title>Control panel</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, height=device-height, initial-scale=0.8, user-scalable=yes, maximum-scale=1.0"/><link rel="stylesheet" href="css/core.css" type="text/css"/></head><body><header id="app_header"><nav><ul id="ul_menu"><li><a href="#"><img alt="Menu" src="gfx/menu.png"></a><div id="div_menu"></div></li></ul></nav><div id="s_header">Loading...</div><div id="div_attention" class="hidden"><ul id="ul_attention"><li><a href="#"><img alt="Attention" src="gfx/icons/attention.png"></a><div id="div_attention_content"></div></li></ul></div></header><div id="page_content"><noscript class="no_script_message"><img src="gfx/flags/russian-16x16.png" alt="Русский"> Панель управления не работает с отключенным JavaScript. <hr><img src="gfx/flags/uk-16x16.png" alt="English"> Control panel can't operate with disabled JavaScript. </noscript></div><script src="js/smoothie.js"></script><script src="js/core.js"></script></body></html>
|
||||
2276
js/core.js
Normal file
1047
js/smoothie.js
Normal file
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>
|
||||