http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/examples/embedded_cpp/embedded_cpp.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/examples/embedded_cpp/embedded_cpp.cpp b/thirdparty/civetweb-1.10/examples/embedded_cpp/embedded_cpp.cpp new file mode 100644 index 0000000..d45a573 --- /dev/null +++ b/thirdparty/civetweb-1.10/examples/embedded_cpp/embedded_cpp.cpp @@ -0,0 +1,432 @@ +/* Copyright (c) 2013-2017 the Civetweb developers + * Copyright (c) 2013 No Face Press, LLC + * License http://opensource.org/licenses/mit-license.php MIT License + */ + +// Simple example program on how to use Embedded C++ interface. + +#include "CivetServer.h" +#include <cstring> + +#ifdef _WIN32 +#include <windows.h> +#else +#include <unistd.h> +#endif + +#define DOCUMENT_ROOT "." +#define PORT "8081" +#define EXAMPLE_URI "/example" +#define EXIT_URI "/exit" +bool exitNow = false; + +class ExampleHandler : public CivetHandler +{ + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "<html><body>\r\n"); + mg_printf(conn, + "<h2>This is an example text from a C++ handler</h2>\r\n"); + mg_printf(conn, + "<p>To see a page from the A handler <a " + "href=\"a\">click here</a></p>\r\n"); + mg_printf(conn, + "<p>To see a page from the A handler with a parameter " + "<a href=\"a?param=1\">click here</a></p>\r\n"); + mg_printf(conn, + "<p>To see a page from the A/B handler <a " + "href=\"a/b\">click here</a></p>\r\n"); + mg_printf(conn, + "<p>To see a page from the *.foo handler <a " + "href=\"xy.foo\">click here</a></p>\r\n"); + mg_printf(conn, + "<p>To see a page from the WebSocket handler <a " + "href=\"ws\">click here</a></p>\r\n"); + mg_printf(conn, + "<p>To exit <a href=\"%s\">click here</a></p>\r\n", + EXIT_URI); + mg_printf(conn, "</body></html>\r\n"); + return true; + } +}; + +class ExitHandler : public CivetHandler +{ + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "Bye!\n"); + exitNow = true; + return true; + } +}; + +class AHandler : public CivetHandler +{ + private: + bool + handleAll(const char *method, + CivetServer *server, + struct mg_connection *conn) + { + std::string s = ""; + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method); + if (CivetServer::getParam(conn, "param", s)) { + mg_printf(conn, "<p>param set to %s</p>", s.c_str()); + } else { + mg_printf(conn, "<p>param not set</p>"); + } + mg_printf(conn, "</body></html>\n"); + return true; + } + + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + return handleAll("GET", server, conn); + } + bool + handlePost(CivetServer *server, struct mg_connection *conn) + { + return handleAll("POST", server, conn); + } +}; + +class ABHandler : public CivetHandler +{ + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the AB handler!!!</h2>"); + mg_printf(conn, "</body></html>\n"); + return true; + } +}; + +class FooHandler : public CivetHandler +{ + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html\r\nConnection: close\r\n\r\n"); + + mg_printf(conn, "<html><body>\n"); + mg_printf(conn, "<h2>This is the Foo GET handler!!!</h2>\n"); + mg_printf(conn, + "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n", + req_info->request_method, + req_info->request_uri, + req_info->http_version); + mg_printf(conn, "</body></html>\n"); + + return true; + } + bool + handlePost(CivetServer *server, struct mg_connection *conn) + { + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + long long rlen, wlen; + long long nlen = 0; + long long tlen = req_info->content_length; + char buf[1024]; + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/html\r\nConnection: close\r\n\r\n"); + + mg_printf(conn, "<html><body>\n"); + mg_printf(conn, "<h2>This is the Foo POST handler!!!</h2>\n"); + mg_printf(conn, + "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n", + req_info->request_method, + req_info->request_uri, + req_info->http_version); + mg_printf(conn, "<p>Content Length: %li</p>\n", (long)tlen); + mg_printf(conn, "<pre>\n"); + + while (nlen < tlen) { + rlen = tlen - nlen; + if (rlen > sizeof(buf)) { + rlen = sizeof(buf); + } + rlen = mg_read(conn, buf, (size_t)rlen); + if (rlen <= 0) { + break; + } + wlen = mg_write(conn, buf, (size_t)rlen); + if (wlen != rlen) { + break; + } + nlen += wlen; + } + + mg_printf(conn, "\n</pre>\n"); + mg_printf(conn, "</body></html>\n"); + + return true; + } + + #define fopen_recursive fopen + + bool + handlePut(CivetServer *server, struct mg_connection *conn) + { + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + long long rlen, wlen; + long long nlen = 0; + long long tlen = req_info->content_length; + FILE * f; + char buf[1024]; + int fail = 0; + +#ifdef _WIN32 + _snprintf(buf, sizeof(buf), "D:\\somewhere\\%s\\%s", req_info->remote_user, req_info->local_uri); + buf[sizeof(buf)-1] = 0; + if (strlen(buf)>255) { + /* Windows will not work with path > 260 (MAX_PATH), unless we use + * the unicode API. However, this is just an example code: A real + * code will probably never store anything to D:\\somewhere and + * must be adapted to the specific needs anyhow. */ + fail = 1; + f = NULL; + } else { + f = fopen_recursive(buf, "wb"); + } +#else + snprintf(buf, sizeof(buf), "~/somewhere/%s/%s", req_info->remote_user, req_info->local_uri); + buf[sizeof(buf)-1] = 0; + if (strlen(buf)>1020) { + /* The string is too long and probably truncated. Make sure an + * UTF-8 string is never truncated between the UTF-8 code bytes. + * This example code must be adapted to the specific needs. */ + fail = 1; + f = NULL; + } else { + f = fopen_recursive(buf, "w"); + } +#endif + + if (!f) { + fail = 1; + } else { + while (nlen < tlen) { + rlen = tlen - nlen; + if (rlen > sizeof(buf)) { + rlen = sizeof(buf); + } + rlen = mg_read(conn, buf, (size_t)rlen); + if (rlen <= 0) { + fail = 1; + break; + } + wlen = fwrite(buf, 1, (size_t)rlen, f); + if (wlen != rlen) { + fail = 1; + break; + } + nlen += wlen; + } + fclose(f); + } + + if (fail) { + mg_printf(conn, + "HTTP/1.1 409 Conflict\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + } else { + mg_printf(conn, + "HTTP/1.1 201 Created\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + } + + return true; + } +}; + +class WsStartHandler : public CivetHandler +{ + public: + bool + handleGet(CivetServer *server, struct mg_connection *conn) + { + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + + mg_printf(conn, "<!DOCTYPE html>\n"); + mg_printf(conn, "<html>\n<head>\n"); + mg_printf(conn, "<meta charset=\"UTF-8\">\n"); + mg_printf(conn, "<title>Embedded websocket example</title>\n"); + +#ifdef USE_WEBSOCKET + /* mg_printf(conn, "<script type=\"text/javascript\"><![CDATA[\n"); ... + * xhtml style */ + mg_printf(conn, "<script>\n"); + mg_printf( + conn, + "var i=0\n" + "function load() {\n" + " var wsproto = (location.protocol === 'https:') ? 'wss:' : 'ws:';\n" + " connection = new WebSocket(wsproto + '//' + window.location.host + " + "'/websocket');\n" + " websock_text_field = " + "document.getElementById('websock_text_field');\n" + " connection.onmessage = function (e) {\n" + " websock_text_field.innerHTML=e.data;\n" + " i=i+1;" + " connection.send(i);\n" + " }\n" + " connection.onerror = function (error) {\n" + " alert('WebSocket error');\n" + " connection.close();\n" + " }\n" + "}\n"); + /* mg_printf(conn, "]]></script>\n"); ... xhtml style */ + mg_printf(conn, "</script>\n"); + mg_printf(conn, "</head>\n<body onload=\"load()\">\n"); + mg_printf( + conn, + "<div id='websock_text_field'>No websocket connection yet</div>\n"); +#else + mg_printf(conn, "</head>\n<body>\n"); + mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n"); +#endif + mg_printf(conn, "</body>\n</html>\n"); + + return 1; +} +}; + + +#ifdef USE_WEBSOCKET +class WebSocketHandler : public CivetWebSocketHandler { + + virtual bool handleConnection(CivetServer *server, + const struct mg_connection *conn) { + printf("WS connected\n"); + return true; + } + + virtual void handleReadyState(CivetServer *server, + struct mg_connection *conn) { + printf("WS ready\n"); + + const char *text = "Hello from the websocket ready handler"; + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text)); + } + + virtual bool handleData(CivetServer *server, + struct mg_connection *conn, + int bits, + char *data, + size_t data_len) { + printf("WS got %lu bytes: ", (long unsigned)data_len); + fwrite(data, 1, data_len, stdout); + printf("\n"); + + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len); + return (data_len<4); + } + + virtual void handleClose(CivetServer *server, + const struct mg_connection *conn) { + printf("WS closed\n"); + } +}; +#endif + + +int +main(int argc, char *argv[]) +{ + const char *options[] = { + "document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0}; + + std::vector<std::string> cpp_options; + for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) { + cpp_options.push_back(options[i]); + } + + // CivetServer server(options); // <-- C style start + CivetServer server(cpp_options); // <-- C++ style start + + ExampleHandler h_ex; + server.addHandler(EXAMPLE_URI, h_ex); + + ExitHandler h_exit; + server.addHandler(EXIT_URI, h_exit); + + AHandler h_a; + server.addHandler("/a", h_a); + + ABHandler h_ab; + server.addHandler("/a/b", h_ab); + + WsStartHandler h_ws; + server.addHandler("/ws", h_ws); + +#ifdef NO_FILES + /* This handler will handle "everything else", including + * requests to files. If this handler is installed, + * NO_FILES should be set. */ + FooHandler h_foo; + server.addHandler("", h_foo); + + printf("See a page from the \"all\" handler at http://localhost:%s/\n", PORT); +#else + FooHandler h_foo; + server.addHandler("**.foo", h_foo); + printf("Browse files at http://localhost:%s/\n", PORT); +#endif + +#ifdef USE_WEBSOCKET + WebSocketHandler h_websocket; + server.addWebSocketHandler("/websocket", h_websocket); + printf("Run websocket example at http://localhost:%s/ws\n", PORT); +#endif + + printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI); + printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI); + + while (!exitNow) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + + printf("Bye!\n"); + + return 0; +}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/examples/https/README.md ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/examples/https/README.md b/thirdparty/civetweb-1.10/examples/https/README.md new file mode 100644 index 0000000..7b18b47 --- /dev/null +++ b/thirdparty/civetweb-1.10/examples/https/README.md @@ -0,0 +1,15 @@ +HTTPS Server configuration example +==== + +This directory contains an example [`civetweb.conf`](civetweb.conf) configuration file for a secure HTTPS server. You can run a HTTPS server without most of the options there - only `ssl_certificate` and one port (e.g., `443s`) in `listening_ports` is required. The default settings will work, but not comply with up to date security standards. It is somewhat debatable what "up to date security" means - you can use the following web sites to run tests: + +- https://securityheaders.io +- https://www.htbridge.com/ssl +- https://www.htbridge.com/websec +- https://www.ssllabs.com/ssltest/analyze.html / https://www.qualys.com/forms/freescan/ +- probably there are some more ... let me know! + +Instructions to run the test and to adapt the configuration can be found [`civetweb.conf`](civetweb.conf). You can test this configuration directly with the standalone server, or you can take the settings and add it into your embedding code. + +Note: I do not take any warranty or liability for this configuration, or for the content of any linked web site. + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/examples/https/civetweb.conf ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/examples/https/civetweb.conf b/thirdparty/civetweb-1.10/examples/https/civetweb.conf new file mode 100644 index 0000000..cd10edd --- /dev/null +++ b/thirdparty/civetweb-1.10/examples/https/civetweb.conf @@ -0,0 +1,86 @@ +# Instructions to run (on Linux) to reproduce test results: +# +# 1) copy civetweb executable here (examples/https directory) +# 2) sudo ./civetweb +# +# Instructions to adapt to your own server: +# +# 1) generate your own server cert +# 2) generate at least one backup server cert +# in case you want a self signed cert, you can use the script +# in resources/cert for both steps +# 3) copy the content of the *.pin files into the Public-Key-Pins +# header config (the base64 encoded certificate hash) +# 4) set the document root, and all other required http server settings +# 5) Run the tests from the three websites below. They will tell you +# also what clients are compatible with your settings. The settings +# here are very strict and lock out most older clients/browsers. +# You will find some hints for fine tuning there as well. +# 6) If you know all your clients, and give them client certificates in +# advance, you can significantly improve security by setting +# "ssl_verify_peer" to "yes" and specifying a client cert (directory) +# using "ssl_ca_file/path". This will lock out all clients without a +# proper certificate. Don't use it for your public home page, but +# consider it for your private remote access server. +# 7) run civetweb, like above - or better create your own start script +# You are welcome to share your thoughts and experience on GitHub +# (or Google groups) - see README.md in CivetWeb main directory + +# Don't run as super user, switch back to a regular user +run_as_user user + +# The standard HTTP port 80 should redirect to the standard HTTPS port 443 +listening_ports 80r,443s + +# Don't forget to set the document root and domain +#document_root tdb +#authentication_domain mydomain.com + +# Set the a certificate +ssl_certificate ../../resources/cert/server.pem + +# Require a client cert for your private server (see above) +#ssl_verify_peer yes +#ssl_ca_file ../../resources/cert/client.pem + +# Enforce TLS1.2 and some strong cipher(s) +ssl_protocol_version 4 +ssl_cipher_list ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS + +# Tell all browsers to access this site only as HTTPS for the next 180 days +strict_transport_security_max_age 15552000 + +# Set some HTTP security header, see https://securityheaders.io +additional_header Content-Security-Policy: script-src 'self' +additional_header X-Frame-Options: SAMEORIGIN +additional_header X-Xss-Protection: 1; mode=block +additional_header X-Content-Type-Options: nosniff +additional_header Referrer-Policy: same-origin +additional_header Public-Key-Pins: pin-sha256="uz1UTAPen+xb+UoQqkVlEx4H653LbMjfRJcZx5OrjbI="; pin-sha256="pf3px1MBPmlTGAPoiHWqaSJ9L9Z+DKfwgsU7LfLnmsk="; max-age=7776000 +#additional_header Expect-CT: max-age=86400,report-uri="https://mydomain.com/report" + + +# Ratings from 2017-09-03 (tests performed later may require more +# strict security settings) +# +# Headers rated A+ from https://securityheaders.io/ +# +# SSL rated B from https://www.htbridge.com/ssl when using a self signed +# certificate, but no other weaknesses for modern browsers. +# Site remarks some older TLS versions and some weaker ciphers are not +# supported (but that's accessibility, not security). +# +# HTTPS rated A+ from https://www.htbridge.com/websec/ when using a self +# signed certificate, generated with make_certs.sh in resources/cert/ +# and adding the server.pin and server_bkup.pin content into the +# Public-Key-Pins header above. +# +# A rating of "T / If trust issues are ignored: A" (ignoring self-signed cert) +# from https://www.ssllabs.com/ssltest/, https://www.qualys.com/forms/freescan/ +# (Note: this test is runs with reverse DNS name, while all others use the +# IP address). +# +# Note: This settings are very strict and prevent some older but still common +# versions of major browsers to access this site. The test web sites will give +# you an overview. Test, before you use this settings. + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/format.bat ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/format.bat b/thirdparty/civetweb-1.10/format.bat new file mode 100755 index 0000000..e1ce640 --- /dev/null +++ b/thirdparty/civetweb-1.10/format.bat @@ -0,0 +1,33 @@ +#!/bin/sh +clang-format -i src/civetweb.c +clang-format -i src/main.c +clang-format -i src/CivetServer.cpp +clang-format -i src/civetweb_private_lua.h +clang-format -i src/md5.inl +clang-format -i src/sha1.inl +clang-format -i src/mod_lua.inl +clang-format -i src/mod_duktape.inl +clang-format -i src/timer.inl +clang-format -i src/handle_form.inl + +clang-format -i src/third_party/civetweb_lua.h + +clang-format -i include/civetweb.h +clang-format -i include/CivetServer.h + +clang-format -i test/public_func.h +clang-format -i test/public_func.c +clang-format -i test/public_server.h +clang-format -i test/public_server.c +clang-format -i test/private.h +clang-format -i test/private.c +clang-format -i test/private_exe.h +clang-format -i test/private_exe.c +clang-format -i test/shared.h +clang-format -i test/shared.c +clang-format -i test/timertest.h +clang-format -i test/timertest.c +clang-format -i test/civetweb_check.h +clang-format -i test/main.c + +clang-format -i examples/embedded_c/embedded_c.c http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/include/CivetServer.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.10/include/CivetServer.h b/thirdparty/civetweb-1.10/include/CivetServer.h new file mode 100644 index 0000000..2da1096 --- /dev/null +++ b/thirdparty/civetweb-1.10/include/CivetServer.h @@ -0,0 +1,611 @@ +/* Copyright (c) 2013-2017 the Civetweb developers + * Copyright (c) 2013 No Face Press, LLC + * + * License http://opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _CIVETWEB_SERVER_H_ +#define _CIVETWEB_SERVER_H_ +#ifdef __cplusplus + +#include "civetweb.h" +#include <map> +#include <string> +#include <vector> +#include <stdexcept> + +// forward declaration +class CivetServer; + +/** + * Exception class for thrown exceptions within the CivetHandler object. + */ +class CIVETWEB_API CivetException : public std::runtime_error +{ + public: + CivetException(const std::string &msg) : std::runtime_error(msg) + { + } +}; + +/** + * Basic interface for a URI request handler. Handlers implementations + * must be reentrant. + */ +class CIVETWEB_API CivetHandler +{ + public: + /** + * Destructor + */ + virtual ~CivetHandler() + { + } + + /** + * Callback method for GET request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handleGet(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for POST request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handlePost(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for HEAD request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handleHead(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for PUT request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handlePut(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for DELETE request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handleDelete(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for OPTIONS request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handleOptions(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for PATCH request. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if implemented, false otherwise + */ + virtual bool handlePatch(CivetServer *server, struct mg_connection *conn); +}; + +/** + * Basic interface for a URI authorization handler. Handler implementations + * must be reentrant. + */ +class CIVETWEB_API CivetAuthHandler +{ + public: + /** + * Destructor + */ + virtual ~CivetAuthHandler() + { + } + + /** + * Callback method for authorization requests. It is up the this handler + * to generate 401 responses if authorization fails. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true if authorization succeeded, false otherwise + */ + virtual bool authorize(CivetServer *server, struct mg_connection *conn) = 0; +}; + +/** + * Basic interface for a websocket handler. Handlers implementations + * must be reentrant. + */ +class CIVETWEB_API CivetWebSocketHandler +{ + public: + /** + * Destructor + */ + virtual ~CivetWebSocketHandler() + { + } + + /** + * Callback method for when the client intends to establish a websocket + *connection, before websocket handshake. + * + * @param server - the calling server + * @param conn - the connection information + * @returns true to keep socket open, false to close it + */ + virtual bool handleConnection(CivetServer *server, + const struct mg_connection *conn); + + /** + * Callback method for when websocket handshake is successfully completed, + *and connection is ready for data exchange. + * + * @param server - the calling server + * @param conn - the connection information + */ + virtual void handleReadyState(CivetServer *server, + struct mg_connection *conn); + + /** + * Callback method for when a data frame has been received from the client. + * + * @param server - the calling server + * @param conn - the connection information + * @bits: first byte of the websocket frame, see websocket RFC at + *http://tools.ietf.org/html/rfc6455, section 5.2 + * @data, data_len: payload, with mask (if any) already applied. + * @returns true to keep socket open, false to close it + */ + virtual bool handleData(CivetServer *server, + struct mg_connection *conn, + int bits, + char *data, + size_t data_len); + + /** + * Callback method for when the connection is closed. + * + * @param server - the calling server + * @param conn - the connection information + */ + virtual void handleClose(CivetServer *server, + const struct mg_connection *conn); +}; + +/** + * CivetCallbacks + * + * wrapper for mg_callbacks + */ +struct CIVETWEB_API CivetCallbacks : public mg_callbacks { + CivetCallbacks(); +}; + +/** + * CivetServer + * + * Basic class for embedded web server. This has an URL mapping built-in. + */ +class CIVETWEB_API CivetServer +{ + public: + /** + * Constructor + * + * This automatically starts the sever. + * It is good practice to call getContext() after this in case there + * were errors starting the server. + * + * Note: CivetServer should not be used as a static instance in a Windows + * DLL, since the constructor creates threads and the destructor joins + * them again (creating/joining threads should not be done in static + * constructors). + * + * @param options - the web server options. + * @param callbacks - optional web server callback methods. + * + * @throws CivetException + */ + CivetServer(const char **options, + const struct CivetCallbacks *callbacks = 0, + const void *UserContext = 0); + CivetServer(std::vector<std::string> options, + const struct CivetCallbacks *callbacks = 0, + const void *UserContext = 0); + + /** + * Destructor + */ + virtual ~CivetServer(); + + /** + * close() + * + * Stops server and frees resources. + */ + void close(); + + /** + * getContext() + * + * @return the context or 0 if not running. + */ + const struct mg_context * + getContext() const + { + return context; + } + + /** + * addHandler(const std::string &, CivetHandler *) + * + * Adds a URI handler. If there is existing URI handler, it will + * be replaced with this one. + * + * URI's are ordered and prefix (REST) URI's are supported. + * + * @param uri - URI to match. + * @param handler - handler instance to use. + */ + void addHandler(const std::string &uri, CivetHandler *handler); + + void + addHandler(const std::string &uri, CivetHandler &handler) + { + addHandler(uri, &handler); + } + + /** + * addWebSocketHandler + * + * Adds a WebSocket handler for a specific URI. If there is existing URI + *handler, it will + * be replaced with this one. + * + * URI's are ordered and prefix (REST) URI's are supported. + * + * @param uri - URI to match. + * @param handler - handler instance to use. + */ + void addWebSocketHandler(const std::string &uri, + CivetWebSocketHandler *handler); + + void + addWebSocketHandler(const std::string &uri, CivetWebSocketHandler &handler) + { + addWebSocketHandler(uri, &handler); + } + + /** + * removeHandler(const std::string &) + * + * Removes a handler. + * + * @param uri - the exact URL used in addHandler(). + */ + void removeHandler(const std::string &uri); + + /** + * removeWebSocketHandler(const std::string &) + * + * Removes a web socket handler. + * + * @param uri - the exact URL used in addWebSocketHandler(). + */ + void removeWebSocketHandler(const std::string &uri); + + /** + * addAuthHandler(const std::string &, CivetAuthHandler *) + * + * Adds a URI authorization handler. If there is existing URI authorization + * handler, it will be replaced with this one. + * + * URI's are ordered and prefix (REST) URI's are supported. + * + * @param uri - URI to match. + * @param handler - authorization handler instance to use. + */ + void addAuthHandler(const std::string &uri, CivetAuthHandler *handler); + + void + addAuthHandler(const std::string &uri, CivetAuthHandler &handler) + { + addAuthHandler(uri, &handler); + } + + /** + * removeAuthHandler(const std::string &) + * + * Removes an authorization handler. + * + * @param uri - the exact URL used in addAuthHandler(). + */ + void removeAuthHandler(const std::string &uri); + + /** + * getListeningPorts() + * + * Returns a list of ports that are listening + * + * @return A vector of ports + */ + + std::vector<int> getListeningPorts(); + + /** + * getCookie(struct mg_connection *conn, const std::string &cookieName, + *std::string &cookieValue) + * + * Puts the cookie value string that matches the cookie name in the + *cookieValue destinaton string. + * + * @param conn - the connection information + * @param cookieName - cookie name to get the value from + * @param cookieValue - cookie value is returned using thiis reference + * @returns the size of the cookie value string read. + */ + static int getCookie(struct mg_connection *conn, + const std::string &cookieName, + std::string &cookieValue); + + /** + * getHeader(struct mg_connection *conn, const std::string &headerName) + * @param conn - the connection information + * @param headerName - header name to get the value from + * @returns a char array whcih contains the header value as string + */ + static const char *getHeader(struct mg_connection *conn, + const std::string &headerName); + + /** + * getParam(struct mg_connection *conn, const char *, std::string &, size_t) + * + * Returns a query paramter contained in the supplied buffer. The + * occurance value is a zero-based index of a particular key name. This + * should not be confused with the index over all of the keys. Note that + *this + * function assumes that parameters are sent as text in http query string + * format, which is the default for web forms. This function will work for + * html forms with method="GET" and method="POST" attributes. In other + *cases, + * you may use a getParam version that directly takes the data instead of + *the + * connection as a first argument. + * + * @param conn - parameters are read from the data sent through this + *connection + * @param name - the key to search for + * @param dst - the destination string + * @param occurrence - the occurrence of the selected name in the query (0 + *based). + * @return true if key was found + */ + static bool getParam(struct mg_connection *conn, + const char *name, + std::string &dst, + size_t occurrence = 0); + + /** + * getParam(const std::string &, const char *, std::string &, size_t) + * + * Returns a query paramter contained in the supplied buffer. The + * occurance value is a zero-based index of a particular key name. This + * should not be confused with the index over all of the keys. + * + * @param data - the query string (text) + * @param name - the key to search for + * @param dst - the destination string + * @param occurrence - the occurrence of the selected name in the query (0 + *based). + * @return true if key was found + */ + static bool + getParam(const std::string &data, + const char *name, + std::string &dst, + size_t occurrence = 0) + { + return getParam(data.c_str(), data.length(), name, dst, occurrence); + } + + /** + * getParam(const char *, size_t, const char *, std::string &, size_t) + * + * Returns a query paramter contained in the supplied buffer. The + * occurance value is a zero-based index of a particular key name. This + * should not be confused with the index over all of the keys. + * + * @param data the - query string (text) + * @param data_len - length of the query string + * @param name - the key to search for + * @param dst - the destination string + * @param occurrence - the occurrence of the selected name in the query (0 + *based). + * @return true if key was found + */ + static bool getParam(const char *data, + size_t data_len, + const char *name, + std::string &dst, + size_t occurrence = 0); + + /** + * urlDecode(const std::string &, std::string &, bool) + * + * @param src - string to be decoded + * @param dst - destination string + * @param is_form_url_encoded - true if form url encoded + * form-url-encoded data differs from URI encoding in a way that it + * uses '+' as character for space, see RFC 1866 section 8.2.1 + * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt + */ + static void + urlDecode(const std::string &src, + std::string &dst, + bool is_form_url_encoded = true) + { + urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded); + } + + /** + * urlDecode(const char *, size_t, std::string &, bool) + * + * @param src - buffer to be decoded + * @param src_len - length of buffer to be decoded + * @param dst - destination string + * @param is_form_url_encoded - true if form url encoded + * form-url-encoded data differs from URI encoding in a way that it + * uses '+' as character for space, see RFC 1866 section 8.2.1 + * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt + */ + static void urlDecode(const char *src, + size_t src_len, + std::string &dst, + bool is_form_url_encoded = true); + + /** + * urlDecode(const char *, std::string &, bool) + * + * @param src - buffer to be decoded (0 terminated) + * @param dst - destination string + * @param is_form_url_encoded true - if form url encoded + * form-url-encoded data differs from URI encoding in a way that it + * uses '+' as character for space, see RFC 1866 section 8.2.1 + * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt + */ + static void urlDecode(const char *src, + std::string &dst, + bool is_form_url_encoded = true); + + /** + * urlEncode(const std::string &, std::string &, bool) + * + * @param src - buffer to be encoded + * @param dst - destination string + * @param append - true if string should not be cleared before encoding. + */ + static void + urlEncode(const std::string &src, std::string &dst, bool append = false) + { + urlEncode(src.c_str(), src.length(), dst, append); + } + + /** + * urlEncode(const char *, size_t, std::string &, bool) + * + * @param src - buffer to be encoded (0 terminated) + * @param dst - destination string + * @param append - true if string should not be cleared before encoding. + */ + static void + urlEncode(const char *src, std::string &dst, bool append = false); + + /** + * urlEncode(const char *, size_t, std::string &, bool) + * + * @param src - buffer to be encoded + * @param src_len - length of buffer to be decoded + * @param dst - destination string + * @param append - true if string should not be cleared before encoding. + */ + static void urlEncode(const char *src, + size_t src_len, + std::string &dst, + bool append = false); + + // generic user context which can be set/read, + // the server does nothing with this apart from keep it. + const void * + getUserContext() const + { + return UserContext; + } + + protected: + class CivetConnection + { + public: + char *postData; + unsigned long postDataLen; + + CivetConnection(); + ~CivetConnection(); + }; + + struct mg_context *context; + std::map<struct mg_connection *, class CivetConnection> connections; + + // generic user context which can be set/read, + // the server does nothing with this apart from keep it. + const void *UserContext; + + private: + /** + * requestHandler(struct mg_connection *, void *cbdata) + * + * Handles the incomming request. + * + * @param conn - the connection information + * @param cbdata - pointer to the CivetHandler instance. + * @returns 0 if implemented, false otherwise + */ + static int requestHandler(struct mg_connection *conn, void *cbdata); + + static int webSocketConnectionHandler(const struct mg_connection *conn, + void *cbdata); + static void webSocketReadyHandler(struct mg_connection *conn, void *cbdata); + static int webSocketDataHandler(struct mg_connection *conn, + int bits, + char *data, + size_t data_len, + void *cbdata); + static void webSocketCloseHandler(const struct mg_connection *conn, + void *cbdata); + /** + * authHandler(struct mg_connection *, void *cbdata) + * + * Handles the authorization requests. + * + * @param conn - the connection information + * @param cbdata - pointer to the CivetAuthHandler instance. + * @returns 1 if authorized, 0 otherwise + */ + static int authHandler(struct mg_connection *conn, void *cbdata); + + /** + * closeHandler(struct mg_connection *) + * + * Handles closing a request (internal handler) + * + * @param conn - the connection information + */ + static void closeHandler(const struct mg_connection *conn); + + /** + * Stores the user provided close handler + */ + void (*userCloseHandler)(const struct mg_connection *conn); +}; + +#endif /* __cplusplus */ +#endif /* _CIVETWEB_SERVER_H_ */