summaryrefslogtreecommitdiffstats
path: root/src/WebAdmin.h
blob: b76ca6df8aa5aeacec4f6f6ab92051af7a3e8aeb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

// WebAdmin.h

// Declares the cWebAdmin class representing the admin interface over http protocol, and related services (API)

#pragma once

#include "Bindings/LuaState.h"
#include "IniFile.h"
#include "HTTP/HTTPServer.h"
#include "HTTP/HTTPMessage.h"





// Disable MSVC warnings:
#if defined(_MSC_VER)
	#pragma warning(push)
	#pragma warning(disable:4355)  // 'this' : used in base member initializer list
#endif





// fwd:
class cEvent;
class cWebPlugin;





// tolua_begin
struct HTTPFormData
{
	std::string Name;
	std::string Value;
	std::string Type;
} ;
// tolua_end




// tolua_begin
struct HTTPRequest
{
	typedef std::map< std::string, std::string > StringStringMap;
	typedef std::map< std::string, HTTPFormData > FormDataMap;

	/** The entire URL presented to the HTTP server. */
	AString URL;

	/** HTTP method used for the request ("GET", "POST" etc.) */
	AString Method;

	/** The Path part of the request's URL (excluding GET params). */
	AString Path;

	/** Name of the logged-in user. Empty if not logged in. */
	AString Username;

	// tolua_end

	/** Parameters given in the URL, after the questionmark */
	StringStringMap Params;     // >> EXPORTED IN MANUALBINDINGS <<

	/** Parameters posted as a part of a form - either in the URL (GET method) or in the body (POST method) */
	StringStringMap PostParams;  // >> EXPORTED IN MANUALBINDINGS <<

	/** Same as PostParams */
	FormDataMap FormData;       // >> EXPORTED IN MANUALBINDINGS <<
} ;  // tolua_export





// tolua_begin
struct HTTPTemplateRequest
{
	HTTPRequest Request;
} ;
// tolua_end





struct sWebAdminPage
{
	AString Content;
	AString PluginName;
	AString TabTitle;
	AString TabUrlPath;
	AString ContentType;
};





// tolua_begin
class cWebAdmin :
	// tolua_end
	public cHTTPServer::cCallbacks
	// tolua_begin
{
public:
	// tolua_end

	/** Interface for getting the content of a single WebTab. */
	class cWebTabCallback abstract
	{
	public:
		// Force a virtual destructor in descendants
		virtual ~cWebTabCallback() {}

		/** Returns the contents for the specified request.
		Returns true if the call was successful, false on an error.
		a_Request is the full HTTP request object, as received from the client.
		a_UrlPath is the UrlPath of the WebTab registered for this request, as parsed from a_Request.
		Descendants should fill a_Content with the page contents
		and optionally set a_ContentType [defaults to "text/html"] */
		virtual bool Call(
			const HTTPRequest & a_Request,
			const AString & a_UrlPath,
			AString & a_Content,
			AString & a_ContentType
		) = 0;
	};


	/** Container for a single web tab.
	Each web tab has a title, URL path and an associated plugin's name.
	Each web tab is registered with a callback to provide the content. */
	class cWebTab
	{
	public:
		AString m_Title;
		AString m_UrlPath;
		AString m_PluginName;
		SharedPtr<cWebTabCallback> m_Callback;

		cWebTab(const AString & a_Title, const AString & a_UrlPath, const AString & a_PluginName, SharedPtr<cWebTabCallback> a_Callback):
			m_Title(a_Title),
			m_UrlPath(a_UrlPath),
			m_PluginName(a_PluginName),
			m_Callback(a_Callback)
		{
		}
	};
	typedef SharedPtr<cWebTab> cWebTabPtr;
	typedef std::vector<cWebTabPtr> cWebTabPtrs;


	cWebAdmin(void);
	virtual ~cWebAdmin();

	/** Initializes the object. Returns true if successfully initialized and ready to start */
	bool Init(void);

	/** Starts the HTTP server taking care of the webadmin. Returns true if successful */
	bool Start(void);

	/** Stops the HTTP server, if it was started. */
	void Stop(void);

	/** Loads the login template into m_LoginPage.
	Returns true if the loading succeeds, false if not. */
	bool LoadLoginPage(void);

	/** Returns a copy of all the registered web tabs.
	Exported to Lua in ManualBindings.cpp. */
	cWebTabPtrs GetAllWebTabs(void) { return m_WebTabs; }

	/** Removes all WebTabs registered by the specified plugin. */
	void RemoveAllPluginWebTabs(const AString & a_PluginName);

	/** Returns the (inner) page contents for the specified request.
	Calls the appropriate WebTab handler to get the contents.
	Exported to Lua in ManualBindings.cpp. */
	sWebAdminPage GetPage(const HTTPRequest & a_Request);

	// tolua_begin

	/** Reloads m_IniFile, m_LoginPage and m_TemplateScript.
	Note that reloading will not change the "enabled" state of the server, and it will not update listening ports. */
	void Reload(void);

	/** Returns the list of ports on which the webadmin is configured to listen. */
	AString GetPorts(void) const { return StringsConcat(m_Ports, ','); }
	// tolua_end

	/** Adds a new WebTab handler.
	a_Title is the display title of the tab
	a_UrlPath is the part of the URL that uniquely identifies this tab.
	a_PluginName is the display name of the plugin creating this tab.
	a_Callback is used to provide the actual WebTab contents, when requested.
	Exported in ManualBindings.cpp. */
	void AddWebTab(
		const AString & a_Title,
		const AString & a_UrlPath,
		const AString & a_PluginName,
		SharedPtr<cWebTabCallback> a_Callback
	);

	/** Removes the WebTab with the specified URL path.
	Returns true if WebTab was found and removed, false if not found.
	Exported in ManualBindings.cpp */
	bool DelWebTab(const AString & a_UrlPath);

	/** Escapes text passed into it, so it can be embedded into html.
	Exported to Lua in ManualBindings.cpp. */
	static AString GetHTMLEscapedString(const AString & a_Input);

	/** Escapes the string for use in an URL
	Exported to Lua in ManualBindings.cpp. */
	static AString GetURLEncodedString(const AString & a_Input);

	/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style).
	Exported to Lua in ManualBindings.cpp. */
	static AString GetBaseURL(const AString & a_URL);

	/** 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 an empty string.
	Exported to Lua in ManualBindings.cpp. */
	static AString GetContentTypeFromFileExt(const AString & a_FileExtension);

protected:

	/** Protects m_WebTabs, m_TemplateScript, m_LoginTemplate and m_IniFile against multithreaded access. */
	cCriticalSection m_CS;

	/** All registered WebTab handlers.
	Protected against multithreaded access by m_CS. */
	cWebTabPtrs m_WebTabs;

	/** The Lua template script to provide templates.
	Protected against multithreaded access by m_CS. */
	cLuaState m_TemplateScript;

	/** The HTML page that provides the login.
	Protected against multithreaded access by m_CS. */
	AString m_LoginPage;

	/** The webadmin.ini file, used for the settings and allowed logins.
	Protected against multithreaded access by m_CS. */
	cIniFile m_IniFile;

	/** Set to true if Init() succeeds and the webadmin isn't to be disabled */
	bool m_IsInitialized;

	/** Set to true if Start() succeeds in starting the server, reset back to false in Stop(). */
	bool m_IsRunning;

	/** The ports on which the webadmin is running. */
	AStringVector m_Ports;

	/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
	cHTTPServer m_HTTPServer;


	/** Loads webadmin.ini into m_IniFile.
	Creates a default file if it doesn't exist.
	Returns true if webadmin is enabled, false if disabled. */
	bool LoadIniFile(void);

	/** Handles requests coming to the "/webadmin" or "/~webadmin" URLs */
	void HandleWebadminRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request);

	/** Handles requests for the root page */
	void HandleRootRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request);

	/** Handles requests for a file */
	void HandleFileRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request);

	// cHTTPServer::cCallbacks overrides:
	virtual void OnRequestBegun   (cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) override;
	virtual void OnRequestBody    (cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size) override;
	virtual void OnRequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) override;
} ;  // tolua_export





// Revert MSVC warnings back to orignal state:
#if defined(_MSC_VER)
	#pragma warning(pop)
#endif