spectrum2_manager server: Allow serving static content
This commit is contained in:
parent
5d3244bd8b
commit
8f5a0d64f2
10 changed files with 744 additions and 175 deletions
|
@ -17,3 +17,8 @@ INSTALL(FILES
|
|||
spectrum_manager.cfg
|
||||
DESTINATION /etc/spectrum2
|
||||
)
|
||||
|
||||
INSTALL(DIRECTORY
|
||||
html
|
||||
DESTINATION /var/lib/spectrum2_manager
|
||||
)
|
||||
|
|
10
spectrum_manager/src/html/footer.html
Normal file
10
spectrum_manager/src/html/footer.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
</section>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div id="footer_wrap" class="outer">
|
||||
<footer class="inner">
|
||||
<p class="copyright">Spectrum 2 developed by <a href="https://github.com/hanzz">Jan Kaluza - HanzZ</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
</body></html>
|
84
spectrum_manager/src/html/form.css
Normal file
84
spectrum_manager/src/html/form.css
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* Basic Grey */
|
||||
.basic-grey {
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
max-width: 500px;
|
||||
background: #F7F7F7;
|
||||
padding: 25px 15px 25px 10px;
|
||||
font: 12px Georgia, "Times New Roman", Times, serif;
|
||||
color: #888;
|
||||
text-shadow: 1px 1px 1px #FFF;
|
||||
border:1px solid #E4E4E4;
|
||||
}
|
||||
.basic-grey h1 {
|
||||
font-size: 25px;
|
||||
padding: 0px 0px 10px 40px;
|
||||
display: block;
|
||||
border-bottom:1px solid #E4E4E4;
|
||||
margin: -10px -15px 30px -10px;;
|
||||
color: #888;
|
||||
}
|
||||
.basic-grey h1>span {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
}
|
||||
.basic-grey label {
|
||||
display: block;
|
||||
margin: 0px;
|
||||
}
|
||||
.basic-grey label>span {
|
||||
float: left;
|
||||
width: 20%;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
margin-top: 10px;
|
||||
color: #888;
|
||||
}
|
||||
.basic-grey input[type="text"], .basic-grey input[type="email"], .basic-grey input[type="password"], .basic-grey textarea, .basic-grey select {
|
||||
border: 1px solid #DADADA;
|
||||
color: #888;
|
||||
height: 30px;
|
||||
margin-bottom: 16px;
|
||||
margin-right: 6px;
|
||||
margin-top: 2px;
|
||||
outline: 0 none;
|
||||
padding: 3px 3px 3px 5px;
|
||||
width: 70%;
|
||||
font-size: 12px;
|
||||
line-height:15px;
|
||||
box-shadow: inset 0px 1px 4px #ECECEC;
|
||||
-moz-box-shadow: inset 0px 1px 4px #ECECEC;
|
||||
-webkit-box-shadow: inset 0px 1px 4px #ECECEC;
|
||||
}
|
||||
.basic-grey textarea{
|
||||
padding: 5px 3px 3px 5px;
|
||||
}
|
||||
.basic-grey select {
|
||||
background: #FFF url('down-arrow.png') no-repeat right;
|
||||
background: #FFF url('down-arrow.png') no-repeat right);
|
||||
appearance:none;
|
||||
-webkit-appearance:none;
|
||||
-moz-appearance: none;
|
||||
text-indent: 0.01px;
|
||||
text-overflow: '';
|
||||
width: 70%;
|
||||
height: 35px;
|
||||
line-height: 25px;
|
||||
}
|
||||
.basic-grey textarea{
|
||||
height:100px;
|
||||
}
|
||||
.basic-grey .button {
|
||||
background: #E27575;
|
||||
border: none;
|
||||
padding: 10px 25px 10px 25px;
|
||||
color: #FFF;
|
||||
box-shadow: 1px 1px 5px #B6B6B6;
|
||||
border-radius: 3px;
|
||||
text-shadow: 1px 1px 1px #9E3F3F;
|
||||
cursor: pointer;
|
||||
}
|
||||
.basic-grey .button:hover {
|
||||
background: #CF7A7A
|
||||
}
|
||||
|
32
spectrum_manager/src/html/header.html
Normal file
32
spectrum_manager/src/html/header.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports">
|
||||
|
||||
<link href="/style.css" rel="stylesheet" type="text/css" media="all">
|
||||
<link href="/form.css" rel="stylesheet" type="text/css" media="all">
|
||||
|
||||
<title>Spectrum 2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
<header class="inner">
|
||||
|
||||
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;">
|
||||
|
||||
<section id="menu" style="text-align: center;">
|
||||
<a class="menuitem" href="/">Home</a>
|
||||
<a class="menuitem" href="/users">Users</a>
|
||||
<a class="menuitem" href="/instances">Instances</a>
|
||||
</section>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<div id="main_content_wrap" class="outer">
|
||||
<section id="main_content" class="inner">
|
71
spectrum_manager/src/html/login/index.html
Normal file
71
spectrum_manager/src/html/login/index.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="description" content="Spectrum 2 : Spectrum 2 IM transports">
|
||||
|
||||
<link href="/style.css" rel="stylesheet" type="text/css" media="all">
|
||||
<link href="/form.css" rel="stylesheet" type="text/css" media="all">
|
||||
|
||||
<title>Spectrum 2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
<header class="inner">
|
||||
|
||||
<img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;">
|
||||
|
||||
<!-- <section id="menu" style="text-align: center;">
|
||||
<a class="menuitem" href="http://spectrum.im/">About</a>
|
||||
<a class="menuitem" href="http://slack.spectrum.im/">Add Spectrum 2 to my Slack Team</a>
|
||||
<a class="menuitem" href="http://spectrum.im/documentation">Documentation</a>
|
||||
<a class="menuitem" href="http://spectrum.im/download">Download</a>
|
||||
<a class="menuitem" href="http://spectrum.im/discussion">Discussion</a>
|
||||
<a class="menuitem" href="https://github.com/hanzz/spectrum2/issues">Issue tracker</a>
|
||||
</section>-->
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<div id="main_content_wrap" class="outer">
|
||||
<section id="main_content" class="inner">
|
||||
|
||||
|
||||
<form action="/authorize" class="basic-grey" method="POST">
|
||||
<h1>Login form
|
||||
<span>Use your username and password to login to Spectrum 2 Manager.</span>
|
||||
</h1>
|
||||
<label>
|
||||
<span>Username:</span>
|
||||
<input type="text" id="user" name="user" placeholder="Username"></textarea>
|
||||
</label>
|
||||
<label>
|
||||
<span>Password:</span>
|
||||
<input type="password" id="password" name="password" placeholder="Password"></textarea>
|
||||
</label>
|
||||
<label>
|
||||
<span> </span>
|
||||
<input type="submit" class="button" value="Login" />
|
||||
</label>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div id="footer_wrap" class="outer">
|
||||
<footer class="inner">
|
||||
<p class="copyright">Spectrum 2 developed by <a href="https://github.com/hanzz">Jan Kaluza - HanzZ</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body></html>
|
BIN
spectrum_manager/src/html/logo.png
Normal file
BIN
spectrum_manager/src/html/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
465
spectrum_manager/src/html/style.css
Normal file
465
spectrum_manager/src/html/style.css
Normal file
|
@ -0,0 +1,465 @@
|
|||
/*******************************************************************************
|
||||
Slate Theme for Github Pages
|
||||
by Jason Costello, @jsncostello
|
||||
*******************************************************************************/
|
||||
|
||||
@import url(pygment_trac.css);
|
||||
|
||||
/*******************************************************************************
|
||||
MeyerWeb Reset
|
||||
*******************************************************************************/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Theme Styles
|
||||
*******************************************************************************/
|
||||
|
||||
body {
|
||||
box-sizing: border-box;
|
||||
color:#373737;
|
||||
background: #212121;
|
||||
font-size: 16px;
|
||||
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 10px 0;
|
||||
font-weight: 700;
|
||||
color:#222222;
|
||||
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-bottom: 10px;
|
||||
font-size: 32px;
|
||||
background: url('../images/bg_hr.png') repeat-x bottom;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0 15px 0;
|
||||
}
|
||||
|
||||
footer p {
|
||||
color: #f2f2f2;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #007edf;
|
||||
text-shadow: none;
|
||||
|
||||
transition: color 0.5s ease;
|
||||
transition: text-shadow 0.5s ease;
|
||||
-webkit-transition: color 0.5s ease;
|
||||
-webkit-transition: text-shadow 0.5s ease;
|
||||
-moz-transition: color 0.5s ease;
|
||||
-moz-transition: text-shadow 0.5s ease;
|
||||
-o-transition: color 0.5s ease;
|
||||
-o-transition: text-shadow 0.5s ease;
|
||||
-ms-transition: color 0.5s ease;
|
||||
-ms-transition: text-shadow 0.5s ease;
|
||||
}
|
||||
|
||||
#main_content a:hover {
|
||||
color: #0069ba;
|
||||
text-shadow: #0090ff 0px 0px 2px;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #43adff;
|
||||
text-shadow: #0090ff 0px 0px 2px;
|
||||
}
|
||||
|
||||
#menu a:hover {
|
||||
color: #212121;
|
||||
text-shadow: #0090ff 0px 0px 2px;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
max-width: 739px;
|
||||
padding: 5px;
|
||||
margin: 10px 0 10px 0;
|
||||
/* border: 1px solid #ebebeb;
|
||||
|
||||
box-shadow: 0 0 5px #ebebeb;
|
||||
-webkit-box-shadow: 0 0 5px #ebebeb;
|
||||
-moz-box-shadow: 0 0 5px #ebebeb;
|
||||
-o-box-shadow: 0 0 5px #ebebeb;
|
||||
-ms-box-shadow: 0 0 5px #ebebeb;*/
|
||||
}
|
||||
|
||||
header img {
|
||||
border: 0;
|
||||
box-shadow: 0 0 0px #ebebeb;
|
||||
-webkit-box-shadow: 0 0 0px #ebebeb;
|
||||
-moz-box-shadow: 0 0 0px #ebebeb;
|
||||
-o-box-shadow: 0 0 0px #ebebeb;
|
||||
-ms-box-shadow: 0 0 0px #ebebeb;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
width: 100%;
|
||||
color: #222;
|
||||
background-color: #fff;
|
||||
|
||||
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
|
||||
font-size: 14px;
|
||||
|
||||
border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 3px;
|
||||
margin: 0 3px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: block;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #666;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 0 0 20px;
|
||||
border-left: 3px solid #bbb;
|
||||
}
|
||||
|
||||
ul, ol, dl {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
ul li {
|
||||
list-style: inside;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
ol li {
|
||||
list-style: decimal inside;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
padding-left: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dl p {
|
||||
padding-left: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 1px;
|
||||
margin-bottom: 5px;
|
||||
border: none;
|
||||
background: url('../images/bg_hr.png') repeat-x center;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid #373737;
|
||||
margin-bottom: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
padding: 5px;
|
||||
background: #373737;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 3px;
|
||||
border: 1px solid #373737;
|
||||
}
|
||||
|
||||
form {
|
||||
background: #f2f2f2;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
/* width: 100%; */
|
||||
max-width: 100%;
|
||||
display:block ; margin:0 auto ;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Full-Width Styles
|
||||
*******************************************************************************/
|
||||
|
||||
.outer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inner {
|
||||
position: relative;
|
||||
max-width: 880px;
|
||||
padding: 20px 10px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#forkme_banner {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top:0;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
padding: 10px 50px 10px 10px;
|
||||
color: #fff;
|
||||
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.5);
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
#header_wrap {
|
||||
background: #212121;
|
||||
background: -moz-linear-gradient(top, #373737, #212121);
|
||||
background: -webkit-linear-gradient(top, #373737, #212121);
|
||||
background: -ms-linear-gradient(top, #373737, #212121);
|
||||
background: -o-linear-gradient(top, #373737, #212121);
|
||||
background: linear-gradient(top, #373737, #212121);
|
||||
}
|
||||
|
||||
#header_wrap .inner {
|
||||
padding: 50px 10px 30px 10px;
|
||||
}
|
||||
|
||||
#project_title {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 42px;
|
||||
font-weight: 700;
|
||||
text-shadow: #111 0px 0px 10px;
|
||||
}
|
||||
|
||||
#project_tagline {
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
background: none;
|
||||
text-shadow: #111 0px 0px 10px;
|
||||
}
|
||||
|
||||
#downloads {
|
||||
position: absolute;
|
||||
width: 210px;
|
||||
z-index: 10;
|
||||
bottom: -40px;
|
||||
right: 0;
|
||||
height: 70px;
|
||||
background: url('../images/icon_download.png') no-repeat 0% 90%;
|
||||
}
|
||||
|
||||
#menu {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
bottom: -20px;
|
||||
left: 0;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.menuitem {
|
||||
margin:0;
|
||||
margin-right:7px;
|
||||
color:white;
|
||||
padding:10px;
|
||||
height: 35px;
|
||||
background: #0090FF;
|
||||
}
|
||||
|
||||
.zip_download_link {
|
||||
display: block;
|
||||
float: right;
|
||||
width: 90px;
|
||||
height:70px;
|
||||
text-indent: -5000px;
|
||||
overflow: hidden;
|
||||
background: url(../images/sprite_download.png) no-repeat bottom left;
|
||||
}
|
||||
|
||||
.tar_download_link {
|
||||
display: block;
|
||||
float: right;
|
||||
width: 90px;
|
||||
height:70px;
|
||||
text-indent: -5000px;
|
||||
overflow: hidden;
|
||||
background: url(../images/sprite_download.png) no-repeat bottom right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.zip_download_link:hover {
|
||||
background: url(../images/sprite_download.png) no-repeat top left;
|
||||
}
|
||||
|
||||
.tar_download_link:hover {
|
||||
background: url(../images/sprite_download.png) no-repeat top right;
|
||||
}
|
||||
|
||||
#main_content_wrap {
|
||||
background: #f2f2f2;
|
||||
border-top: 1px solid #111;
|
||||
border-bottom: 1px solid #111;
|
||||
}
|
||||
|
||||
#main_content {
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
#footer_wrap {
|
||||
background: #212121;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Small Device Styles
|
||||
*******************************************************************************/
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
body {
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
#downloads {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inner {
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
#project_title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ bool ManagerConfig::load(const std::string &configfile, boost::program_options::
|
|||
("service.admin_password", value<std::string>()->default_value(""), "Administrator password.")
|
||||
("service.port", value<int>()->default_value(8081), "Web interface port.")
|
||||
("service.config_directory", value<std::string>()->default_value("/etc/spectrum2/transports/"), "Directory with spectrum2 configuration files. One .cfg file per one instance")
|
||||
("service.data_dir", value<std::string>()->default_value("/var/lib/spectrum2_manager"), "Directory to store Spectrum 2 manager data")
|
||||
("servers.server", value<std::vector<std::string> >()->multitoken(), "Server.")
|
||||
;
|
||||
|
||||
|
|
|
@ -8,123 +8,18 @@
|
|||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
|
||||
#define SESSION_TTL 120
|
||||
|
||||
static std::string get_header() {
|
||||
return "\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> \
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" dir=\"ltr\"> \
|
||||
<head>\
|
||||
<title>Spectrum 2 web interface</title>\
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/>\
|
||||
<style type=\"text/css\">\
|
||||
body{ background-color: #F9F9F9; color: #444444; font: normal normal 14px \"Helvetica\", \"Arial\", Sans-Serif; }\
|
||||
\
|
||||
pre, kbd, var, samp, tt{ font-family: \"Courier\", Monospace; }\
|
||||
\
|
||||
pre { font-size: 12px; }\
|
||||
\
|
||||
h1, h2, h3, h4, h5, h6, pre{ color: #094776; }\
|
||||
\
|
||||
h1{ font-size: 28px; }\
|
||||
\
|
||||
h2{ font-size: 24px; font-weight: normal; }\
|
||||
\
|
||||
h1, h2, h3, h4, h5, h6{ margin-bottom: 20px; }\
|
||||
\
|
||||
h2, h3{ border-bottom: 2px solid #EEEEEE; padding: 0 0 3px; } \
|
||||
\
|
||||
h3{ border-color: #E5E5E5; border-width: 1px; }\
|
||||
\
|
||||
h4{ font-size: 18px; }\
|
||||
\
|
||||
h1 a, h2 a{ font-weight: normal; }\
|
||||
\
|
||||
h1 a, h2 a, h3 a{ text-decoration: none; }\
|
||||
\
|
||||
h3, h5, h6{ font-size: 18px; }\
|
||||
\
|
||||
h4, h5, h6{ font-size: 14px; }\
|
||||
\
|
||||
p, dl, ul, ol{ margin: 20px 0; }\
|
||||
\
|
||||
p, dl, ul, ol, h3, h4, h5, h6{ margin-left: 20px; }\
|
||||
\
|
||||
li > ul,\
|
||||
li > ol{ margin: 0; margin-left: 40px; }\
|
||||
\
|
||||
dl > dd{ margin-left: 20px; }\
|
||||
\
|
||||
li > p { margin: 0; }\
|
||||
\
|
||||
p, li, dd, dt, pre{ line-height: 1.5; }\
|
||||
\
|
||||
table {\
|
||||
border-collapse: collapse;\
|
||||
margin-bottom: 20px;\
|
||||
margin-left:20px;\
|
||||
}\
|
||||
\
|
||||
th {\
|
||||
padding: 0 0.5em;\
|
||||
text-align: center;\
|
||||
}\
|
||||
\
|
||||
th {\
|
||||
border: 1px solid #FB7A31;\
|
||||
background: #FFC;\
|
||||
}\
|
||||
\
|
||||
td {\
|
||||
border-bottom: 1px solid #CCC;\
|
||||
border-right: 1px solid #CCC;\
|
||||
border-left: 1px solid #CCC;\
|
||||
padding: 0 0.5em;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
a:link,\
|
||||
a:visited{ color: #1A5B8D; }\
|
||||
\
|
||||
a:hover,\
|
||||
a:active{ color: #742CAC; }\
|
||||
\
|
||||
a.headerlink{ visibility: hidden; }\
|
||||
\
|
||||
:hover > a.headerlink { visibility: visible; }\
|
||||
\
|
||||
a img{ \
|
||||
border: 0;\
|
||||
outline: 0;\
|
||||
}\
|
||||
\
|
||||
img{ display: block; max-width: 100%; }\
|
||||
\
|
||||
code {\
|
||||
border: 1px solid #FB7A31;\
|
||||
background: #FFC;\
|
||||
}\
|
||||
\
|
||||
pre {\
|
||||
white-space: pre-wrap;\
|
||||
white-space: -moz-pre-wrap;\
|
||||
white-space: -o-pre-wrap;\
|
||||
border: 1px solid #FB7A31;\
|
||||
background: #FFC;\
|
||||
padding:5px;\
|
||||
padding-left: 15px;\
|
||||
}\
|
||||
\
|
||||
</style>\
|
||||
</head><body><h1>Spectrum 2 web interface</h1>";
|
||||
}
|
||||
static struct mg_serve_http_opts s_http_server_opts;
|
||||
|
||||
|
||||
static void get_qsvar(const struct http_message *hm,
|
||||
const char *name, char *dst, size_t dst_len) {
|
||||
mg_get_http_var(&hm->query_string, name, dst, dst_len);
|
||||
mg_get_http_var(&hm->body, name, dst, dst_len);
|
||||
}
|
||||
|
||||
static void my_strlcpy(char *dst, const char *src, size_t len) {
|
||||
|
@ -153,6 +48,26 @@ Server::Server(ManagerConfig *config) {
|
|||
mg_mgr_init(&m_mgr, this);
|
||||
m_nc = mg_bind(&m_mgr, std::string(":" + boost::lexical_cast<std::string>(CONFIG_INT(m_config, "service.port"))).c_str(), &_event_handler);
|
||||
mg_set_protocol_http_websocket(m_nc);
|
||||
|
||||
s_http_server_opts.document_root = CONFIG_STRING(m_config, "service.data_dir").c_str();
|
||||
|
||||
std::ifstream header(std::string(CONFIG_STRING(m_config, "service.data_dir") + "/header.html").c_str(), std::ios::in);
|
||||
if (header) {
|
||||
header.seekg(0, std::ios::end);
|
||||
m_header.resize(header.tellg());
|
||||
header.seekg(0, std::ios::beg);
|
||||
header.read(&m_header[0], m_header.size());
|
||||
header.close();
|
||||
}
|
||||
|
||||
std::ifstream footer(std::string(CONFIG_STRING(m_config, "service.data_dir") + "/footer.html").c_str(), std::ios::in);
|
||||
if (footer) {
|
||||
footer.seekg(0, std::ios::end);
|
||||
m_footer.resize(footer.tellg());
|
||||
footer.seekg(0, std::ios::beg);
|
||||
footer.read(&m_footer[0], m_footer.size());
|
||||
footer.close();
|
||||
}
|
||||
}
|
||||
|
||||
Server::~Server() {
|
||||
|
@ -179,6 +94,7 @@ Server::session *Server::new_session(const char *user) {
|
|||
snprintf(session->random, sizeof(session->random), "%d", rand());
|
||||
generate_session_id(session->session_id, session->random, session->user);
|
||||
session->expire = time(0) + SESSION_TTL;
|
||||
session->admin = std::string(user) == m_user;
|
||||
|
||||
sessions[session->session_id] = session;
|
||||
return session;
|
||||
|
@ -243,11 +159,14 @@ bool Server::is_authorized(const struct mg_connection *conn, struct http_message
|
|||
|
||||
// Always authorize accesses to login page and to authorize URI
|
||||
if (!mg_vcmp(&hm->uri, "/login") ||
|
||||
!mg_vcmp(&hm->uri, "/login/") ||
|
||||
!mg_vcmp(&hm->uri, "/form.css") ||
|
||||
!mg_vcmp(&hm->uri, "/style.css") ||
|
||||
!mg_vcmp(&hm->uri, "/logo.png") ||
|
||||
!mg_vcmp(&hm->uri, "/authorize")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// pthread_rwlock_rdlock(&rwlock);
|
||||
if ((session = get_session(hm)) != NULL) {
|
||||
generate_session_id(valid_id, session->random, session->user);
|
||||
if (strcmp(valid_id, session->session_id) == 0) {
|
||||
|
@ -255,7 +174,6 @@ bool Server::is_authorized(const struct mg_connection *conn, struct http_message
|
|||
authorized = true;
|
||||
}
|
||||
}
|
||||
// pthread_rwlock_unlock(&rwlock);
|
||||
|
||||
return authorized;
|
||||
}
|
||||
|
@ -272,37 +190,12 @@ void Server::print_html(struct mg_connection *conn, struct http_message *hm, con
|
|||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: %d\r\n" // Always set Content-Length
|
||||
"\r\n"
|
||||
"%s",
|
||||
(int) html.size(), html.c_str());
|
||||
}
|
||||
|
||||
void Server::serve_login(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::string html= "\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> \
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" dir=\"ltr\"> \
|
||||
<head>\
|
||||
<title>Spectrum 2 web interface</title>\
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/>\
|
||||
</head>\
|
||||
<body>\
|
||||
<center>\
|
||||
<h2>Spectrum 2 web interface login</h2>\
|
||||
<br/>\
|
||||
<form action=\"/authorize\">\
|
||||
Username: <input type=\"text\" name=\"user\"></input><br/>\
|
||||
Password: <input type=\"password\" name=\"password\"></input><br/>\
|
||||
<input type=\"submit\" value=\"Login\"></input>\
|
||||
</form>\
|
||||
</center>\
|
||||
</body>\
|
||||
</html>";
|
||||
|
||||
print_html(conn, hm, html);
|
||||
"%s%s%s",
|
||||
(int) html.size() + m_header.size() + m_footer.size(), m_header.c_str(), html.c_str(), m_footer.c_str());
|
||||
}
|
||||
|
||||
void Server::serve_onlineusers(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::string html = get_header();
|
||||
std::string html;
|
||||
char jid[255];
|
||||
get_qsvar(hm, "jid", jid, sizeof(jid));
|
||||
|
||||
|
@ -331,7 +224,7 @@ void Server::serve_onlineusers(struct mg_connection *conn, struct http_message *
|
|||
}
|
||||
|
||||
void Server::serve_cmd(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::string html = get_header();
|
||||
std::string html;
|
||||
char jid[255];
|
||||
get_qsvar(hm, "jid", jid, sizeof(jid));
|
||||
char cmd[4096];
|
||||
|
@ -358,7 +251,7 @@ void Server::serve_cmd(struct mg_connection *conn, struct http_message *hm) {
|
|||
|
||||
|
||||
void Server::serve_start(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::string html= get_header() ;
|
||||
std::string html;
|
||||
char jid[255];
|
||||
get_qsvar(hm, "jid", jid, sizeof(jid));
|
||||
|
||||
|
@ -369,7 +262,7 @@ void Server::serve_start(struct mg_connection *conn, struct http_message *hm) {
|
|||
}
|
||||
|
||||
void Server::serve_stop(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::string html= get_header();
|
||||
std::string html;
|
||||
char jid[255];
|
||||
get_qsvar(hm, "jid", jid, sizeof(jid));
|
||||
|
||||
|
@ -378,40 +271,45 @@ void Server::serve_stop(struct mg_connection *conn, struct http_message *hm) {
|
|||
html += "</body></html>";
|
||||
print_html(conn, hm, html);
|
||||
}
|
||||
|
||||
void Server::serve_root(struct mg_connection *conn, struct http_message *hm) {
|
||||
std::vector<std::string> list = show_list(m_config, false);
|
||||
std::string html= get_header() + "<h2>List of instances</h2><table><tr><th>JID<th>Status</th><th>Command</th><th>Run command</th></tr>";
|
||||
std::string html = "<h2>List of instances</h2>";
|
||||
|
||||
BOOST_FOREACH(std::string &instance, list) {
|
||||
html += "<tr>";
|
||||
html += "<td><a href=\"/onlineusers?jid=" + instance + "\">" + instance + "</a></td>";
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
Swift::BoostNetworkFactories networkFactories(&eventLoop);
|
||||
|
||||
ask_local_server(m_config, networkFactories, instance, "status");
|
||||
eventLoop.runUntilEvents();
|
||||
while(get_response().empty()) {
|
||||
eventLoop.runUntilEvents();
|
||||
}
|
||||
html += "<td>" + get_response() + "</td>";
|
||||
if (get_response().find("Running") == 0) {
|
||||
html += "<td><a href=\"/stop?jid=" + instance + "\">Stop</a></td>";
|
||||
html += "<td><form action=\"/cmd\">";
|
||||
html += "<input type=\"hidden\" name=\"jid\" value=\"" + instance + "\"></input>";
|
||||
html += "<input type=\"text\" name=\"cmd\"></input>";
|
||||
html += "<input type=\"submit\" value=\"Run\"></input>";
|
||||
html += "</form></td>";
|
||||
}
|
||||
else {
|
||||
html += "<td><a href=\"/start?jid=" + instance + "\">Start</a></td>";
|
||||
html += "<td></td>";
|
||||
}
|
||||
|
||||
html += "</tr>";
|
||||
if (list.empty()) {
|
||||
html += "<p>There are no Spectrum 2 instances yet. You can create new instance by adding configuration files into <pre>/etc/spectrum2/transports</pre> directory. You can then maintain the Spectrum 2 instance here.</p>";
|
||||
}
|
||||
else {
|
||||
html += "<table><tr><th>JID<th>Status</th><th>Command</th><th>Run command</th></tr>";
|
||||
BOOST_FOREACH(std::string &instance, list) {
|
||||
html += "<tr>";
|
||||
html += "<td><a href=\"/onlineusers?jid=" + instance + "\">" + instance + "</a></td>";
|
||||
Swift::SimpleEventLoop eventLoop;
|
||||
Swift::BoostNetworkFactories networkFactories(&eventLoop);
|
||||
|
||||
html += "</table></body></html>";
|
||||
ask_local_server(m_config, networkFactories, instance, "status");
|
||||
eventLoop.runUntilEvents();
|
||||
while(get_response().empty()) {
|
||||
eventLoop.runUntilEvents();
|
||||
}
|
||||
html += "<td>" + get_response() + "</td>";
|
||||
if (get_response().find("Running") == 0) {
|
||||
html += "<td><a href=\"/stop?jid=" + instance + "\">Stop</a></td>";
|
||||
html += "<td><form action=\"/cmd\">";
|
||||
html += "<input type=\"hidden\" name=\"jid\" value=\"" + instance + "\"></input>";
|
||||
html += "<input type=\"text\" name=\"cmd\"></input>";
|
||||
html += "<input type=\"submit\" value=\"Run\"></input>";
|
||||
html += "</form></td>";
|
||||
}
|
||||
else {
|
||||
html += "<td><a href=\"/start?jid=" + instance + "\">Start</a></td>";
|
||||
html += "<td></td>";
|
||||
}
|
||||
|
||||
html += "</tr>";
|
||||
}
|
||||
|
||||
html += "</table>";
|
||||
}
|
||||
print_html(conn, hm, html);
|
||||
}
|
||||
|
||||
|
@ -421,12 +319,11 @@ void Server::event_handler(struct mg_connection *conn, int ev, void *p) {
|
|||
if (ev != MG_EV_HTTP_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_authorized(conn, hm)) {
|
||||
redirect_to(conn, hm, "/login");
|
||||
} else if (mg_vcmp(&hm->uri, "/authorize") == 0) {
|
||||
authorize(conn, hm);
|
||||
} else if (mg_vcmp(&hm->uri, "/login") == 0) {
|
||||
serve_login(conn, hm);
|
||||
} else if (mg_vcmp(&hm->uri, "/") == 0) {
|
||||
serve_root(conn, hm);
|
||||
} else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) {
|
||||
|
@ -437,6 +334,8 @@ void Server::event_handler(struct mg_connection *conn, int ev, void *p) {
|
|||
serve_start(conn, hm);
|
||||
} else if (mg_vcmp(&hm->uri, "/stop") == 0) {
|
||||
serve_stop(conn, hm);
|
||||
} else {
|
||||
mg_serve_http(conn, hm, s_http_server_opts);
|
||||
}
|
||||
|
||||
conn->flags |= MG_F_SEND_AND_CLOSE;
|
||||
|
|
|
@ -38,6 +38,7 @@ class Server {
|
|||
char random[20]; // Random data used for extra user validation
|
||||
char user[255]; // Authenticated user
|
||||
time_t expire; // Expiration timestamp, UTC
|
||||
bool admin;
|
||||
};
|
||||
|
||||
/// Constructor.
|
||||
|
@ -51,7 +52,6 @@ class Server {
|
|||
void event_handler(struct mg_connection *nc, int ev, void *p);
|
||||
|
||||
private:
|
||||
void serve_login(struct mg_connection *conn, struct http_message *hm);
|
||||
void serve_root(struct mg_connection *conn, struct http_message *hm);
|
||||
void serve_start(struct mg_connection *conn, struct http_message *hm);
|
||||
void serve_stop(struct mg_connection *conn, struct http_message *hm);
|
||||
|
@ -78,4 +78,6 @@ class Server {
|
|||
std::string m_user;
|
||||
std::string m_password;
|
||||
ManagerConfig *m_config;
|
||||
std::string m_header;
|
||||
std::string m_footer;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue