2012-01-29 14:28:19 -05:00
|
|
|
|
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
2011-10-03 14:41:19 -04:00
|
|
|
#include "cWebAdmin.h"
|
|
|
|
#include "cStringMap.h"
|
|
|
|
|
|
|
|
#include "cWebPlugin.h"
|
2012-01-27 18:47:32 -05:00
|
|
|
#include "cWebPlugin_Lua.h"
|
2011-10-03 14:41:19 -04:00
|
|
|
|
|
|
|
#include "cPluginManager.h"
|
|
|
|
#include "cPlugin.h"
|
|
|
|
|
|
|
|
#include "cWorld.h"
|
|
|
|
#include "cPlayer.h"
|
|
|
|
#include "cServer.h"
|
|
|
|
#include "cRoot.h"
|
|
|
|
|
|
|
|
#include "../iniFile/iniFile.h"
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2012-01-29 14:28:19 -05:00
|
|
|
#include <psapi.h>
|
2011-10-03 14:41:19 -04:00
|
|
|
#else
|
2012-01-29 14:28:19 -05:00
|
|
|
#include <sys/resource.h>
|
2011-10-03 14:41:19 -04:00
|
|
|
#endif
|
|
|
|
|
2012-01-29 14:28:19 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-10-03 14:41:19 -04:00
|
|
|
extern std::vector<std::string> StringSplit(std::string str, std::string delim);
|
|
|
|
|
|
|
|
cWebAdmin* WebAdmin = 0;
|
|
|
|
|
|
|
|
cWebAdmin::cWebAdmin( int a_Port /* = 8080 */ )
|
|
|
|
: m_Port( a_Port )
|
|
|
|
, m_bConnected( false )
|
|
|
|
{
|
|
|
|
WebAdmin = this;
|
|
|
|
m_Event = new cEvent();
|
|
|
|
Init( m_Port );
|
|
|
|
}
|
|
|
|
|
|
|
|
cWebAdmin::~cWebAdmin()
|
|
|
|
{
|
|
|
|
WebAdmin = 0;
|
|
|
|
m_WebServer->Stop();
|
|
|
|
|
|
|
|
while( m_Plugins.begin() != m_Plugins.end() )
|
|
|
|
{
|
|
|
|
delete *m_Plugins.begin();
|
|
|
|
//m_Plugins.remove( *m_Plugins.begin() );
|
|
|
|
}
|
|
|
|
delete m_WebServer;
|
|
|
|
delete m_IniFile;
|
|
|
|
|
|
|
|
m_Event->Wait();
|
|
|
|
delete m_Event;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReplaceString( std::string & a_HayStack, const std::string & a_Needle, const std::string & a_ReplaceWith )
|
|
|
|
{
|
|
|
|
size_t pos1 = a_HayStack.find( a_Needle );
|
|
|
|
a_HayStack.replace( pos1, a_Needle.size(), a_ReplaceWith );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cWebAdmin::AddPlugin( cWebPlugin* a_Plugin )
|
|
|
|
{
|
|
|
|
m_Plugins.remove( a_Plugin );
|
|
|
|
m_Plugins.push_back( a_Plugin );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cWebAdmin::RemovePlugin( cWebPlugin* a_Plugin )
|
|
|
|
{
|
|
|
|
m_Plugins.remove( a_Plugin );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cWebAdmin::Request_Handler(webserver::http_request* r)
|
|
|
|
{
|
|
|
|
if( WebAdmin == 0 ) return;
|
|
|
|
LOG("Path: %s", r->path_.c_str() );
|
|
|
|
|
|
|
|
std::vector< std::string > Split = StringSplit( r->path_, "/" );
|
|
|
|
|
|
|
|
if(r->path_ == "/")
|
|
|
|
{
|
|
|
|
r->answer_ += "<center>";
|
|
|
|
r->answer_ += "MCServer WebAdmin";
|
|
|
|
r->answer_ += "<br>";
|
|
|
|
r->answer_ += "<form method='get' action='webadmin/'>";
|
|
|
|
r->answer_ += "<input type='submit' value='Log in'>";
|
|
|
|
r->answer_ += "</form>";
|
|
|
|
r->answer_ += "</center>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( Split.size() > 0 && Split[0] == "webadmin" )
|
|
|
|
{
|
|
|
|
if( r->authentication_given_ )
|
|
|
|
{
|
|
|
|
std::string UserPassword = WebAdmin->m_IniFile->GetValue( "User:"+r->username_, "Password", "");
|
|
|
|
if (UserPassword != "" && r->password_ == UserPassword)
|
|
|
|
{
|
2012-01-27 18:47:32 -05:00
|
|
|
std::string BaseURL = "./";
|
|
|
|
if( Split.size() > 1 )
|
|
|
|
{
|
|
|
|
for( unsigned int i = 0; i < Split.size(); i++)
|
|
|
|
{
|
|
|
|
BaseURL += "../";
|
|
|
|
}
|
|
|
|
BaseURL += "webadmin/";
|
|
|
|
}
|
|
|
|
|
2011-10-03 14:41:19 -04:00
|
|
|
std::string Menu;
|
|
|
|
std::string Content;
|
|
|
|
std::string Template = WebAdmin->GetTemplate();
|
2012-01-22 15:15:11 -05:00
|
|
|
std::string FoundPlugin;
|
2011-10-03 14:41:19 -04:00
|
|
|
|
|
|
|
for( PluginList::iterator itr = WebAdmin->m_Plugins.begin(); itr != WebAdmin->m_Plugins.end(); ++itr )
|
|
|
|
{
|
2012-01-27 18:47:32 -05:00
|
|
|
cWebPlugin* WebPlugin = *itr;
|
|
|
|
cWebPlugin_Lua* LuaPlugin = dynamic_cast< cWebPlugin_Lua* >( WebPlugin );
|
|
|
|
if( LuaPlugin )
|
|
|
|
{
|
|
|
|
std::list< std::string > NameList = LuaPlugin->GetTabNames();
|
|
|
|
for( std::list< std::string >::iterator Name = NameList.begin(); Name != NameList.end(); ++Name )
|
|
|
|
{
|
|
|
|
Menu += "<li><a href='" + BaseURL + WebPlugin->GetName() + "/" + (*Name) + "'>" + (*Name) + "</a></li>";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Menu += "<li><a href='" + BaseURL + WebPlugin->GetName() + "'>" + WebPlugin->GetName() + "</a></li>";
|
|
|
|
}
|
2011-10-03 14:41:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
HTTPRequest Request;
|
|
|
|
Request.Username = r->username_;
|
|
|
|
Request.Method = r->method_;
|
|
|
|
Request.Params = new cStringMap(r->params_);
|
|
|
|
Request.Path = r->path_;
|
|
|
|
|
|
|
|
if( Split.size() > 1 )
|
|
|
|
{
|
|
|
|
for( PluginList::iterator itr = WebAdmin->m_Plugins.begin(); itr != WebAdmin->m_Plugins.end(); ++itr )
|
|
|
|
{
|
|
|
|
if( (*itr)->GetName() == Split[1] )
|
|
|
|
{
|
|
|
|
Content = (*itr)->HandleRequest( &Request );
|
2012-01-27 18:47:32 -05:00
|
|
|
cWebPlugin* WebPlugin = *itr;
|
|
|
|
FoundPlugin = WebPlugin->GetName();
|
|
|
|
cWebPlugin_Lua* LuaPlugin = dynamic_cast< cWebPlugin_Lua* >( WebPlugin );
|
|
|
|
if( LuaPlugin )
|
|
|
|
{
|
|
|
|
FoundPlugin += " - " + LuaPlugin->GetTabNameForRequest( &Request );
|
|
|
|
}
|
2011-10-03 14:41:19 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-01-22 15:15:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
delete Request.Params;
|
|
|
|
|
|
|
|
if( FoundPlugin.empty() ) // Default page
|
|
|
|
{
|
|
|
|
Content.clear();
|
|
|
|
FoundPlugin = "Current Game";
|
|
|
|
Content += "<h4>Server Name:</h4>";
|
|
|
|
Content += "<p>" + std::string( cRoot::Get()->GetServer()->GetServerID() ) + "</p>";
|
|
|
|
|
|
|
|
Content += "<h4>Plugins:</h4><ul>";
|
|
|
|
cPluginManager* PM = cRoot::Get()->GetPluginManager();
|
|
|
|
if( PM )
|
|
|
|
{
|
|
|
|
const cPluginManager::PluginList & List = PM->GetAllPlugins();
|
|
|
|
for( cPluginManager::PluginList::const_iterator itr = List.begin(); itr != List.end(); ++itr )
|
|
|
|
{
|
2012-01-27 18:47:32 -05:00
|
|
|
char c_VersionNum[32]; // 32 digits should be enough? XD
|
|
|
|
sprintf_s( c_VersionNum, 32, "%i", (*itr)->GetVersion() );
|
|
|
|
Content += std::string("<li>") + std::string( (*itr)->GetName() ) + " V. " + std::string( c_VersionNum ) + "</li>";
|
|
|
|
|
2012-01-22 15:15:11 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Content += "</ul>";
|
|
|
|
Content += "<h4>Players:</h4><ul>";
|
2011-10-03 14:41:19 -04:00
|
|
|
|
2012-01-22 15:15:11 -05:00
|
|
|
cWorld* World = cRoot::Get()->GetWorld(); // TODO - Create a list of worlds and players
|
|
|
|
cWorld::PlayerList PlayerList = World->GetAllPlayers();
|
|
|
|
for( cWorld::PlayerList::iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr )
|
2011-10-03 14:41:19 -04:00
|
|
|
{
|
2012-01-22 15:15:11 -05:00
|
|
|
Content += std::string("<li>") + std::string( (*itr)->GetName() ) + "</li>";
|
2011-10-03 14:41:19 -04:00
|
|
|
}
|
2012-01-22 15:15:11 -05:00
|
|
|
Content += "</ul><br>";
|
2011-10-03 14:41:19 -04:00
|
|
|
}
|
|
|
|
|
2012-01-22 15:15:11 -05:00
|
|
|
|
2011-10-03 14:41:19 -04:00
|
|
|
|
|
|
|
if( Split.size() > 1 )
|
|
|
|
{
|
2012-01-27 18:47:32 -05:00
|
|
|
Content += "\n<p><a href='" + BaseURL + "'>Go back</a></p>";
|
2011-10-03 14:41:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// mem usage
|
|
|
|
#ifndef _WIN32
|
|
|
|
rusage resource_usage;
|
|
|
|
if (getrusage(RUSAGE_SELF, &resource_usage) != 0)
|
|
|
|
{
|
|
|
|
ReplaceString( Template, std::string("{MEM}"), "Error :(" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char MemUsage[32];
|
|
|
|
sprintf( MemUsage, "%0.2f", ((double)resource_usage.ru_maxrss / 1024 / 1024) );
|
|
|
|
ReplaceString( Template, std::string("{MEM}"), MemUsage );
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
|
|
PROCESS_MEMORY_COUNTERS pmc;
|
|
|
|
if( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc) ) )
|
|
|
|
{
|
|
|
|
char MemUsage[32];
|
|
|
|
sprintf( MemUsage, "%0.2f", (pmc.WorkingSetSize / 1024.f / 1024.f) );
|
|
|
|
ReplaceString( Template, std::string("{MEM}"), MemUsage );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// end mem usage
|
|
|
|
|
|
|
|
ReplaceString( Template, std::string("{USERNAME}"), r->username_ );
|
|
|
|
ReplaceString( Template, std::string("{MENU}"), Menu );
|
2012-01-22 15:15:11 -05:00
|
|
|
ReplaceString( Template, std::string("{PLUGIN_NAME}"), FoundPlugin );
|
2011-10-03 14:41:19 -04:00
|
|
|
ReplaceString( Template, std::string("{CONTENT}"), Content );
|
|
|
|
ReplaceString( Template, std::string("{TITLE}"), "MCServer" );
|
|
|
|
|
|
|
|
r->answer_ = Template;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r->answer_ += "Wrong username/password";
|
|
|
|
r->auth_realm_ = "MCServer WebAdmin";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r->answer_ += "no auth";
|
|
|
|
r->auth_realm_ = "MCServer WebAdmin";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cWebAdmin::Init( int a_Port )
|
|
|
|
{
|
|
|
|
m_Port = a_Port;
|
|
|
|
|
|
|
|
m_IniFile = new cIniFile("webadmin.ini");
|
|
|
|
if( m_IniFile->ReadFile() )
|
|
|
|
{
|
|
|
|
m_Port = m_IniFile->GetValueI("WebAdmin", "Port", 8080 );
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG("Starting WebAdmin on port %i", m_Port);
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
HANDLE hThread = CreateThread(
|
|
|
|
NULL, // default security
|
|
|
|
0, // default stack size
|
|
|
|
ListenThread, // name of the thread function
|
|
|
|
this, // thread parameters
|
|
|
|
0, // default startup flags
|
|
|
|
NULL);
|
|
|
|
CloseHandle( hThread ); // Just close the handle immediately
|
|
|
|
#else
|
|
|
|
pthread_t LstnThread;
|
|
|
|
pthread_create( &LstnThread, 0, ListenThread, this);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
DWORD WINAPI cWebAdmin::ListenThread(LPVOID lpParam)
|
|
|
|
#else
|
|
|
|
void *cWebAdmin::ListenThread( void *lpParam )
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
cWebAdmin* self = (cWebAdmin*)lpParam;
|
|
|
|
|
|
|
|
self->m_WebServer = new webserver(self->m_Port, Request_Handler );
|
|
|
|
self->m_WebServer->Begin();
|
|
|
|
|
|
|
|
self->m_Event->Set();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cWebAdmin::GetTemplate()
|
|
|
|
{
|
|
|
|
std::string retVal = "";
|
|
|
|
|
|
|
|
char SourceFile[] = "webadmin/template.html";
|
|
|
|
|
|
|
|
FILE* f;
|
|
|
|
#ifdef _WIN32
|
|
|
|
if( fopen_s(&f, SourceFile, "rb" ) == 0 ) // no error
|
|
|
|
#else
|
|
|
|
if( (f = fopen(SourceFile, "rb" ) ) != 0 ) // no error
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// obtain file size:
|
|
|
|
fseek (f , 0 , SEEK_END);
|
|
|
|
long lSize = ftell (f);
|
|
|
|
rewind (f);
|
|
|
|
|
|
|
|
// allocate memory to contain the whole file:
|
|
|
|
char* buffer = (char*) malloc (sizeof(char)*lSize);
|
|
|
|
|
|
|
|
// copy the file into the buffer:
|
|
|
|
size_t result = fread (buffer, 1, lSize, f);
|
|
|
|
if ((long)result != lSize)
|
|
|
|
{
|
|
|
|
LOG ("WEBADMIN: Could not read file %s", SourceFile);
|
|
|
|
free( buffer );
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
retVal.assign( buffer, lSize );
|
|
|
|
|
|
|
|
free( buffer );
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cWebAdmin::RemovePlugin( lua_State* L )
|
|
|
|
{
|
|
|
|
for( PluginList::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); )
|
|
|
|
{
|
|
|
|
if( (*itr)->GetLuaState() == L )
|
|
|
|
{
|
|
|
|
PluginList::iterator prev = itr++;
|
|
|
|
delete *prev; // deleting a dereferenced iterator also takes it out of the list, so no need for erase()
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|