Cuberite
A lightweight, fast and extensible game server for Minecraft
WebAdmin.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "WebAdmin.h"
5 
6 #include "World.h"
7 #include "Entities/Player.h"
8 #include "Server.h"
9 #include "Root.h"
10 
12 #include "HTTP/HTTPFormParser.h"
13 
14 
15 
16 
17 
18 static const char DEFAULT_WEBADMIN_PORTS[] = "8080";
19 
20 
21 
22 
23 
25 // cWebadminRequestData
26 
31 {
32 public:
34 
35 
37  m_Form(a_Request, *this)
38  {
39  }
40 
41  // cHTTPFormParser::cCallbacks overrides. Files are ignored:
42  virtual void OnFileStart(cHTTPFormParser &, const AString & a_FileName) override
43  {
44  UNUSED(a_FileName);
45  }
46  virtual void OnFileData(cHTTPFormParser &, const char * a_Data, size_t a_Size) override
47  {
48  UNUSED(a_Data);
49  UNUSED(a_Size);
50  }
51  virtual void OnFileEnd(cHTTPFormParser &) override {}
52 } ;
53 
54 
55 
56 
57 
59 // cWebAdmin:
60 
62  m_TemplateScript("<webadmin_template>"),
63  m_IsInitialized(false),
64  m_IsRunning(false)
65 {
66 }
67 
68 
69 
70 
71 
73 {
74  ASSERT(!m_IsRunning); // Was the HTTP server stopped properly?
75 }
76 
77 
78 
79 
80 
81 bool cWebAdmin::Init(void)
82 {
83  if (!LoadIniFile())
84  {
85  // WebAdmin is disabled, bail out faking a success
86  return true;
87  }
88 
89  LOGD("Initialising WebAdmin...");
90 
91  Reload();
92 
93  // Read the ports to be used:
94  // Note that historically the ports were stored in the "Port" and "PortsIPv6" values
95  m_Ports = ReadUpgradeIniPorts(m_IniFile, "WebAdmin", "Ports", "Port", "PortsIPv6", DEFAULT_WEBADMIN_PORTS);
96 
97  if (!m_HTTPServer.Initialize())
98  {
99  return false;
100  }
101  m_IsInitialized = true;
102  m_IniFile.WriteFile("webadmin.ini");
103  return true;
104 }
105 
106 
107 
108 
109 
111 {
112  if (!m_IsInitialized)
113  {
114  // Not initialized
115  return false;
116  }
117 
118  LOGD("Starting WebAdmin...");
119 
121  return m_IsRunning;
122 }
123 
124 
125 
126 
127 
128 void cWebAdmin::Stop(void)
129 {
130  if (!m_IsRunning)
131  {
132  return;
133  }
134 
135  LOGD("Stopping WebAdmin...");
136  m_HTTPServer.Stop();
137  m_IsRunning = false;
138 }
139 
140 
141 
142 
143 
145 {
146  cFile File("webadmin/login_template.html", cFile::fmRead);
147  if (!File.IsOpen())
148  {
149  return false;
150  }
151 
152  AString TemplateContent;
153  if (File.ReadRestOfFile(TemplateContent) == -1)
154  {
155  return false;
156  }
157 
158  cCSLock Lock(m_CS);
159  m_LoginPage = TemplateContent;
160  return true;
161 }
162 
163 
164 
165 
166 
167 void cWebAdmin::RemoveAllPluginWebTabs(const AString & a_PluginName)
168 {
169  cCSLock lock(m_CS);
170  m_WebTabs.erase(std::remove_if(m_WebTabs.begin(), m_WebTabs.end(), [=](const cWebTabPtr & a_CBWebTab)
171  {
172  return (a_CBWebTab->m_PluginName == a_PluginName);
173  }),
174  m_WebTabs.end()
175  );
176 }
177 
178 
179 
180 
181 
183 {
184  cCSLock lock(m_CS);
185  if (!LoadIniFile())
186  {
187  // We are asked to disable the webadmin, cannot do that, so warn the admin:
188  LOGWARNING(
189  "WebAdmin was previously enabled and now the settings say to disable it."
190  " This will not take effect until you restart the server."
191  );
192  }
193  else if (!HasUsers())
194  {
195  LOGWARNING(
196  "The webadmin is enabled but has no users configured."
197  " To add new users, edit webadmin.ini"
198  );
199  }
200 
201  // Initialize the WebAdmin template script and reload the file:
203  {
205  }
208  if (!m_TemplateScript.LoadFile("webadmin/template.lua"))
209  {
210  LOGWARN("Could not load WebAdmin template \"%s\". WebAdmin will not work properly!", "webadmin/template.lua");
212  }
213 
214  // Load the login template, provide a fallback default if not found:
215  if (!LoadLoginPage())
216  {
217  LOGWARN("Could not load WebAdmin login page \"%s\", using fallback template.", "webadmin/login_template.html");
218 
219  // Set the fallback:
220  m_LoginPage = \
221  "<h1>Cuberite WebAdmin</h1>" \
222  "<center>" \
223  "<form method='get' action='webadmin/'>" \
224  "<input type='submit' value='Log in'>" \
225  "</form>" \
226  "</center>";
227  }
228 }
229 
230 
231 
232 
233 
235 {
236  m_IniFile.Clear();
237  if (!m_IniFile.ReadFile("webadmin.ini"))
238  {
239  LOGWARN("Regenerating webadmin.ini, all settings will be reset");
240  m_IniFile.AddHeaderComment(" This file controls the webadmin feature of Cuberite");
241  m_IniFile.AddHeaderComment(" It specifies whether webadmin is enabled, and what logins are allowed. ");
242  m_IniFile.AddHeaderComment(" Username format: [User:*username*]");
243  m_IniFile.AddHeaderComment(" Password format: Password=*password*; for example:");
244  m_IniFile.AddHeaderComment(" [User:admin]");
245  m_IniFile.AddHeaderComment(" Password=admin");
246  m_IniFile.AddHeaderComment(" Please restart Cuberite to apply changes made in this file!");
247  m_IniFile.SetValue("WebAdmin", "Ports", DEFAULT_WEBADMIN_PORTS);
248  m_IniFile.WriteFile("webadmin.ini");
249  }
250 
251  return m_IniFile.GetValueSetB("WebAdmin", "Enabled", true);
252 }
253 
254 
255 
256 
257 
259 {
260  for (int i = 0; i < m_IniFile.GetNumKeys(); i++)
261  {
262  AString key = m_IniFile.GetKeyName(i);
263  if (key.rfind("User:", 0) == 0)
264  {
265  return true;
266  }
267  }
268  return false;
269 }
270 
271 
272 
273 
274 
276 {
277  if (!a_Request.HasAuth())
278  {
279  a_Connection.SendNeedAuth("Cuberite WebAdmin");
280  return;
281  }
282 
283  // Check auth:
284  {
285  cCSLock Lock(m_CS);
286  AString UserPassword = m_IniFile.GetValue("User:" + a_Request.GetAuthUsername(), "Password", "");
287  if ((UserPassword == "") || (a_Request.GetAuthPassword() != UserPassword))
288  {
289  a_Connection.SendNeedAuth("Cuberite WebAdmin - bad username or password");
290  return;
291  }
292  }
293 
294  // Check if the contents should be wrapped in the template:
295  auto BareURL = a_Request.GetURLPath();
296  ASSERT(BareURL.length() > 0);
297  bool ShouldWrapInTemplate = (!BareURL.empty() && (BareURL[1] != '~'));
298 
299  // Retrieve the request data:
300  auto Data = std::static_pointer_cast<cWebadminRequestData>(a_Request.GetUserData());
301  if (Data == nullptr)
302  {
303  a_Connection.SendStatusAndReason(500, "Bad UserData");
304  return;
305  }
306 
307  // Wrap it all up for the Lua call:
308  AString Template;
309  HTTPTemplateRequest TemplateRequest;
310  TemplateRequest.Request.URL = a_Request.GetURL();
311  TemplateRequest.Request.Username = a_Request.GetAuthUsername();
312  TemplateRequest.Request.Method = a_Request.GetMethod();
313  TemplateRequest.Request.Path = BareURL.substr(1);
314 
315  if (Data->m_Form.Finish())
316  {
317  for (cHTTPFormParser::const_iterator itr = Data->m_Form.begin(), end = Data->m_Form.end(); itr != end; ++itr)
318  {
319  HTTPFormData HTTPfd;
320  HTTPfd.Value = itr->second;
321  HTTPfd.Type = "";
322  HTTPfd.Name = itr->first;
323  TemplateRequest.Request.FormData[itr->first] = HTTPfd;
324  TemplateRequest.Request.PostParams[itr->first] = itr->second;
325  } // for itr - Data->m_Form[]
326 
327  // Parse the URL into individual params:
328  const AString & URL = a_Request.GetURL();
329  size_t idxQM = URL.find('?');
330  if (idxQM != AString::npos)
331  {
332  cHTTPFormParser URLParams(cHTTPFormParser::fpkURL, URL.c_str() + idxQM + 1, URL.length() - idxQM - 1, *Data);
333  URLParams.Finish();
334  for (cHTTPFormParser::const_iterator itr = URLParams.begin(), end = URLParams.end(); itr != end; ++itr)
335  {
336  TemplateRequest.Request.Params[itr->first] = itr->second;
337  } // for itr - URLParams[]
338  }
339  }
340 
341  // Try to get the template from the Lua template script
342  if (ShouldWrapInTemplate)
343  {
344  cCSLock LockSelf(m_CS);
345  cLuaState::cLock LockTemplate(m_TemplateScript);
346  if (m_TemplateScript.Call("ShowPage", this, &TemplateRequest, cLuaState::Return, Template))
347  {
349  Resp.SetContentType("text/html");
350  a_Connection.Send(Resp);
351  a_Connection.Send(Template.c_str(), Template.length());
352  a_Connection.FinishResponse();
353  return;
354  }
355  a_Connection.SendStatusAndReason(500, "m_TemplateScript failed");
356  return;
357  }
358 
359  // Send the un-decorated page content:
360  auto page = GetPage(TemplateRequest.Request);
362  resp.SetContentType(page.ContentType);
363  a_Connection.Send(resp);
364  a_Connection.Send(page.Content.c_str(), page.Content.length());
365  a_Connection.FinishResponse();
366 }
367 
368 
369 
370 
371 
373 {
374  UNUSED(a_Request);
375 
377  Resp.SetContentType("text/html");
378  a_Connection.Send(Resp);
379  a_Connection.Send(m_LoginPage);
380  a_Connection.FinishResponse();
381 }
382 
383 
384 
385 
386 
388 {
389  AString FileURL = a_Request.GetURL();
390  std::replace(FileURL.begin(), FileURL.end(), '\\', '/');
391 
392  // Remove all leading backslashes:
393  if (!FileURL.empty() && (FileURL[0] == '/'))
394  {
395  size_t FirstCharToRead = FileURL.find_first_not_of('/');
396  if (FirstCharToRead != AString::npos)
397  {
398  FileURL = FileURL.substr(FirstCharToRead);
399  }
400  }
401 
402  // Read the file contents and guess its mime-type, based on the extension:
403  AString Content = "<h2>404 Not Found</h2>";
404  AString ContentType = "text/html";
405  AString Path = "webadmin/files/" + FileURL;
406 
407  // Return 404 if the file is not found, or the URL contains '../' (for security reasons)
408  if ((FileURL.find("../") == AString::npos) && cFile::IsFile(Path))
409  {
410  cFile File(Path, cFile::fmRead);
411  AString FileContent;
412  if (File.IsOpen() && (File.ReadRestOfFile(FileContent) != -1))
413  {
414  std::swap(Content, FileContent);
415  size_t LastPointPosition = Path.find_last_of('.');
416  if (LastPointPosition != AString::npos)
417  {
418  ContentType = GetContentTypeFromFileExt(Path.substr(LastPointPosition + 1));
419  }
420  }
421  if (ContentType.empty())
422  {
423  ContentType = "application/unknown";
424  }
425  }
426 
427  // Send the response:
429  Resp.SetContentType(ContentType);
430  a_Connection.Send(Resp);
431  a_Connection.Send(Content);
432  a_Connection.FinishResponse();
433 }
434 
435 
436 
437 
438 
440 {
441  static bool IsInitialized = false;
442  static AStringMap ContentTypeMap;
443  if (!IsInitialized)
444  {
445  // Initialize the ContentTypeMap:
446  ContentTypeMap["png"] = "image/png";
447  ContentTypeMap["fif"] = "image/fif";
448  ContentTypeMap["gif"] = "image/gif";
449  ContentTypeMap["jpeg"] = "image/jpeg";
450  ContentTypeMap["jpg"] = "image/jpeg";
451  ContentTypeMap["jpe"] = "image/jpeg";
452  ContentTypeMap["tiff"] = "image/tiff";
453  ContentTypeMap["ico"] = "image/ico";
454  ContentTypeMap["csv"] = "text/csv";
455  ContentTypeMap["css"] = "text/css";
456  ContentTypeMap["js"] = "text/javascript";
457  ContentTypeMap["txt"] = "text/plain";
458  ContentTypeMap["rtx"] = "text/richtext";
459  ContentTypeMap["rtf"] = "text/richtext";
460  ContentTypeMap["xml"] = "text/xml";
461  ContentTypeMap["html"] = "text/html";
462  ContentTypeMap["htm"] = "text/html";
463  ContentTypeMap["xhtml"] = "application/xhtml+xml"; // Not recomended for IE6, but no-one uses that anymore
464  }
465 
466  auto itr = ContentTypeMap.find(StrToLower(a_FileExtension));
467  if (itr == ContentTypeMap.end())
468  {
469  return AString();
470  }
471  return itr->second;
472 }
473 
474 
475 
476 
477 
479 {
480  sWebAdminPage page;
481  auto split = StringSplit(a_Request.Path, "/");
482 
483  // If no specific page was requested, return an empty object:
484  if (split.size() <= 2)
485  {
486  return page;
487  }
488 
489  // Find the WebTab handler responsible for the request:
490  cWebTabPtr tab;
491  {
492  cCSLock Lock(m_CS);
493  for (auto & wt: m_WebTabs)
494  {
495  if (
496  (wt->m_PluginName == split[1]) &&
497  (wt->m_UrlPath == split[2])
498  )
499  {
500  tab = wt;
501  break;
502  }
503  } // for wt - m_WebTabs[]
504  }
505 
506  // If a WebTab handler was found, call it:
507  if (tab != nullptr)
508  {
509  page.ContentType = "text/html"; // Default to HTML content type, unless overridden by a plugin
510  if (!tab->m_Callback->Call(a_Request, split[1], page.Content, page.ContentType))
511  {
512  page.Content = GetHTMLEscapedString(fmt::format(
513  FMT_STRING("WebTab callback for plugin {}, page {} has failed."),
514  tab->m_PluginName, tab->m_Title
515  ));
516  }
517  page.PluginName = tab->m_PluginName;
518  page.TabTitle = tab->m_Title;
519  page.TabUrlPath = split[1];
520  }
521 
522  return page;
523 }
524 
525 
526 
527 
528 
530 {
531  return GetBaseURL(StringSplit(a_URL, "/"));
532 }
533 
534 
535 
536 
537 
539  const AString & a_Title,
540  const AString & a_UrlPath,
541  const AString & a_PluginName,
542  std::shared_ptr<cWebAdmin::cWebTabCallback> a_Callback
543 )
544 {
545  cCSLock lock(m_CS);
546  m_WebTabs.emplace_back(std::make_shared<cWebTab>(a_Title, a_UrlPath, a_PluginName, std::move(a_Callback)));
547 }
548 
549 
550 
551 
552 
553 bool cWebAdmin::DelWebTab(const AString & a_UrlPath)
554 {
555  cCSLock lock(m_CS);
556  for (auto itr = m_WebTabs.begin(), end = m_WebTabs.end(); itr != end; ++itr)
557  {
558  if ((*itr)->m_UrlPath == a_UrlPath)
559  {
560  m_WebTabs.erase(itr);
561  return true;
562  }
563  } // for itr - m_WebTabs[]
564 
565  // Not found:
566  return false;
567 }
568 
569 
570 
571 
572 
574 {
575  AString dst;
576  dst.reserve(a_Input.length());
577 
578  // Loop over input and substitute HTML characters for their alternatives:
579  size_t len = a_Input.length();
580  for (size_t i = 0; i < len; i++)
581  {
582  switch (a_Input[i])
583  {
584  case '&': dst.append("&amp;"); break;
585  case '\'': dst.append("&apos;"); break;
586  case '"': dst.append("&quot;"); break;
587  case '<': dst.append("&lt;"); break;
588  case '>': dst.append("&gt;"); break;
589  default:
590  {
591  dst.push_back(a_Input[i]);
592  break;
593  }
594  } // switch (a_Input[i])
595  } // for i - a_Input[]
596 
597  return dst;
598 }
599 
600 
601 
602 
603 
605 {
606  return URLEncode(a_Input);
607 }
608 
609 
610 
611 
612 
614 {
615  AString BaseURL = "./";
616  if (a_URLSplit.size() > 1)
617  {
618  for (unsigned int i = 0; i < a_URLSplit.size(); i++)
619  {
620  BaseURL += "../";
621  }
622  BaseURL += "webadmin/";
623  }
624  return BaseURL;
625 }
626 
627 
628 
629 
630 
632 {
633  UNUSED(a_Connection);
634  const AString & URL = a_Request.GetURL();
635  if (
636  (strncmp(URL.c_str(), "/webadmin", 9) == 0) ||
637  (strncmp(URL.c_str(), "/~webadmin", 10) == 0)
638  )
639  {
640  a_Request.SetUserData(std::make_shared<cWebadminRequestData>(a_Request));
641  return;
642  }
643  if (URL == "/")
644  {
645  // The root needs no body handler and is fully handled in the OnRequestFinished() call
646  return;
647  }
648  // TODO: Handle other requests
649 }
650 
651 
652 
653 
654 
655 void cWebAdmin::OnRequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size)
656 {
657  UNUSED(a_Connection);
658  auto Data = std::static_pointer_cast<cWebadminRequestData>(a_Request.GetUserData());
659  if (Data == nullptr)
660  {
661  return;
662  }
663  Data->m_Form.Parse(a_Data, a_Size);
664 }
665 
666 
667 
668 
669 
671 {
672  const AString & URL = a_Request.GetURL();
673  if (
674  (strncmp(URL.c_str(), "/webadmin", 9) == 0) ||
675  (strncmp(URL.c_str(), "/~webadmin", 10) == 0)
676  )
677  {
678  HandleWebadminRequest(a_Connection, a_Request);
679  }
680  else if (URL == "/")
681  {
682  // The root needs no body handler and is fully handled in the OnRequestFinished() call
683  HandleRootRequest(a_Connection, a_Request);
684  }
685  else
686  {
687  HandleFileRequest(a_Connection, a_Request);
688  }
689 }
690 
691 
692 
693 
694 
#define ASSERT(x)
Definition: Globals.h:276
#define UNUSED
Definition: Globals.h:72
AStringVector ReadUpgradeIniPorts(cSettingsRepositoryInterface &a_Settings, const AString &a_KeyName, const AString &a_PortsValueName, const AString &a_OldIPv4ValueName, const AString &a_OldIPv6ValueName, const AString &a_DefaultValue)
Reads the list of ports from the INI file, possibly upgrading from IPv4 / IPv6-specific values into n...
Definition: IniFile.cpp:923
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
#define LOGWARN
Definition: LoggerSimple.h:88
#define LOGD
Definition: LoggerSimple.h:83
AString URLEncode(const AString &a_Text)
URL-encodes the given string.
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:55
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Definition: StringUtils.h:16
static const char DEFAULT_WEBADMIN_PORTS[]
Definition: WebAdmin.cpp:18
void Close(void)
Closes the m_LuaState, if not closed already.
Definition: LuaState.cpp:529
bool Call(const FnT &a_Function, Args &&... args)
Call the specified Lua function.
Definition: LuaState.h:751
bool LoadFile(const AString &a_FileName, bool a_LogWarnings=true)
Loads the specified file Returns false and optionally logs a warning to the console if not successful...
Definition: LuaState.cpp:637
static const cRet Return
Definition: LuaState.h:445
void RegisterAPILibs(void)
Registers all the API libraries that MCS provides into m_LuaState.
Definition: LuaState.cpp:498
bool IsValid(void) const
Returns true if the m_LuaState is valid.
Definition: LuaState.h:580
void Create(void)
Creates the m_LuaState, if not created already.
Definition: LuaState.cpp:480
Provides a RAII-style locking for the LuaState.
Definition: LuaState.h:145
bool Finish(void)
Notifies that there's no more data incoming and the parser should finish its parsing.
@ fpkURL
The form has been transmitted as parameters to a GET request.
void SetContentType(const AString &a_ContentType)
Definition: HTTPMessage.h:39
Stores outgoing response headers and serializes them to an HTTP data stream.
Definition: HTTPMessage.h:71
Provides storage for an incoming HTTP request.
Definition: HTTPMessage.h:90
const AString & GetMethod(void) const
Returns the method used in the request.
Definition: HTTPMessage.h:109
const AString & GetAuthUsername(void) const
Returns the username that the request presented.
Definition: HTTPMessage.h:121
void SetUserData(cUserDataPtr a_UserData)
Attaches any kind of data to this request, to be later retrieved by GetUserData().
Definition: HTTPMessage.h:129
AString GetURLPath(void) const
Returns the path part of the URL.
cUserDataPtr GetUserData(void)
Returns the data attached to this request by the class client.
Definition: HTTPMessage.h:132
const AString & GetAuthPassword(void) const
Returns the password that the request presented.
Definition: HTTPMessage.h:124
bool HasAuth(void) const
Returns true if the request has had the Auth header present.
Definition: HTTPMessage.h:118
const AString & GetURL(void) const
Returns the URL used in the request.
Definition: HTTPMessage.h:112
Base class for anything that can be used as the UserData for the request.
Definition: HTTPMessage.h:97
bool Initialize(void)
Initializes the server - reads the cert files etc.
Definition: HTTPServer.cpp:85
void Stop(void)
Stops the server, drops all current connections.
Definition: HTTPServer.cpp:176
bool Start(cCallbacks &a_Callbacks, const AStringVector &a_Ports)
Starts the server and assigns the callbacks to use for incoming requests.
Definition: HTTPServer.cpp:134
void SendNeedAuth(const AString &a_Realm)
Sends the "401 unauthorized" reply together with instructions on authorizing, using the specified rea...
void FinishResponse(void)
Indicates that the current response is finished, gets ready for receiving another request (HTTP 1....
void SendStatusAndReason(int a_StatusCode, const AString &a_Reason)
Sends HTTP status code together with a_Reason (used for HTTP errors).
void Send(const cHTTPOutgoingResponse &a_Response)
Sends the headers contained in a_Response.
AString GetKeyName(const int keyID) const
Definition: IniFile.cpp:293
AString GetValue(const AString &keyname, const AString &valuename, const AString &defValue="") const override
Get the value at the specified key and value, returns defValue on failure.
Definition: IniFile.cpp:485
bool WriteFile(const AString &a_FileName) const
Writes data stored in class to the specified ini file.
Definition: IniFile.cpp:190
bool ReadFile(const AString &a_FileName, bool a_AllowExampleRedirect=true)
Reads the contents of the specified ini file If the file doesn't exist and a_AllowExampleRedirect is ...
Definition: IniFile.cpp:50
void Clear(void)
Deletes all stored ini data (but doesn't touch the file)
Definition: IniFile.cpp:645
void AddHeaderComment(const AString &comment)
Adds a header comment.
Definition: IniFile.cpp:674
bool SetValue(const int keyID, const int valueID, const AString &value)
Definition: IniFile.cpp:397
int GetNumKeys(void) const
Returns number of keys currently in the ini.
Definition: IniFile.h:117
bool GetValueSetB(const AString &keyname, const AString &valuename, const bool defValue=false) override
Definition: IniFile.h:150
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Definition: File.h:38
@ fmRead
Definition: File.h:54
int ReadRestOfFile(AString &a_Contents)
Reads the file from current position till EOF into an AString; returns the number of bytes read or -1...
Definition: File.cpp:263
bool IsOpen(void) const
Definition: File.cpp:118
static bool IsFile(const AString &a_Path)
Returns true if the specified path is a regular file.
Definition: File.cpp:425
The form parser callbacks for requests in the "/webadmin" and "/~webadmin" paths.
Definition: WebAdmin.cpp:31
cWebadminRequestData(const cHTTPIncomingRequest &a_Request)
Definition: WebAdmin.cpp:36
virtual void OnFileData(cHTTPFormParser &, const char *a_Data, size_t a_Size) override
Called when more file data has come for the current file in the form data.
Definition: WebAdmin.cpp:46
virtual void OnFileEnd(cHTTPFormParser &) override
Called when the current file part has ended in the form data.
Definition: WebAdmin.cpp:51
cHTTPFormParser m_Form
Definition: WebAdmin.cpp:33
virtual void OnFileStart(cHTTPFormParser &, const AString &a_FileName) override
Called when a new file part is encountered in the form data.
Definition: WebAdmin.cpp:42
std::string Value
Definition: WebAdmin.h:31
std::string Name
Definition: WebAdmin.h:30
std::string Type
Definition: WebAdmin.h:32
FormDataMap FormData
Same as PostParams.
Definition: WebAdmin.h:66
StringStringMap PostParams
Parameters posted as a part of a form - either in the URL (GET method) or in the body (POST method)
Definition: WebAdmin.h:63
AString URL
The entire URL presented to the HTTP server.
Definition: WebAdmin.h:46
AString Method
HTTP method used for the request ("GET", "POST" etc.)
Definition: WebAdmin.h:49
StringStringMap Params
Parameters given in the URL, after the questionmark.
Definition: WebAdmin.h:60
AString Path
The Path part of the request's URL (excluding GET params).
Definition: WebAdmin.h:52
AString Username
Name of the logged-in user.
Definition: WebAdmin.h:55
HTTPRequest Request
Definition: WebAdmin.h:76
AString PluginName
Definition: WebAdmin.h:87
AString TabUrlPath
Definition: WebAdmin.h:89
AString Content
Definition: WebAdmin.h:86
AString ContentType
Definition: WebAdmin.h:90
AString TabTitle
Definition: WebAdmin.h:88
virtual void OnRequestBody(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request, const char *a_Data, size_t a_Size) override
Called when another part of request body has arrived.
Definition: WebAdmin.cpp:655
cLuaState m_TemplateScript
The Lua template script to provide templates.
Definition: WebAdmin.h:235
void Stop(void)
Stops the HTTP server, if it was started.
Definition: WebAdmin.cpp:128
static AString GetContentTypeFromFileExt(const AString &a_FileExtension)
Returns the content type from the file extension.
Definition: WebAdmin.cpp:439
AStringVector m_Ports
The ports on which the webadmin is running.
Definition: WebAdmin.h:252
std::shared_ptr< cWebTab > cWebTabPtr
Definition: WebAdmin.h:147
cIniFile m_IniFile
The webadmin.ini file, used for the settings and allowed logins.
Definition: WebAdmin.h:243
void HandleFileRequest(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Handles requests for a file.
Definition: WebAdmin.cpp:387
virtual void OnRequestBegun(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request) override
Called when a new request arrives over a connection and all its headers have been parsed.
Definition: WebAdmin.cpp:631
cCriticalSection m_CS
Protects m_WebTabs, m_TemplateScript, m_LoginTemplate and m_IniFile against multithreaded access.
Definition: WebAdmin.h:227
void HandleWebadminRequest(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Handles requests coming to the "/webadmin" or "/~webadmin" URLs.
Definition: WebAdmin.cpp:275
virtual void OnRequestFinished(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request) override
Called when the request body has been fully received in previous calls to OnRequestBody()
Definition: WebAdmin.cpp:670
bool DelWebTab(const AString &a_UrlPath)
Removes the WebTab with the specified URL path.
Definition: WebAdmin.cpp:553
bool LoadIniFile(void)
Loads webadmin.ini into m_IniFile.
Definition: WebAdmin.cpp:234
void HandleRootRequest(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Handles requests for the root page.
Definition: WebAdmin.cpp:372
bool LoadLoginPage(void)
Loads the login template into m_LoginPage.
Definition: WebAdmin.cpp:144
bool Start(void)
Starts the HTTP server taking care of the webadmin.
Definition: WebAdmin.cpp:110
bool Init(void)
Initializes the object.
Definition: WebAdmin.cpp:81
cWebAdmin(void)
Definition: WebAdmin.cpp:61
bool m_IsRunning
Set to true if Start() succeeds in starting the server, reset back to false in Stop().
Definition: WebAdmin.h:249
virtual ~cWebAdmin() override
Definition: WebAdmin.cpp:72
bool HasUsers()
Checks inside the webadmin.ini file if there are users configured.
Definition: WebAdmin.cpp:258
void RemoveAllPluginWebTabs(const AString &a_PluginName)
Removes all WebTabs registered by the specified plugin.
Definition: WebAdmin.cpp:167
static AString GetURLEncodedString(const AString &a_Input)
Escapes the string for use in an URL Exported to Lua in ManualBindings.cpp.
Definition: WebAdmin.cpp:604
void Reload(void)
Reloads m_IniFile, m_LoginPage and m_TemplateScript.
Definition: WebAdmin.cpp:182
void AddWebTab(const AString &a_Title, const AString &a_UrlPath, const AString &a_PluginName, std::shared_ptr< cWebTabCallback > a_Callback)
Adds a new WebTab handler.
Definition: WebAdmin.cpp:538
cWebTabPtrs m_WebTabs
All registered WebTab handlers.
Definition: WebAdmin.h:231
cHTTPServer m_HTTPServer
The HTTP server which provides the underlying HTTP parsing, serialization and events.
Definition: WebAdmin.h:255
static AString GetBaseURL(const AString &a_URL)
Returns the prefix needed for making a link point to the webadmin root from the given URL ("....
Definition: WebAdmin.cpp:529
static AString GetHTMLEscapedString(const AString &a_Input)
Escapes text passed into it, so it can be embedded into html.
Definition: WebAdmin.cpp:573
bool m_IsInitialized
Set to true if Init() succeeds and the webadmin isn't to be disabled.
Definition: WebAdmin.h:246
sWebAdminPage GetPage(const HTTPRequest &a_Request)
Returns the (inner) page contents for the specified request.
Definition: WebAdmin.cpp:478
AString m_LoginPage
The HTML page that provides the login.
Definition: WebAdmin.h:239