1 /* Copyright (c) 2013-2017 the Civetweb developers
2  * Copyright (c) 2013 No Face Press, LLC
3  *
4  * License http://opensource.org/licenses/mit-license.php MIT License
5  */
6 
7 #ifndef CIVETSERVER_HEADER_INCLUDED
8 #define CIVETSERVER_HEADER_INCLUDED
9 #ifdef __cplusplus
10 
11 #include "civetweb.h"
12 #include <map>
13 #include <stdexcept>
14 #include <string>
15 #include <vector>
16 
17 #ifndef CIVETWEB_CXX_API
18 #if defined(_WIN32)
19 #if defined(CIVETWEB_CXX_DLL_EXPORTS)
20 #define CIVETWEB_CXX_API __declspec(dllexport)
21 #elif defined(CIVETWEB_CXX_DLL_IMPORTS)
22 #define CIVETWEB_CXX_API __declspec(dllimport)
23 #else
24 #define CIVETWEB_CXX_API
25 #endif
26 #elif __GNUC__ >= 4
27 #define CIVETWEB_CXX_API __attribute__((visibility("default")))
28 #else
29 #define CIVETWEB_CXX_API
30 #endif
31 #endif
32 
33 // forward declaration
34 class CivetServer;
35 
36 /**
37  * Exception class for thrown exceptions within the CivetHandler object.
38  */
39 class CIVETWEB_CXX_API CivetException : public std::runtime_error
40 {
41   public:
CivetException(const std::string & msg)42 	CivetException(const std::string &msg) : std::runtime_error(msg)
43 	{
44 	}
45 };
46 
47 /**
48  * Basic interface for a URI request handler.  Handlers implementations
49  * must be reentrant.
50  */
51 class CIVETWEB_CXX_API CivetHandler
52 {
53   public:
54 	/**
55 	 * Destructor
56 	 */
~CivetHandler()57 	virtual ~CivetHandler()
58 	{
59 	}
60 
61 	/**
62 	 * Callback method for GET request.
63 	 *
64 	 * @param server - the calling server
65 	 * @param conn - the connection information
66 	 * @returns true if implemented, false otherwise
67 	 */
68 	virtual bool handleGet(CivetServer *server, struct mg_connection *conn);
69 
70 	/**
71 	 * Callback method for GET request.
72 	 *
73 	 * @param server - the calling server
74 	 * @param conn - the connection information
75 	 * @param http - pointer to return status code
76 	 * @returns true if implemented, false otherwise
77 	 */
78 	virtual bool handleGet(CivetServer *server,
79 	                       struct mg_connection *conn,
80 	                       int *status_code);
81 
82 	/**
83 	 * Callback method for POST request.
84 	 *
85 	 * @param server - the calling server
86 	 * @param conn - the connection information
87 	 * @returns true if implemented, false otherwise
88 	 */
89 	virtual bool handlePost(CivetServer *server, struct mg_connection *conn);
90 
91 	/**
92 	 * Callback method for POST request.
93 	 *
94 	 * @param server - the calling server
95 	 * @param conn - the connection information
96 	 * @param http - pointer to return status code
97 	 * @returns true if implemented, false otherwise
98 	 */
99 	virtual bool handlePost(CivetServer *server,
100 	                        struct mg_connection *conn,
101 	                        int *status_code);
102 
103 	/**
104 	 * Callback method for HEAD request.
105 	 *
106 	 * @param server - the calling server
107 	 * @param conn - the connection information
108 	 * @returns true if implemented, false otherwise
109 	 */
110 	virtual bool handleHead(CivetServer *server, struct mg_connection *conn);
111 
112 	/**
113 	 * Callback method for HEAD request.
114 	 *
115 	 * @param server - the calling server
116 	 * @param conn - the connection information
117 	 * @param http - pointer to return status code
118 	 * @returns true if implemented, false otherwise
119 	 */
120 	virtual bool handleHead(CivetServer *server,
121 	                        struct mg_connection *conn,
122 	                        int *status_code);
123 
124 	/**
125 	 * Callback method for PUT request.
126 	 *
127 	 * @param server - the calling server
128 	 * @param conn - the connection information
129 	 * @returns true if implemented, false otherwise
130 	 */
131 	virtual bool handlePut(CivetServer *server, struct mg_connection *conn);
132 
133 	/**
134 	 * Callback method for PUT request.
135 	 *
136 	 * @param server - the calling server
137 	 * @param conn - the connection information
138 	 * @param http - pointer to return status code
139 	 * @returns true if implemented, false otherwise
140 	 */
141 	virtual bool handlePut(CivetServer *server,
142 	                       struct mg_connection *conn,
143 	                       int *status_code);
144 
145 	/**
146 	 * Callback method for DELETE request.
147 	 *
148 	 * @param server - the calling server
149 	 * @param conn - the connection information
150 	 * @returns true if implemented, false otherwise
151 	 */
152 	virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);
153 
154 	/**
155 	 * Callback method for DELETE request.
156 	 *
157 	 * @param server - the calling server
158 	 * @param conn - the connection information
159 	 * @param http - pointer to return status code
160 	 * @returns true if implemented, false otherwise
161 	 */
162 	virtual bool handleDelete(CivetServer *server,
163 	                          struct mg_connection *conn,
164 	                          int *status_code);
165 
166 	/**
167 	 * Callback method for OPTIONS request.
168 	 *
169 	 * @param server - the calling server
170 	 * @param conn - the connection information
171 	 * @returns true if implemented, false otherwise
172 	 */
173 	virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);
174 
175 	/**
176 	 * Callback method for OPTIONS request.
177 	 *
178 	 * @param server - the calling server
179 	 * @param conn - the connection information
180 	 * @param http - pointer to return status code
181 	 * @returns true if implemented, false otherwise
182 	 */
183 	virtual bool handleOptions(CivetServer *server,
184 	                           struct mg_connection *conn,
185 	                           int *status_code);
186 
187 	/**
188 	 * Callback method for PATCH request.
189 	 *
190 	 * @param server - the calling server
191 	 * @param conn - the connection information
192 	 * @returns true if implemented, false otherwise
193 	 */
194 	virtual bool handlePatch(CivetServer *server, struct mg_connection *conn);
195 
196 	/**
197 	 * Callback method for PATCH request.
198 	 *
199 	 * @param server - the calling server
200 	 * @param conn - the connection information
201 	 * @param http - pointer to return status code
202 	 * @returns true if implemented, false otherwise
203 	 */
204 	virtual bool handlePatch(CivetServer *server,
205 	                         struct mg_connection *conn,
206 	                         int *status_code);
207 };
208 
209 /**
210  * Basic interface for a URI authorization handler.  Handler implementations
211  * must be reentrant.
212  */
213 class CIVETWEB_CXX_API CivetAuthHandler
214 {
215   public:
216 	/**
217 	 * Destructor
218 	 */
~CivetAuthHandler()219 	virtual ~CivetAuthHandler()
220 	{
221 	}
222 
223 	/**
224 	 * Callback method for authorization requests. It is up the this handler
225 	 * to generate 401 responses if authorization fails.
226 	 *
227 	 * @param server - the calling server
228 	 * @param conn - the connection information
229 	 * @returns true if authorization succeeded, false otherwise
230 	 */
231 	virtual bool authorize(CivetServer *server, struct mg_connection *conn) = 0;
232 };
233 
234 /**
235  * Basic interface for a websocket handler.  Handlers implementations
236  * must be reentrant.
237  */
238 class CIVETWEB_CXX_API CivetWebSocketHandler
239 {
240   public:
241 	/**
242 	 * Destructor
243 	 */
~CivetWebSocketHandler()244 	virtual ~CivetWebSocketHandler()
245 	{
246 	}
247 
248 	/**
249 	 * Callback method for when the client intends to establish a websocket
250 	 *connection, before websocket handshake.
251 	 *
252 	 * @param server - the calling server
253 	 * @param conn - the connection information
254 	 * @returns true to keep socket open, false to close it
255 	 */
256 	virtual bool handleConnection(CivetServer *server,
257 	                              const struct mg_connection *conn);
258 
259 	/**
260 	 * Callback method for when websocket handshake is successfully completed,
261 	 *and connection is ready for data exchange.
262 	 *
263 	 * @param server - the calling server
264 	 * @param conn - the connection information
265 	 */
266 	virtual void handleReadyState(CivetServer *server,
267 	                              struct mg_connection *conn);
268 
269 	/**
270 	 * Callback method for when a data frame has been received from the client.
271 	 *
272 	 * @param server - the calling server
273 	 * @param conn - the connection information
274 	 * @bits: first byte of the websocket frame, see websocket RFC at
275 	 *http://tools.ietf.org/html/rfc6455, section 5.2
276 	 * @data, data_len: payload, with mask (if any) already applied.
277 	 * @returns true to keep socket open, false to close it
278 	 */
279 	virtual bool handleData(CivetServer *server,
280 	                        struct mg_connection *conn,
281 	                        int bits,
282 	                        char *data,
283 	                        size_t data_len);
284 
285 	/**
286 	 * Callback method for when the connection is closed.
287 	 *
288 	 * @param server - the calling server
289 	 * @param conn - the connection information
290 	 */
291 	virtual void handleClose(CivetServer *server,
292 	                         const struct mg_connection *conn);
293 };
294 
295 /**
296  * CivetCallbacks
297  *
298  * wrapper for mg_callbacks
299  */
300 struct CIVETWEB_CXX_API CivetCallbacks : public mg_callbacks {
301 	CivetCallbacks();
302 };
303 
304 /**
305  * CivetServer
306  *
307  * Basic class for embedded web server.  This has an URL mapping built-in.
308  */
309 class CIVETWEB_CXX_API CivetServer
310 {
311   public:
312 	/**
313 	 * Constructor
314 	 *
315 	 * This automatically starts the sever.
316 	 * It is good practice to call getContext() after this in case there
317 	 * were errors starting the server.
318 	 *
319 	 * Note: CivetServer should not be used as a static instance in a Windows
320 	 * DLL, since the constructor creates threads and the destructor joins
321 	 * them again (creating/joining threads should not be done in static
322 	 * constructors).
323 	 *
324 	 * @param options - the web server options.
325 	 * @param callbacks - optional web server callback methods.
326 	 *
327 	 * @throws CivetException
328 	 */
329 	CivetServer(const char **options,
330 	            const struct CivetCallbacks *callbacks = 0,
331 	            const void *UserContext = 0);
332 	CivetServer(const std::vector<std::string> &options,
333 	            const struct CivetCallbacks *callbacks = 0,
334 	            const void *UserContext = 0);
335 
336 	/**
337 	 * Destructor
338 	 */
339 	virtual ~CivetServer();
340 
341 	/**
342 	 * close()
343 	 *
344 	 * Stops server and frees resources.
345 	 */
346 	void close();
347 
348 	/**
349 	 * getContext()
350 	 *
351 	 * @return the context or 0 if not running.
352 	 */
353 	const struct mg_context *
getContext()354 	getContext() const
355 	{
356 		return context;
357 	}
358 
359 	/**
360 	 * addHandler(const std::string &, CivetHandler *)
361 	 *
362 	 * Adds a URI handler.  If there is existing URI handler, it will
363 	 * be replaced with this one.
364 	 *
365 	 * URI's are ordered and prefix (REST) URI's are supported.
366 	 *
367 	 *  @param uri - URI to match.
368 	 *  @param handler - handler instance to use.
369 	 */
370 	void addHandler(const std::string &uri, CivetHandler *handler);
371 
372 	void
addHandler(const std::string & uri,CivetHandler & handler)373 	addHandler(const std::string &uri, CivetHandler &handler)
374 	{
375 		addHandler(uri, &handler);
376 	}
377 
378 	/**
379 	 * addWebSocketHandler
380 	 *
381 	 * Adds a WebSocket handler for a specific URI.  If there is existing URI
382 	 *handler, it will
383 	 * be replaced with this one.
384 	 *
385 	 * URI's are ordered and prefix (REST) URI's are supported.
386 	 *
387 	 *  @param uri - URI to match.
388 	 *  @param handler - handler instance to use.
389 	 */
390 	void addWebSocketHandler(const std::string &uri,
391 	                         CivetWebSocketHandler *handler);
392 
393 	void
addWebSocketHandler(const std::string & uri,CivetWebSocketHandler & handler)394 	addWebSocketHandler(const std::string &uri, CivetWebSocketHandler &handler)
395 	{
396 		addWebSocketHandler(uri, &handler);
397 	}
398 
399 	/**
400 	 * removeHandler(const std::string &)
401 	 *
402 	 * Removes a handler.
403 	 *
404 	 * @param uri - the exact URL used in addHandler().
405 	 */
406 	void removeHandler(const std::string &uri);
407 
408 	/**
409 	 * removeWebSocketHandler(const std::string &)
410 	 *
411 	 * Removes a web socket handler.
412 	 *
413 	 * @param uri - the exact URL used in addWebSocketHandler().
414 	 */
415 	void removeWebSocketHandler(const std::string &uri);
416 
417 	/**
418 	 * addAuthHandler(const std::string &, CivetAuthHandler *)
419 	 *
420 	 * Adds a URI authorization handler.  If there is existing URI authorization
421 	 * handler, it will be replaced with this one.
422 	 *
423 	 * URI's are ordered and prefix (REST) URI's are supported.
424 	 *
425 	 * @param uri - URI to match.
426 	 * @param handler - authorization handler instance to use.
427 	 */
428 	void addAuthHandler(const std::string &uri, CivetAuthHandler *handler);
429 
430 	void
addAuthHandler(const std::string & uri,CivetAuthHandler & handler)431 	addAuthHandler(const std::string &uri, CivetAuthHandler &handler)
432 	{
433 		addAuthHandler(uri, &handler);
434 	}
435 
436 	/**
437 	 * removeAuthHandler(const std::string &)
438 	 *
439 	 * Removes an authorization handler.
440 	 *
441 	 * @param uri - the exact URL used in addAuthHandler().
442 	 */
443 	void removeAuthHandler(const std::string &uri);
444 
445 	/**
446 	 * getListeningPorts()
447 	 *
448 	 * Returns a list of ports that are listening
449 	 *
450 	 * @return A vector of ports
451 	 */
452 
453 	std::vector<int> getListeningPorts();
454 
455 	/**
456 	 * getListeningPorts()
457 	 *
458 	 * Variant of getListeningPorts() returning the full port information
459 	 * (protocol, SSL, ...)
460 	 *
461 	 * @return A vector of ports
462 	 */
463 	std::vector<struct mg_server_port> getListeningPortsFull();
464 
465 	/**
466 	 * getCookie(struct mg_connection *conn, const std::string &cookieName,
467 	 * std::string &cookieValue)
468 	 *
469 	 * Puts the cookie value string that matches the cookie name in the
470 	 * cookieValue destination string.
471 	 *
472 	 * @param conn - the connection information
473 	 * @param cookieName - cookie name to get the value from
474 	 * @param cookieValue - cookie value is returned using this reference
475 	 * @returns the size of the cookie value string read.
476 	 */
477 	static int getCookie(struct mg_connection *conn,
478 	                     const std::string &cookieName,
479 	                     std::string &cookieValue);
480 
481 	/**
482 	 * getHeader(struct mg_connection *conn, const std::string &headerName)
483 	 * @param conn - the connection information
484 	 * @param headerName - header name to get the value from
485 	 * @returns a char array which contains the header value as string
486 	 */
487 	static const char *getHeader(struct mg_connection *conn,
488 	                             const std::string &headerName);
489 
490 	/**
491 	 * getMethod(struct mg_connection *conn)
492 	 * @param conn - the connection information
493 	 * @returns method of HTTP request
494 	 */
495 	static const char *getMethod(struct mg_connection *conn);
496 
497 	/**
498 	 * getParam(struct mg_connection *conn, const char *, std::string &, size_t)
499 	 *
500 	 * Returns a query which contained in the supplied buffer.  The
501 	 * occurrence value is a zero-based index of a particular key name.  This
502 	 * should not be confused with the index over all of the keys.  Note that
503 	 *this
504 	 * function assumes that parameters are sent as text in http query string
505 	 * format, which is the default for web forms. This function will work for
506 	 * html forms with method="GET" and method="POST" attributes. In other
507 	 *cases,
508 	 * you may use a getParam version that directly takes the data instead of
509 	 *the
510 	 * connection as a first argument.
511 	 *
512 	 * @param conn - parameters are read from the data sent through this
513 	 *connection
514 	 * @param name - the key to search for
515 	 * @param dst - the destination string
516 	 * @param occurrence - the occurrence of the selected name in the query (0
517 	 *based).
518 	 * @return true if key was found
519 	 */
520 	static bool getParam(struct mg_connection *conn,
521 	                     const char *name,
522 	                     std::string &dst,
523 	                     size_t occurrence = 0);
524 
525 	/**
526 	 * getParam(const std::string &, const char *, std::string &, size_t)
527 	 *
528 	 * Returns a query parameter contained in the supplied buffer.  The
529 	 * occurrence value is a zero-based index of a particular key name.  This
530 	 * should not be confused with the index over all of the keys.
531 	 *
532 	 * @param data - the query string (text)
533 	 * @param name - the key to search for
534 	 * @param dst - the destination string
535 	 * @param occurrence - the occurrence of the selected name in the query (0
536 	 *based).
537 	 * @return true if key was found
538 	 */
539 	static bool
540 	getParam(const std::string &data,
541 	         const char *name,
542 	         std::string &dst,
543 	         size_t occurrence = 0)
544 	{
545 		return getParam(data.c_str(), data.length(), name, dst, occurrence);
546 	}
547 
548 	/**
549 	 * getParam(const char *, size_t, const char *, std::string &, size_t)
550 	 *
551 	 * Returns a query parameter contained in the supplied buffer.  The
552 	 * occurrence value is a zero-based index of a particular key name.  This
553 	 * should not be confused with the index over all of the keys.
554 	 *
555 	 * @param data the - query string (text)
556 	 * @param data_len - length of the query string
557 	 * @param name - the key to search for
558 	 * @param dst - the destination string
559 	 * @param occurrence - the occurrence of the selected name in the query (0
560 	 *based).
561 	 * @return true if key was found
562 	 */
563 	static bool getParam(const char *data,
564 	                     size_t data_len,
565 	                     const char *name,
566 	                     std::string &dst,
567 	                     size_t occurrence = 0);
568 
569 	/**
570 	 * getPostData(struct mg_connection *)
571 	 *
572 	 * Returns response body from a request made as POST. Since the
573 	 * connections map is protected, it can't be directly accessed.
574 	 * This uses string to store post data to handle big posts.
575 	 *
576 	 * @param conn - connection from which post data will be read
577 	 * @return Post data (empty if not available).
578 	 */
579 	static std::string getPostData(struct mg_connection *conn);
580 
581 	/**
582 	 * urlDecode(const std::string &, std::string &, bool)
583 	 *
584 	 * @param src - string to be decoded
585 	 * @param dst - destination string
586 	 * @param is_form_url_encoded - true if form url encoded
587 	 *       form-url-encoded data differs from URI encoding in a way that it
588 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
589 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
590 	 */
591 	static void
592 	urlDecode(const std::string &src,
593 	          std::string &dst,
594 	          bool is_form_url_encoded = true)
595 	{
596 		urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
597 	}
598 
599 	/**
600 	 * urlDecode(const char *, size_t, std::string &, bool)
601 	 *
602 	 * @param src - buffer to be decoded
603 	 * @param src_len - length of buffer to be decoded
604 	 * @param dst - destination string
605 	 * @param is_form_url_encoded - true if form url encoded
606 	 *       form-url-encoded data differs from URI encoding in a way that it
607 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
608 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
609 	 */
610 	static void urlDecode(const char *src,
611 	                      size_t src_len,
612 	                      std::string &dst,
613 	                      bool is_form_url_encoded = true);
614 
615 	/**
616 	 * urlDecode(const char *, std::string &, bool)
617 	 *
618 	 * @param src - buffer to be decoded (0 terminated)
619 	 * @param dst - destination string
620 	 * @param is_form_url_encoded true - if form url encoded
621 	 *       form-url-encoded data differs from URI encoding in a way that it
622 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
623 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
624 	 */
625 	static void urlDecode(const char *src,
626 	                      std::string &dst,
627 	                      bool is_form_url_encoded = true);
628 
629 	/**
630 	 * urlEncode(const std::string &, std::string &, bool)
631 	 *
632 	 * @param src - buffer to be encoded
633 	 * @param dst - destination string
634 	 * @param append - true if string should not be cleared before encoding.
635 	 */
636 	static void
637 	urlEncode(const std::string &src, std::string &dst, bool append = false)
638 	{
639 		urlEncode(src.c_str(), src.length(), dst, append);
640 	}
641 
642 	/**
643 	 * urlEncode(const char *, size_t, std::string &, bool)
644 	 *
645 	 * @param src - buffer to be encoded (0 terminated)
646 	 * @param dst - destination string
647 	 * @param append - true if string should not be cleared before encoding.
648 	 */
649 	static void
650 	urlEncode(const char *src, std::string &dst, bool append = false);
651 
652 	/**
653 	 * urlEncode(const char *, size_t, std::string &, bool)
654 	 *
655 	 * @param src - buffer to be encoded
656 	 * @param src_len - length of buffer to be decoded
657 	 * @param dst - destination string
658 	 * @param append - true if string should not be cleared before encoding.
659 	 */
660 	static void urlEncode(const char *src,
661 	                      size_t src_len,
662 	                      std::string &dst,
663 	                      bool append = false);
664 
665 	// generic user context which can be set/read,
666 	// the server does nothing with this apart from keep it.
667 	const void *
getUserContext()668 	getUserContext() const
669 	{
670 		return UserContext;
671 	}
672 
673   protected:
674 	class CivetConnection
675 	{
676 	  public:
677 		std::vector<char> postData;
678 	};
679 
680 	struct mg_context *context;
681 	std::map<const struct mg_connection *, CivetConnection> connections;
682 
683 	// generic user context which can be set/read,
684 	// the server does nothing with this apart from keep it.
685 	const void *UserContext;
686 
687   private:
688 	/**
689 	 * requestHandler(struct mg_connection *, void *cbdata)
690 	 *
691 	 * Handles the incoming request.
692 	 *
693 	 * @param conn - the connection information
694 	 * @param cbdata - pointer to the CivetHandler instance.
695 	 * @returns 0 if implemented, false otherwise
696 	 */
697 	static int requestHandler(struct mg_connection *conn, void *cbdata);
698 
699 	static int webSocketConnectionHandler(const struct mg_connection *conn,
700 	                                      void *cbdata);
701 	static void webSocketReadyHandler(struct mg_connection *conn, void *cbdata);
702 	static int webSocketDataHandler(struct mg_connection *conn,
703 	                                int bits,
704 	                                char *data,
705 	                                size_t data_len,
706 	                                void *cbdata);
707 	static void webSocketCloseHandler(const struct mg_connection *conn,
708 	                                  void *cbdata);
709 	/**
710 	 * authHandler(struct mg_connection *, void *cbdata)
711 	 *
712 	 * Handles the authorization requests.
713 	 *
714 	 * @param conn - the connection information
715 	 * @param cbdata - pointer to the CivetAuthHandler instance.
716 	 * @returns 1 if authorized, 0 otherwise
717 	 */
718 	static int authHandler(struct mg_connection *conn, void *cbdata);
719 
720 	/**
721 	 * closeHandler(struct mg_connection *)
722 	 *
723 	 * Handles closing a request (internal handler)
724 	 *
725 	 * @param conn - the connection information
726 	 */
727 	static void closeHandler(const struct mg_connection *conn);
728 
729 	/**
730 	 * Stores the user provided close handler
731 	 */
732 	void (*userCloseHandler)(const struct mg_connection *conn);
733 };
734 
735 #endif /*  __cplusplus */
736 #endif /* CIVETSERVER_HEADER_INCLUDED */
737