commit
b1cc1451d4
BIN
MCServer/webadmin/files/background.gif
Normal file
BIN
MCServer/webadmin/files/background.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 B |
BIN
MCServer/webadmin/files/favicon.ico
Normal file
BIN
MCServer/webadmin/files/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
MCServer/webadmin/files/logo.png
Normal file
BIN
MCServer/webadmin/files/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
MCServer/webadmin/files/mc-logo.png
Normal file
BIN
MCServer/webadmin/files/mc-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
326
MCServer/webadmin/files/style.css
Normal file
326
MCServer/webadmin/files/style.css
Normal file
@ -0,0 +1,326 @@
|
||||
/* reset CSS */
|
||||
|
||||
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, font, 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 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
background: transparent;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
/* remember to define focus styles! */
|
||||
:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* remove textarea resize at Safari */
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
/* remember to highlight inserts somehow! */
|
||||
ins {
|
||||
text-decoration: none;
|
||||
}
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* tables still need 'cellspacing="0"' in the markup */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Origional from http://www.perspectived.com/
|
||||
Modified by Ben Phelps
|
||||
Made for FakeTruth - MCServer
|
||||
*/
|
||||
|
||||
/* Basic ---------------------------------------- */
|
||||
|
||||
.clear { clear: both; }
|
||||
|
||||
body {
|
||||
background: white;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
color: #646464;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
text-align: left;
|
||||
width: 930px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Logo ---------------------------------------- */
|
||||
|
||||
h1 {
|
||||
margin: 15px 0 10px 5px;
|
||||
width: 180px;
|
||||
height: 36px;
|
||||
background: url(logo.png) no-repeat left top;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
display: block;
|
||||
width: 225px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
h1 span { display: none; }
|
||||
|
||||
a {
|
||||
color: #646464;
|
||||
}
|
||||
|
||||
/* Container ---------------------------------------- */
|
||||
|
||||
#containerHolder {
|
||||
background: #eee;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
#container {
|
||||
background: #fff url(background.gif) repeat-y left top;
|
||||
border: 1px solid #ddd;
|
||||
width: 918px;
|
||||
|
||||
}
|
||||
|
||||
#connectHolder {
|
||||
background: #eee;
|
||||
padding: 5px;
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
|
||||
#connect {
|
||||
border: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
padding:5px;
|
||||
width: 908px;
|
||||
}
|
||||
|
||||
.pics {
|
||||
height: 375px;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
.pics img {
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #eee;
|
||||
width: 600px;
|
||||
height: 375px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/* Login -------------------------------------- */
|
||||
|
||||
#loginLogo {
|
||||
margin: 0 auto;
|
||||
margin-top:100px;
|
||||
width: 180px;
|
||||
height: 36px;
|
||||
background-image: url(logo.png);
|
||||
}
|
||||
|
||||
#loginHolder {
|
||||
background: #eee;
|
||||
padding: 5px;
|
||||
width: 310px;
|
||||
margin: 0 auto;
|
||||
height: 90px;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
#login {
|
||||
padding:10px;
|
||||
width: 288px;
|
||||
height: 68px;
|
||||
border: 1px solid #ddd;
|
||||
background:#fff;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
/* Sidebar ---------------------------------------- */
|
||||
|
||||
#sidebar {
|
||||
width: 179px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#sidebar .sideNav { width: 179px; }
|
||||
|
||||
#sidebar .sideNav li { border-bottom: 1px solid #ddd; width: 179px; }
|
||||
|
||||
#sidebar .sideNav li a {
|
||||
display: block;
|
||||
color: #646464;
|
||||
background: #f6f6f6;
|
||||
text-decoration: none;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
padding: 0 19px;
|
||||
width: 141px;
|
||||
}
|
||||
|
||||
#sidebar .sideNav li a:hover { background: #fdfcf6; }
|
||||
|
||||
#sidebar .sideNav li a.active, #sidebar .sideNav li a.active:hover {
|
||||
background: #f0f7fa;
|
||||
color: #c66653;
|
||||
}
|
||||
|
||||
/* Breadcrumb ---------------------------------------- */
|
||||
|
||||
h2 {
|
||||
width: 718px;
|
||||
float: right;
|
||||
color: #646464;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
margin: 20px 0 0 0;
|
||||
padding: 0 0 10px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
h2 a {
|
||||
color: #646464;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h2 a.active { color: #c66653; }
|
||||
|
||||
h2 a:hover { text-decoration: underline; }
|
||||
|
||||
/* Content ---------------------------------------- */
|
||||
|
||||
#main {
|
||||
width: 700px;
|
||||
float: right;
|
||||
padding: 0 19px 0 0;
|
||||
}
|
||||
|
||||
#main p {
|
||||
|
||||
padding: 10px;
|
||||
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
color: #5494af;
|
||||
padding: 0 0 0 10px;
|
||||
margin: 20px 0 10px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
padding: 0 0 0 10px;
|
||||
margin: 20px 0 10px;
|
||||
}
|
||||
|
||||
#main ul {
|
||||
padding: 0 0 0 10px;
|
||||
list-style-type: circle;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#main table {
|
||||
border-top: 1px solid #ddd;
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
#main table tr th {
|
||||
text-align: left;
|
||||
background: #f6f6f6;
|
||||
padding: 0px 20px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#main table tr td {
|
||||
background: #f6f6f6;
|
||||
padding: 0px 20px;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#main table tr.odd td {
|
||||
background: #fbfbfb;
|
||||
}
|
||||
|
||||
#main table tr:hover td { background: #fdfcf6; }
|
||||
|
||||
#main table .action {
|
||||
text-align: right;
|
||||
padding: 0 20px 0 10px;
|
||||
}
|
||||
|
||||
#main table tr .action a { margin: 0 0 0 10px; text-decoration: none; color: #9b9b9b; }
|
||||
#main table tr:hover .action .edit { color: #c5a059; }
|
||||
#main table tr:hover .action .delete { color: #a02b2b; }
|
||||
#main table tr:hover .action .view { color: #55a34a; }
|
||||
|
||||
#main table tr:hover .action a:hover { text-decoration: underline; }
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #ddd;
|
||||
padding: 19px;
|
||||
margin: 0 0 20px 0;
|
||||
background: #fbfbfb;
|
||||
}
|
||||
|
||||
form p { margin: 0 0 14px 0; float: left; width: 100%; }
|
||||
|
||||
label {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0 0 7px 0;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
/* Footer ---------------------------------------- */
|
||||
|
||||
#footer {
|
||||
margin: 10px 0 30px 0;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
color: #9B9B9B;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
#footer a { color: #9B9B9B; }
|
||||
|
||||
#footer a:hover { text-decoration: none; }
|
25
MCServer/webadmin/login_template.html
Normal file
25
MCServer/webadmin/login_template.html
Normal file
@ -0,0 +1,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>MCServer WebAdmin - Login</title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<style type="text/css">
|
||||
header {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<img src="mc-logo.png" alt="MCServer Logo" class="logo">
|
||||
<h1>MCServer - WebAdmin</h1>
|
||||
<form method="get" action="webadmin/">
|
||||
<input type="submit" value="Log in">
|
||||
</form>
|
||||
</header>
|
||||
</body>
|
||||
|
||||
</html>
|
File diff suppressed because one or more lines are too long
142
src/WebAdmin.cpp
142
src/WebAdmin.cpp
@ -131,8 +131,24 @@ bool cWebAdmin::Start(void)
|
||||
m_TemplateScript.RegisterAPILibs();
|
||||
if (!m_TemplateScript.LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
|
||||
{
|
||||
LOGWARN("Could not load WebAdmin template \"%s\", using default template.", FILE_IO_PREFIX "webadmin/template.lua");
|
||||
LOGWARN("Could not load WebAdmin template \"%s\". WebAdmin disabled!", FILE_IO_PREFIX "webadmin/template.lua");
|
||||
m_TemplateScript.Close();
|
||||
m_HTTPServer.Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LoadLoginTemplate())
|
||||
{
|
||||
LOGWARN("Could not load WebAdmin login template \"%s\", using fallback template.", FILE_IO_PREFIX "webadmin/login_template.html");
|
||||
|
||||
// Sets the fallback template:
|
||||
m_LoginTemplate = \
|
||||
"<h1>MCServer WebAdmin</h1>" \
|
||||
"<center>" \
|
||||
"<form method='get' action='webadmin/'>" \
|
||||
"<input type='submit' value='Log in'>" \
|
||||
"</form>" \
|
||||
"</center>";
|
||||
}
|
||||
|
||||
m_IsRunning = m_HTTPServer.Start(*this);
|
||||
@ -159,6 +175,28 @@ void cWebAdmin::Stop(void)
|
||||
|
||||
|
||||
|
||||
bool cWebAdmin::LoadLoginTemplate(void)
|
||||
{
|
||||
cFile File(FILE_IO_PREFIX "webadmin/login_template.html", cFile::fmRead);
|
||||
if (!File.IsOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AString TemplateContent;
|
||||
if (File.ReadRestOfFile(TemplateContent) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_LoginTemplate = TemplateContent;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||
{
|
||||
if (!a_Request.HasAuth())
|
||||
@ -298,17 +336,11 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
|
||||
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||
{
|
||||
UNUSED(a_Request);
|
||||
static const char LoginForm[] = \
|
||||
"<h1>MCServer WebAdmin</h1>" \
|
||||
"<center>" \
|
||||
"<form method='get' action='webadmin/'>" \
|
||||
"<input type='submit' value='Log in'>" \
|
||||
"</form>" \
|
||||
"</center>";
|
||||
|
||||
cHTTPResponse Resp;
|
||||
Resp.SetContentType("text/html");
|
||||
a_Connection.Send(Resp);
|
||||
a_Connection.Send(LoginForm, sizeof(LoginForm) - 1);
|
||||
a_Connection.Send(m_LoginTemplate);
|
||||
a_Connection.FinishResponse();
|
||||
}
|
||||
|
||||
@ -316,6 +348,94 @@ void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest &
|
||||
|
||||
|
||||
|
||||
void cWebAdmin::HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||
{
|
||||
AString FileURL = a_Request.GetURL();
|
||||
std::replace(FileURL.begin(), FileURL.end(), '\\', '/');
|
||||
|
||||
// Remove all leading backslashes:
|
||||
if (FileURL[0] == '/')
|
||||
{
|
||||
size_t FirstCharToRead = FileURL.find_first_not_of('/');
|
||||
if (FirstCharToRead != AString::npos)
|
||||
{
|
||||
FileURL = FileURL.substr(FirstCharToRead);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all "../" strings:
|
||||
ReplaceString(FileURL, "../", "");
|
||||
|
||||
bool LoadedSuccessfull = false;
|
||||
AString Content = "<h2>404 Not Found</h2>";
|
||||
AString Path = Printf(FILE_IO_PREFIX "webadmin/files/%s", FileURL.c_str());
|
||||
if (cFile::IsFile(Path))
|
||||
{
|
||||
cFile File(Path, cFile::fmRead);
|
||||
AString FileContent;
|
||||
if (File.IsOpen() && (File.ReadRestOfFile(FileContent) != -1))
|
||||
{
|
||||
LoadedSuccessfull = true;
|
||||
Content = FileContent;
|
||||
}
|
||||
}
|
||||
|
||||
// Find content type (The currently method is very bad. We should change it later)
|
||||
AString ContentType = "text/html";
|
||||
size_t LastPointPosition = Path.find_last_of('.');
|
||||
if (LoadedSuccessfull && (LastPointPosition != AString::npos) && (LastPointPosition < Path.length()))
|
||||
{
|
||||
AString FileExtension = Path.substr(LastPointPosition + 1);
|
||||
ContentType = GetContentTypeFromFileExt(FileExtension);
|
||||
}
|
||||
|
||||
// Send the response:
|
||||
cHTTPResponse Resp;
|
||||
Resp.SetContentType(ContentType);
|
||||
a_Connection.Send(Resp);
|
||||
a_Connection.Send(Content);
|
||||
a_Connection.FinishResponse();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cWebAdmin::GetContentTypeFromFileExt(const AString & a_FileExtension)
|
||||
{
|
||||
static bool IsInitialized = false;
|
||||
static std::map<AString, AString> ContentTypeMap;
|
||||
if (!IsInitialized)
|
||||
{
|
||||
// Initialize the ContentTypeMap:
|
||||
ContentTypeMap["png"] = "image/png";
|
||||
ContentTypeMap["fif"] = "image/fif";
|
||||
ContentTypeMap["gif"] = "image/gif";
|
||||
ContentTypeMap["jpeg"] = "image/jpeg";
|
||||
ContentTypeMap["jpg"] = "image/jpeg";
|
||||
ContentTypeMap["jpe"] = "image/jpeg";
|
||||
ContentTypeMap["tiff"] = "image/tiff";
|
||||
ContentTypeMap["ico"] = "image/ico";
|
||||
ContentTypeMap["csv"] = "image/comma-separated-values";
|
||||
ContentTypeMap["css"] = "text/css";
|
||||
ContentTypeMap["js"] = "text/javascript";
|
||||
ContentTypeMap["txt"] = "text/plain";
|
||||
ContentTypeMap["rtx"] = "text/richtext";
|
||||
ContentTypeMap["xml"] = "text/xml";
|
||||
}
|
||||
|
||||
AString FileExtension = StrToLower(a_FileExtension);
|
||||
if (ContentTypeMap.find(a_FileExtension) == ContentTypeMap.end())
|
||||
{
|
||||
return "text/html";
|
||||
}
|
||||
return ContentTypeMap[FileExtension];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request)
|
||||
{
|
||||
sWebAdminPage Page;
|
||||
@ -382,6 +502,7 @@ AString cWebAdmin::GetDefaultPage(void)
|
||||
|
||||
|
||||
|
||||
|
||||
AString cWebAdmin::GetBaseURL( const AString& a_URL)
|
||||
{
|
||||
return GetBaseURL(StringSplit(a_URL, "/"));
|
||||
@ -528,7 +649,7 @@ void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest &
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Handle other requests
|
||||
HandleFileRequest(a_Connection, a_Request);
|
||||
}
|
||||
|
||||
// Delete any request data assigned to the request:
|
||||
@ -551,4 +672,3 @@ void cWebAdmin::cWebadminRequestData::OnBody(const char * a_Data, size_t a_Size)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -116,6 +116,9 @@ public:
|
||||
/** Stops the HTTP server, if it was started. */
|
||||
void Stop(void);
|
||||
|
||||
/** Loads the login template. Returns true if the loading succeeds, false if not. */
|
||||
bool LoadLoginTemplate(void);
|
||||
|
||||
void AddPlugin(cWebPlugin * a_Plugin);
|
||||
void RemovePlugin(cWebPlugin * a_Plugin);
|
||||
|
||||
@ -146,6 +149,9 @@ public:
|
||||
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
|
||||
static AString GetBaseURL(const AStringVector & a_URLSplit);
|
||||
|
||||
/** Returns the content type from the file extension. If the extension isn't in the list, the function returns "text/html" */
|
||||
static AString GetContentTypeFromFileExt(const AString & a_FileExtension);
|
||||
|
||||
protected:
|
||||
/** Common base class for request body data handlers */
|
||||
class cRequestData
|
||||
@ -205,6 +211,9 @@ protected:
|
||||
/** The Lua template script to provide templates: */
|
||||
cLuaState m_TemplateScript;
|
||||
|
||||
/** The template that provides the login site: */
|
||||
AString m_LoginTemplate;
|
||||
|
||||
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
|
||||
cHTTPServer m_HTTPServer;
|
||||
|
||||
@ -214,6 +223,9 @@ protected:
|
||||
/** Handles requests for the root page */
|
||||
void HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
|
||||
|
||||
/** Handles requests for a file */
|
||||
void HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
|
||||
|
||||
// cHTTPServer::cCallbacks overrides:
|
||||
virtual void OnRequestBegun (cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
|
||||
virtual void OnRequestBody (cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override;
|
||||
|
Loading…
Reference in New Issue
Block a user