From b6707c3bb53c931e9ec3c5c6630149b7121bbcf5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 4 Nov 2015 18:55:36 +0100 Subject: [PATCH] Removed mongoose due to restricted license and webserver wip till code is restructured (nw) --- 3rdparty/mongoose/LICENSE | 16 - 3rdparty/mongoose/README.md | 78 - 3rdparty/mongoose/docs/API.md | 249 - 3rdparty/mongoose/docs/AndroidBuild.md | 27 - 3rdparty/mongoose/docs/BasicWebsite.md | 34 - 3rdparty/mongoose/docs/Embed.md | 173 - 3rdparty/mongoose/docs/FAQ.md | 45 - 3rdparty/mongoose/docs/FileSharing.md | 18 - 3rdparty/mongoose/docs/Internals.md | 44 - 3rdparty/mongoose/docs/Options.md | 154 - 3rdparty/mongoose/docs/PhpWebsite.md | 49 - 3rdparty/mongoose/docs/ReleaseNotes.md | 218 - 3rdparty/mongoose/docs/SSL.md | 70 - 3rdparty/mongoose/docs/Usage.md | 86 - 3rdparty/mongoose/examples/.gitignore | 1 - 3rdparty/mongoose/examples/Makefile | 20 - .../mongoose/examples/array_vars/Makefile | 21 - .../mongoose/examples/array_vars/array_vars.c | 45 - .../mongoose/examples/big_upload/Makefile | 12 - .../mongoose/examples/big_upload/big_upload.c | 84 - .../examples/cookie_authentication/Makefile | 12 - .../cookie_authentication/cookie_auth.c | 97 - .../examples/cookie_authentication/index.html | 33 - .../examples/cookie_authentication/login.html | 44 - 3rdparty/mongoose/examples/csharp/example.cs | 43 - 3rdparty/mongoose/examples/csharp/mongoose.cs | 68 - .../examples/digest_authentication/Makefile | 12 - .../digest_authentication/digest_auth.c | 36 - .../mongoose/examples/file_upload/Makefile | 20 - .../examples/file_upload/file_upload.c | 61 - .../mongoose/examples/form_submit/Makefile | 12 - .../examples/form_submit/form_submit.c | 62 - .../mongoose/examples/hello_world/Makefile | 21 - .../examples/hello_world/hello_world.c | 38 - .../mongoose/examples/http_client/Makefile | 12 - .../examples/http_client/http_client.c | 82 - .../mongoose/examples/mjpg_streamer/Makefile | 12 - .../examples/mjpg_streamer/mjpg_streamer.c | 105 - .../examples/multi_threaded_server/Makefile | 12 - .../multi_threaded_server.c | 40 - .../mongoose/examples/proxy_server/Makefile | 13 - .../examples/proxy_server/proxy_server.c | 202 - .../proxy_web_root/app1/index.html | 23 - .../proxy_web_root/app2/index.html | 37 - .../proxy_server/proxy_web_root/index.html | 29 - .../examples/proxy_server/ssl_cert.pem | 50 - .../mongoose/examples/restful_api/Makefile | 12 - .../mongoose/examples/restful_api/index.html | 66 - .../examples/restful_api/restful_api.c | 51 - 3rdparty/mongoose/examples/send_file/Makefile | 21 - .../mongoose/examples/send_file/send_file.c | 27 - .../mongoose/examples/web_server/Makefile | 30 - .../examples/web_server/certs/cert.pem | 46 - .../mongoose/examples/web_server/web_server.c | 490 -- .../mongoose/examples/websocket_chat/Makefile | 12 - .../examples/websocket_chat/index.html | 98 - .../examples/websocket_chat/websocket_chat.c | 83 - .../examples/websocket_echo_server/Makefile | 12 - .../examples/websocket_echo_server/index.html | 46 - .../websocket_echo_server.c | 61 - .../examples/websocket_ssl_proxy/Makefile | 27 - .../websocket_ssl_proxy/certs/ws1_ca.pem | 49 - .../websocket_ssl_proxy/certs/ws1_client.pem | 45 - .../websocket_ssl_proxy/certs/ws1_server.pem | 45 - .../websocket_ssl_proxy/certs/ws2_ca.pem | 49 - .../websocket_ssl_proxy/certs/ws2_client.pem | 45 - .../websocket_ssl_proxy/certs/ws2_server.pem | 45 - .../websocket_ssl_proxy/net_skeleton.h | 253 - .../websocket_ssl_proxy/ssl_wrapper.c | 123 - .../websocket_ssl_proxy/ssl_wrapper.h | 34 - .../examples/websocket_ssl_proxy/ws_ssl.c | 182 - .../examples/websocket_ssl_proxy/ws_ssl.html | 50 - 3rdparty/mongoose/jni/Android.mk | 8 - 3rdparty/mongoose/mongoose.c | 5520 ----------------- 3rdparty/mongoose/mongoose.h | 158 - .../mongoose/scripts/embed_binary_files.pl | 53 - 3rdparty/mongoose/test/Makefile | 21 - 3rdparty/mongoose/test/unit_test.c | 533 -- scripts/src/3rdparty.lua | 40 - scripts/src/emu.lua | 2 - scripts/src/main.lua | 1 - src/emu/debug/debugcpu.c | 2 - src/emu/emuopts.c | 4 - src/emu/emuopts.h | 10 - src/emu/luaengine.c | 5 +- src/emu/machine.c | 2 - src/emu/mame.c | 6 - src/emu/mame.h | 4 - src/emu/ui/ui.c | 1 - src/emu/webengine.c | 545 -- src/emu/webengine.h | 48 - web/css/images/ajax-loader.gif | Bin 7825 -> 0 bytes web/css/images/icons-18-black.png | Bin 1968 -> 0 bytes web/css/images/icons-18-white.png | Bin 1988 -> 0 bytes web/css/images/icons-36-black.png | Bin 3859 -> 0 bytes web/css/images/icons-36-white.png | Bin 3861 -> 0 bytes web/css/jquery.mobile.css | 12 - web/favicon.ico | Bin 2238 -> 0 bytes web/images/logo-mame-small.png | Bin 25705 -> 0 bytes web/index.html | 917 --- web/js/jquery.js | 6 - web/js/jquery.mobile.js | 9 - 102 files changed, 2 insertions(+), 12527 deletions(-) delete mode 100644 3rdparty/mongoose/LICENSE delete mode 100644 3rdparty/mongoose/README.md delete mode 100644 3rdparty/mongoose/docs/API.md delete mode 100644 3rdparty/mongoose/docs/AndroidBuild.md delete mode 100644 3rdparty/mongoose/docs/BasicWebsite.md delete mode 100644 3rdparty/mongoose/docs/Embed.md delete mode 100644 3rdparty/mongoose/docs/FAQ.md delete mode 100644 3rdparty/mongoose/docs/FileSharing.md delete mode 100644 3rdparty/mongoose/docs/Internals.md delete mode 100644 3rdparty/mongoose/docs/Options.md delete mode 100644 3rdparty/mongoose/docs/PhpWebsite.md delete mode 100644 3rdparty/mongoose/docs/ReleaseNotes.md delete mode 100644 3rdparty/mongoose/docs/SSL.md delete mode 100644 3rdparty/mongoose/docs/Usage.md delete mode 100644 3rdparty/mongoose/examples/.gitignore delete mode 100644 3rdparty/mongoose/examples/Makefile delete mode 100644 3rdparty/mongoose/examples/array_vars/Makefile delete mode 100644 3rdparty/mongoose/examples/array_vars/array_vars.c delete mode 100644 3rdparty/mongoose/examples/big_upload/Makefile delete mode 100644 3rdparty/mongoose/examples/big_upload/big_upload.c delete mode 100644 3rdparty/mongoose/examples/cookie_authentication/Makefile delete mode 100644 3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c delete mode 100644 3rdparty/mongoose/examples/cookie_authentication/index.html delete mode 100644 3rdparty/mongoose/examples/cookie_authentication/login.html delete mode 100644 3rdparty/mongoose/examples/csharp/example.cs delete mode 100644 3rdparty/mongoose/examples/csharp/mongoose.cs delete mode 100644 3rdparty/mongoose/examples/digest_authentication/Makefile delete mode 100644 3rdparty/mongoose/examples/digest_authentication/digest_auth.c delete mode 100644 3rdparty/mongoose/examples/file_upload/Makefile delete mode 100644 3rdparty/mongoose/examples/file_upload/file_upload.c delete mode 100644 3rdparty/mongoose/examples/form_submit/Makefile delete mode 100644 3rdparty/mongoose/examples/form_submit/form_submit.c delete mode 100644 3rdparty/mongoose/examples/hello_world/Makefile delete mode 100644 3rdparty/mongoose/examples/hello_world/hello_world.c delete mode 100644 3rdparty/mongoose/examples/http_client/Makefile delete mode 100644 3rdparty/mongoose/examples/http_client/http_client.c delete mode 100644 3rdparty/mongoose/examples/mjpg_streamer/Makefile delete mode 100644 3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c delete mode 100644 3rdparty/mongoose/examples/multi_threaded_server/Makefile delete mode 100644 3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c delete mode 100644 3rdparty/mongoose/examples/proxy_server/Makefile delete mode 100644 3rdparty/mongoose/examples/proxy_server/proxy_server.c delete mode 100644 3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html delete mode 100644 3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html delete mode 100644 3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html delete mode 100644 3rdparty/mongoose/examples/proxy_server/ssl_cert.pem delete mode 100644 3rdparty/mongoose/examples/restful_api/Makefile delete mode 100644 3rdparty/mongoose/examples/restful_api/index.html delete mode 100644 3rdparty/mongoose/examples/restful_api/restful_api.c delete mode 100644 3rdparty/mongoose/examples/send_file/Makefile delete mode 100644 3rdparty/mongoose/examples/send_file/send_file.c delete mode 100644 3rdparty/mongoose/examples/web_server/Makefile delete mode 100644 3rdparty/mongoose/examples/web_server/certs/cert.pem delete mode 100644 3rdparty/mongoose/examples/web_server/web_server.c delete mode 100644 3rdparty/mongoose/examples/websocket_chat/Makefile delete mode 100644 3rdparty/mongoose/examples/websocket_chat/index.html delete mode 100644 3rdparty/mongoose/examples/websocket_chat/websocket_chat.c delete mode 100644 3rdparty/mongoose/examples/websocket_echo_server/Makefile delete mode 100644 3rdparty/mongoose/examples/websocket_echo_server/index.html delete mode 100644 3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c delete mode 100644 3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html delete mode 100644 3rdparty/mongoose/jni/Android.mk delete mode 100644 3rdparty/mongoose/mongoose.c delete mode 100644 3rdparty/mongoose/mongoose.h delete mode 100644 3rdparty/mongoose/scripts/embed_binary_files.pl delete mode 100644 3rdparty/mongoose/test/Makefile delete mode 100644 3rdparty/mongoose/test/unit_test.c delete mode 100644 src/emu/webengine.c delete mode 100644 src/emu/webengine.h delete mode 100644 web/css/images/ajax-loader.gif delete mode 100644 web/css/images/icons-18-black.png delete mode 100644 web/css/images/icons-18-white.png delete mode 100644 web/css/images/icons-36-black.png delete mode 100644 web/css/images/icons-36-white.png delete mode 100644 web/css/jquery.mobile.css delete mode 100644 web/favicon.ico delete mode 100644 web/images/logo-mame-small.png delete mode 100644 web/index.html delete mode 100644 web/js/jquery.js delete mode 100644 web/js/jquery.mobile.js diff --git a/3rdparty/mongoose/LICENSE b/3rdparty/mongoose/LICENSE deleted file mode 100644 index feb3592d180..00000000000 --- a/3rdparty/mongoose/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -Copyright (c) 2004-2013 Sergey Lyubka -Copyright (c) 2013-2015 Cesanta Software Limited -All rights reserved - -This code is dual-licensed: you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. For the terms of this -license, see . - -You are free to use this code under the terms of the GNU General -Public License, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -Alternatively, you can license this code under a commercial -license, as set out in . diff --git a/3rdparty/mongoose/README.md b/3rdparty/mongoose/README.md deleted file mode 100644 index 4b4fc3219ba..00000000000 --- a/3rdparty/mongoose/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# Mongoose Web Server - -[![Join the chat at https://gitter.im/cesanta/mongoose](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cesanta/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -Mongoose is the most easy to use web server on the planet. A web server of choice for Web developers (PHP, Ruby, Python, etc) and Web designers. - -Mongoose is built on top of Libmongoose embedded library, which can turn -anything into a web server in 5 minutes worth of effort and few lines of code. -Libmongoose is used to serve Web GUI on embedded devices, implement RESTful -services, RPC frameworks (e.g. JSON-RPC), handle telemetry data exchange, and -perform many other tasks in various different industries including aerospace, -manufacturing, finance, research, automotive, gaming, IT. - - - * [Mailing list](http://groups.google.com/group/mongoose-users) - * [Downloads](http://cesanta.com/products.shtml) - * [Documentation](http://cesanta.com/docs.shtml) - -Check out Fossa - our [embedded multi-protocol library](https://github.com/cesanta/fossa) with TCP,UDP,HTTP,Websocket,MQTT,DNS support, designed for Internet Of Things! - -# Features - -- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX -and many other platforms -- CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download, - URL rewrite, file blacklist -- Custom error pages, Virtual hosts, IP-based ACL, Windows service, - HTTP/HTTPS client -- Simple and clean - [embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h). - The source is in single - [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file - to make embedding easy -- Extremely lightweight, has a core of under 40kB and tiny runtime footprint -- Asynchronous, non-blocking core supporting single- or multi-threaded usage -- On the market since 2004 with over 1 million cumulative downloads -- Stable, mature and tested, has several man-years invested - in continuous improvement and refinement - -# Screenshots - -Download, double-click to start, run browser -- that's all! - -![shot1](http://cesanta.com/images/tut_sharing/tut1.png) -![shot2](http://cesanta.com/images/tut_sharing/tut2.png) - -![shot3](http://cesanta.com/images/tut_sharing/tut3.png) -![shot4](http://cesanta.com/images/tut_sharing/tut4.png) - -# Contributions - -People who have agreed to the -[Cesanta CLA](http://cesanta.com/contributors_la.html) -can make contributions. Note that the CLA isn't a copyright -_assigment_ but rather a copyright _license_. -You retain the copyright on your contributions. - -# Licensing - -Mongoose is released under commercial and -[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open -source licenses. The GPLv2 open source License does not generally permit -incorporating this software into non-open source programs. -For those customers who do not wish to comply with the GPLv2 open -source license requirements, -[Cesanta](http://cesanta.com) offers a full, -royalty-free commercial license and professional support -without any of the GPL restrictions. - -# Other products by Cesanta - -- [Fossa](http://github.com/cesanta/fossa) - Multi-protocol networking library -- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to - secure network communications -- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator -- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression - library -- [V7](https://github.com/cesanta/v7) - Embedded JavaScript engine diff --git a/3rdparty/mongoose/docs/API.md b/3rdparty/mongoose/docs/API.md deleted file mode 100644 index faf93daaaae..00000000000 --- a/3rdparty/mongoose/docs/API.md +++ /dev/null @@ -1,249 +0,0 @@ -# Mongoose API Reference - - struct mg_server *mg_create_server(void *server_param, mg_handler_t handler); - -Creates web server instance. Returns opaque instance pointer, or NULL if -there is not enough memory. `server_param`: Could be any pointer, or NULL. -This pointer will be passed -to the callback functions as `struct mg_connection::server_param` field. -A common use case is to pass `this` pointer of the C++ wrapper class -as `user_param`, to let the callback get the pointer to the C++ object. - -Note that this function doesn't make the -server instance to serve. Serving is done by `mg_poll_server()` function. -Mongoose has single-threaded, event-driven, asynchronous, non-blocking core. -When server instance is created, it contains an information about -the configuration and the state of each connection. -Server instance is capable on listening on only one port. After creation, -`struct mg_server` has a list -of active connections and configuration parameters. - -Side-effect: on UNIX, `mg_create_server()` ignores SIGPIPE signals. If custom -processing is required SIGPIPE, signal handler must be set up after -calling `mg_create_server()`. - -Important: Mongoose does not install `SIGCHLD` handler. If CGI is used, -`SIGCHLD` handler must be set up to reap CGI zombie processes. - - - void mg_destroy_server(struct mg_server **server); - -Deallocates web server instance, closes all pending connections, and makes -server pointer a NULL pointer. - - const char mg_set_option(struct mg_server *server, const char *name, - const char *value); - -Sets a particular server option. Note that at least one option, -`listening_port`, must be specified. To serve static files, `document_root` -must be specified too. If `document_root` option is left unset, Mongoose -will not access filesystem at all. `mg_set_option()` returns NULL if option was -set successfully, otherwise it returns human-readable error string. It is -allowed to call `mg_set_option()` by the same thread that does -`mg_poll_server()` (Mongoose thread) and change server configuration while it -is serving, in between `mg_poll_server()` calls. - - int mg_poll_server(struct mg_server *server, int milliseconds); - -Performs one iteration of IO loop by iterating over all -active connections, performing `select()` syscall on all sockets with a timeout -of `milliseconds`. When `select()` returns, Mongoose -does an IO for each socket that has data to be sent or received. Application -code must call `mg_poll_server()` in a loop. It is an error to have more then -one thread calling `mg_poll_server()`, `mg_set_option()` or any other function -that take `struct mg_server *` parameter. Mongoose does not -mutex-protect `struct mg_server *`, therefore only single thread -(Mongoose thread) should make Mongoose calls. - -`mg_poll_server()` calls user-specified event handler when certain events -occur. Sequence of events for the accepted connection is this: - - * `MG_AUTH` - Mongoose asks whether this connection is authorized. If event - handler returns `MG_FALSE`, then Mongoose does not serve the request but - sends authorization request to the client. If `MG_TRUE` is returned, - then Mongoose continues on with the request. - * `MG_REQUEST` - Mongoose asks event handler to serve the request. If - event handler serves the request by sending a reply, - it should return `MG_TRUE`. Otherwise, - it should return `MG_FALSE` which tells Mongoose that request is not - served and Mongoose should serve it. For example, event handler might - choose to serve only RESTful API requests with URIs that start with - certain prefix, and let Mongoose serve all static files. - If event handler decides to serve the request, but doesn't have - all the data at the moment, it should return `MG_MORE`. That tells - Mongoose to keep the connection open after callback returns. - - `mg_connection::connection_param` pointer is a placeholder to keep - user-specific data. For example, handler could decide to open a DB - connection and store DB connection handle in `connection_param`. - * `MG_POLL` is sent to every connection on every iteration of - `mg_poll_server()`. Event handler should return `MG_FALSE` to ignore - this event. If event handler returns `MG_TRUE`, then Mongoose assumes - that event handler has finished sending data, and Mongoose will - close the connection. - * `MG_HTTP_ERROR` sent when Mongoose is about to send HTTP error back - to the client. Event handler can choose to send a reply itself, in which - case event handler must return `MG_TRUE`. Otherwise, event handler must - return `MG_FALSE`. - * `MG_CLOSE` is sent when the connection is closed. This event is used - to cleanup per-connection state stored in `connection_param` - if it was allocated. Event handler return value is ignored. - -Sequence of events for the client connection is this: - - * `MG_CONNECT` sent when Mongoose has connected to the remote host. - This event is sent to the connection initiated by `mg_connect()` call. - Connection status is held in `mg_connection::status_code`: if zero, - then connection was successful, otherwise connection was not established. - User should send a request upon successful connection. - Event handler should return `MG_TRUE` if connection was successful and - HTTP request has been sent. Otherwise, it should send `MG_FALSE`. - * `MG_REPLY` is sent when response has been received from the remote host. - If event handler sends another request, then it should return `MG_TRUE`. - Otherwise it should return `MG_FALSE` and Mongoose will close the connection. - * `MG_CLOSE` same as for the accepted connection. - - -When mongoose buffers in HTTP request and successfully parses it, it sends -`MG_REQUEST` event for GET requests immediately. For POST requests, -Mongoose delays the call until the whole POST request is buffered in memory. -POST data is available to the callback as `struct mg_connection::content`, -and POST data length is in `struct mg_connection::content_len`. - -Note that websocket connections are treated the same way. Mongoose buffers -websocket frame in memory, and calls event handler when frame is fully -buffered. Frame data is available `struct mg_connection::content`, and -data length is in `struct mg_connection::content_len`, i.e. very similar to -the POST request. `struct mg_connection::is_websocket` flag indicates -whether the request is websocket or not. Also, for websocket requests, -there is `struct mg_connection::wsbits` field which contains first byte -of the websocket frame which URI handler can examine. Note that to -reply to the websocket client, `mg_websocket_write()` should be used. -To reply to the plain HTTP client, `mg_write_data()` should be used. - -Return value: number of active connections. - - - const char **mg_get_valid_option_names(void); - -Returns a NULL-terminated array of option names and their default values. -There are two entries per option in an array: an option name followed by a -default value. A default value could be NULL. A NULL name indicates an end -of the array. - - const char *mg_get_option(const struct mg_server *server, const char *name); - -Returns the value of particular configuration parameter. If -given parameter name is not valid, NULL is returned. For valid names, return -value is guaranteed to be non-NULL. If parameter is not set, zero-length string -is returned. - - void mg_wakeup_server_ex(struct mg_server *, mg_handler_t func, - const char *fmt, ...); - -Sends string message to a server. Function `func` is called for every active -connection. String message is passed in `struct mg_connection::callback_param`. -This function is designed to push data to the connected clients, and -can be called from any thread. There is a limitation on the length of -the message, currently at 8 kilobytes. - - void mg_send_status(struct mg_connection *, int status_code); - void mg_send_header(struct mg_connection *, const char *name, - const char *value); - void mg_send_data(struct mg_connection *, const void *data, int data_len); - void mg_printf_data(struct mg_connection *, const char *format, ...); - -These functions are used to construct a response to the client. HTTP response -consists of three parts: a status line, zero or more HTTP headers, -a response body. Mongoose provides functions for all three parts: - * `mg_send_status()` is used to create status line. This function can be - called zero or once. If `mg_send_status()` is not called, then Mongoose - will send status 200 (success) implicitly. - * `mg_send_header()` adds HTTP header to the response. This function could - be called zero or more times. - * `mg_send_data()` and `mg_printf_data()` are used to send data to the - client. Note that Mongoose adds `Transfer-Encoding: chunked` header - implicitly, and sends data in chunks. Therefore, it is not necessary to - set `Content-Length` header. Note that `mg_send_data()` and - `mg_printf_data()` do not send data immediately. Instead, they spool - data in memory, and Mongoose sends that data later after URI handler - returns. If data to be sent is huge, an URI handler might - send data in pieces by saving state in - `struct mg_connection::connection_param` variable and returning `0`. Then - Mongoose will call a handler repeatedly after each socket write. - - - - void mg_send_file(struct mg_connection *, const char *path); - -Tells Mongoose to serve given file. Mongoose handles file according to -it's extensions, i.e. Mongoose will invoke CGI script if `path` has CGI -extension, it'll render SSI file if `path` has SSI extension, etc. If `path` -points to a directory, Mongoose will show directory listing. If this function -is used, no calls to `mg_send*` or `mg_printf*` functions must be made, and -event handler must return `MG_MORE`. - - size_t mg_websocket_write(struct mg_connection* conn, int opcode, - const char *data, size_t data_len); - size_t mg_websocket_printf(struct mg_connection* conn, int opcode, - const char *fmt, ...); - - -Similar to `mg_write()` and `mg_printf()`, but wraps the data into a -websocket frame with a given websocket `opcode`. - - const char *mg_get_header(const struct mg_connection *, const char *name); - -Get the value of particular HTTP header. This is a helper function. -It traverses http_headers array, and if the header is present in the array, -returns its value. If it is not present, NULL is returned. - - - int mg_get_var(const struct mg_connection *conn, const char *var_name, - char *buf, size_t buf_len); - -Gets HTTP form variable. Both POST buffer and query string are inspected. -Form variable is url-decoded and written to the buffer. On success, this -function returns the length of decoded variable. On error, -1 is returned if -variable not found, and -2 is returned if destination buffer is too small -to hold the variable. Destination buffer is guaranteed to be -'\0' - terminated if it is not NULL or zero length. - - int mg_parse_header(const char *hdr, const char *var_name, char *buf, - size_t buf_size); - -This function parses HTTP header and fetches given variable's value in a buffer. -A header should be like `x=123, y=345, z="other value"`. This function is -designed to parse Cookie headers, Authorization headers, and similar. Returns -the length of the fetched value, or 0 if variable not found. - - int mg_modify_passwords_file(const char *passwords_file_name, - const char *domain, - const char *user, - const char *password); - -Add, edit or delete the entry in the passwords file. -This function allows an application to manipulate .htpasswd files on the -fly by adding, deleting and changing user records. This is one of the -several ways of implementing authentication on the server side. -If password is not NULL, entry is added (or modified if already exists). -If password is NULL, entry is deleted. -Return: 1 on success, 0 on error. - - - int mg_parse_multipart(const char *buf, int buf_len, - char *var_name, int var_name_len, - char *file_name, int file_name_len, - const char **data, int *data_len); - -Parses a buffer that contains multipart form data. Stores chunk name -in a `var_name` buffer. If chunk is an uploaded file, then `file_name` -will have a file name. `data` and `data_len` will point to the chunk data. -Returns number of bytes to skip to the next chunk. - - struct mg_connection *mg_connect(struct mg_server *server, - const char *host, int port, int use_ssl); - -Create connection to the remote host. Returns `NULL` on error, non-null -if the connection has been scheduled for connection. Upon a connection, -Mongoose will send `MG_CONNECT` event to the event handler. diff --git a/3rdparty/mongoose/docs/AndroidBuild.md b/3rdparty/mongoose/docs/AndroidBuild.md deleted file mode 100644 index afd21522f55..00000000000 --- a/3rdparty/mongoose/docs/AndroidBuild.md +++ /dev/null @@ -1,27 +0,0 @@ -# Mongoose Build on Android - -This is a small guide to help you run mongoose on Android. Currently it is -tested on the HTC Wildfire. If you have managed to run it on other devices -as well, please comment or drop an email in the mailing list. -Note : You dont need root access to run mongoose on Android. - -- Clone Mongoose Git repo -- Download the Android NDK from [http://developer.android.com/tools/sdk/ndk/index.html](http://developer.android.com/tools/sdk/ndk/index.html) -- Run `/path-to-ndk/ndk-build -C /path/to/mongoose` - That should generate mongoose/lib/armeabi/mongoose -- Using the adb tool (you need to have Android SDK installed for that), - push the generated mongoose binary to `/data/local` folder on device. -- From adb shell, navigate to `/data/local` and execute `./mongoose`. -- To test if the server is running fine, visit your web-browser and - navigate to `http://127.0.0.1:8080` You should see the `Index of /` page. - -![screenshot](http://cesanta.com/images/android_build.png) - - -Notes: - -- `jni` stands for Java Native Interface. Read up on Android NDK if you want - to know how to interact with the native C functions of mongoose in Android - Java applications. -- TODO: A Java application that interacts with the native binary or a - shared library. diff --git a/3rdparty/mongoose/docs/BasicWebsite.md b/3rdparty/mongoose/docs/BasicWebsite.md deleted file mode 100644 index c5c93c7760d..00000000000 --- a/3rdparty/mongoose/docs/BasicWebsite.md +++ /dev/null @@ -1,34 +0,0 @@ -How To Create Basic Website With Mongoose -=========================================== - -## 1. Create a directory which will contain your website files. For example, on drive `C:\`, create a directory called `my_website`: - -![screenshot](http://cesanta.com/images/tut_basic/tut1.png) - -## 2. Inside `my_website` directory, create a new file called "index". This will be the default web page shown when the website is visited. - -![screenshot](http://cesanta.com/images/tut_basic/tut2.png) - -## 3. Open index file with your favorite editor (for example, Notepad) and enter some HTML code: - -![screenshot](http://cesanta.com/images/tut_basic/tut3.png) - -## 4. Save this file as `index.html`: - -![screenshot](http://cesanta.com/images/tut_basic/tut4.png) - - -## 5. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside `my_website` directory: - -![screenshot](http://cesanta.com/images/tut_basic/tut5.png) - -## 6. Double-click mongoose executable. An icon will appear on a system tray in the bottom right corner of the desktop: - -![screenshot](http://cesanta.com/images/tut_basic/tut6.png) - -## 7. Click on the mongoose icon and choose "Go to my address" menu: -![screenshot](http://cesanta.com/images/tut_basic/tut7.png) - -## 8. A browser will popup displaying `index.html` file. Now, you can expand your website by adding more content. - -![screenshot](http://cesanta.com/images/tut_basic/tut8.png) diff --git a/3rdparty/mongoose/docs/Embed.md b/3rdparty/mongoose/docs/Embed.md deleted file mode 100644 index 8e6dfbf5669..00000000000 --- a/3rdparty/mongoose/docs/Embed.md +++ /dev/null @@ -1,173 +0,0 @@ -# Mongoose Embedding Guide - -Embedding Mongoose is done in two steps: - - 1. Copy - [mongoose.c](https://raw.github.com/cesanta/mongoose/master/mongoose.c) and - [mongoose.h](https://raw.github.com/cesanta/mongoose/master/mongoose.h) - to your application's source tree and include them in the build. - 2. Somewhere in the application code, call `mg_create_server()` to create - a server, configure it with `mg_set_option()` and loop with - `mg_poll_server()` until done. Call `mg_destroy_server()` to cleanup. - -Here's a minimal application `app.c` that embeds mongoose: - - #include "mongoose.h" - - int main(void) { - struct mg_server *server = mg_create_server(NULL, NULL); - mg_set_option(server, "document_root", "."); // Serve current directory - mg_set_option(server, "listening_port", "8080"); // Open port 8080 - - for (;;) { - mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop - } - mg_destroy_server(&server); - - return 0; - } - -To compile it, put `mongoose.c`, `mongoose.h` and `app.c` into one -folder, start terminal on UNIX or Visual Studio command line prompt on Windows, -and run the following command: - - cc app.c mongoose.c -pthread -o app # on Unix - cl.exe app.c mongoose.c /TC /MD # on Windows - -When run, this simple application opens port 8080 and serves static files, -CGI files and lists directory content in the current working directory. - -It is possible to generate HTML page content. Mongoose can call user-defined -function when certain events occur. -That function is called _an event handler_, and it is the second parameter -to `mg_create_server()` function. Here is the example event handler function: - - int event_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - default: return MG_FALSE; - } - } - -Event handler is called by Mongoose with `struct mg_connection *` -pointer and an event number. `struct mg_connection *conn` -has all information about the request: HTTP headers, POST or websocket -data buffer, etcetera. `enum mg_event ev` tells which exactly event is sent. -For each event, an event handler returns a value which tells Mongoose how -to behave. - -The sequence of events for every connection is this: - - * `MG_AUTH` - Mongoose asks whether this connection is authorized. If event - handler returns `MG_FALSE`, then Mongoose does not serve the request but - sends authorization request to the client. If `MG_TRUE` is returned, - then Mongoose continues on with the request. - * `MG_REQUEST` - Mongoose asks event handler to serve the request. If - event handler serves the request by sending a reply, - it should return `MG_TRUE`. Otherwise, - it should return `MG_FALSE` which tells Mongoose that request is not - served and Mongoose should serve it. For example, event handler might - choose to serve only RESTful API requests with URIs that start with - certain prefix, and let Mongoose serve all static files. - If event handler decides to serve the request, but doesn't have - all the data at the moment, it should return `MG_MORE`. That tells - Mongoose to keep the connection open after callback returns. - - `mg_connection::connection_param` pointer is a placeholder to keep - user-specific data. For example, handler could decide to open a DB - connection and store DB connection handle in `connection_param`. - * `MG_POLL` is sent to every connection on every iteration of - `mg_poll_server()`. Event handler should return `MG_FALSE` to ignore - this event. If event handler returns `MG_TRUE`, then Mongoose assumes - that event handler has finished sending data, and Mongoose will - close the connection. - * `MG_HTTP_ERROR` sent when Mongoose is about to send HTTP error back - to the client. Event handler can choose to send a reply itself, in which - case event handler must return `MG_TRUE`. Otherwise, event handler must - return `MG_FALSE` - * `MG_CLOSE` is sent when the connection is closed. This event is used - to cleanup per-connection state stored in `connection_param` - if it was allocated. - -Let's extend our minimal application example and -create an URI that will be served by user's C code. The app will handle -`/hello` URI by showing a hello message. So, when app is run, -http://127.0.0.1:8080/hello will say hello, and here's the code: - - #include - #include "mongoose.h" - - static int event_handler(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_AUTH) { - return MG_TRUE; // Authorize all requests - } else if (ev == MG_REQUEST && !strcmp(conn->uri, "/hello")) { - mg_printf_data(conn, "%s", "Hello world"); - return MG_TRUE; // Mark as processed - } else { - return MG_FALSE; // Rest of the events are not processed - } - } - - int main(void) { - struct mg_server *server = mg_create_server(NULL, event_handler); - mg_set_option(server, "document_root", "."); - mg_set_option(server, "listening_port", "8080"); - - for (;;) { - mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop - } - mg_destroy_server(&server); - - return 0; - } - -## Example code - -Mongoose source code contains number of examples, located in the -[examples](https://github.com/cesanta/mongoose/blob/master/examples/) directory. -To build any example, go to the respective directory and run `make`. - -## Compilation flags - -Below is the list of compilation flags that enable or disable certain -features. By default, some features are enabled, and could be disabled -by setting appropriate `NO_*` flag. Features that are disabled by default -could be enabled by setting appropriate `USE_*` flag. Bare bones Mongoose -is quite small, about 30 kilobytes of compiled x86 code. Each feature adds -a couple of kilobytes to the executable size, and also has some runtime penalty. - -Note that some flags start with `NS_` prefix. This is because Mongoose uses -[Net Skeleton](http://github.com/cesanta/net_skeleton) as a low-level -networking engine. If user code has `#include `, then -all Net Skeleton functions will be available too. - - - -DMONGOOSE_NO_AUTH Disable MD5 authorization support - -DMONGOOSE_NO_CGI Disable CGI support - -DMONGOOSE_NO_DAV Disable WebDAV support - (PUT, DELETE, MKCOL, PROPFIND methods) - -DMONGOOSE_NO_DIRECTORY_LISTING Disable directory listing - -DMONGOOSE_NO_FILESYSTEM Disables all file IO, serving from memory only - -DMONGOOSE_NO_LOGGING Disable access/error logging - -DMONGOOSE_ENABLE_THREADS Enable mg_start_thread() function - -DMONGOOSE_NO_WEBSOCKET Disable WebSocket support - -DMONGOOSE_NO_USER No concept of a user on used platform. - (Platform does not provide getpwnam, setgid or setuid) - - -DMONGOOSE_USE_IDLE_TIMEOUT_SECONDS=X Idle connection timeout, default is 30 - -DMONGOOSE_USE_LUA Enable Lua scripting - -DMONGOOSE_USE_LUA_SQLITE3 Enable sqlite3 binding for Lua - -DMONGOOSE_USE_POST_SIZE_LIMIT=X POST requests larger than X will be - rejected, not set by default - -DMONGOOSE_USE_EXTRA_HTTP_HEADERS=X Append X to the HTTP headers - for static files, empty by default - - -DNS_ENABLE_DEBUG Enables debug messages on stdout, very noisy - -DNS_ENABLE_SSL Enable SSL - -DNS_ENABLE_IPV6 Enable IPv6 support - -DNS_ENABLE_HEXDUMP Enables hexdump of sent and received traffic - -DNS_STACK_SIZE=X Sets stack size to X for ns_start_thread() - -DNS_DISABLE_THREADS Disable threads support - -DNS_DISABLE_SOCKETPAIR For systems without loopback interface - -DMONGOOSE_SEND_NS_EVENTS Send Net Skeleton events to the event handler - in addition to the Mongoose events diff --git a/3rdparty/mongoose/docs/FAQ.md b/3rdparty/mongoose/docs/FAQ.md deleted file mode 100644 index 5648f5a1242..00000000000 --- a/3rdparty/mongoose/docs/FAQ.md +++ /dev/null @@ -1,45 +0,0 @@ -# Mongoose FAQ - -## My Antivirus Software reports Mongoose as a security threat - -Mongoose doesn't contain any malicious logic. Antivirus reports a -[false positive](http://en.wikipedia.org/wiki/Type_I_and_type_II_errors#False_positive_error). -This is when certain byte sequence in Mongoose accidentally matches -virus signature in the Antivirus database. - -## Download page doesn't work - -Please make sure Javascript is enabled in your browser, and that the -antivirus software is not blocking the download. - - -## MacOS message: "Mongoose.app is damaged and can’t be opened. You should move it to the Trash" - -This happens on newer MacOS systems. The reason for the message -is the fact Mongoose.app is not digitally signed. -Mongoose download procedure changes the app on the fly by injecting -user information in the binary, making any prior digital signature void. -Open "System Preferences" -> "Security" and set "Allow apps downloaded from" -to "Anywhere". Revert the settings once Mongoose is installed. - -## PHP doesn't work: getting empty page, or 'File not found' error - -The reason for that is wrong paths to the interpreter. Remember that with PHP, -correct interpreter is `php-cgi.exe` (`php-cgi` on UNIX). Solution: specify -full path to the PHP interpreter, e.g.: - - mongoose -cgi_interpreter /full/path/to/php-cgi - -## Mongoose fails to start - -If Mongoose exits immediately when run, this -usually indicates a syntax error in the configuration file -(named `mongoose.conf` by default) or the command-line arguments. -Syntax checking is omitted from Mongoose to keep its size low. However, -the Manual should be of help. Note: the syntax changes from time to time, -so updating the config file might be necessary after executable update. - -### Embedding with OpenSSL on Windows might fail because of calling convention - -To force Mongoose to use `__stdcall` convention, add `/Gz` compilation -flag to the Visual Studio project settings. diff --git a/3rdparty/mongoose/docs/FileSharing.md b/3rdparty/mongoose/docs/FileSharing.md deleted file mode 100644 index e21750a2e65..00000000000 --- a/3rdparty/mongoose/docs/FileSharing.md +++ /dev/null @@ -1,18 +0,0 @@ -How To Share Files With Mongoose -=========================================== - -## 1. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside the directory you want to share: - -![screenshot](http://cesanta.com/images/tut_sharing/tut1.png) - -## 2. Double-click mongoose executable. A browser will start automatically, an icon will appear on a system tray in the bottom right corner of the desktop: - -![screenshot](http://cesanta.com/images/tut_sharing/tut2.png) - -## 3. Click on the mongoose icon -![screenshot](http://cesanta.com/images/tut_sharing/tut3.png) - - -## 4. Click on "Go to my address" to launch a browser locally. Or, to access a folder from another machine, launch a browser and type in the URL: - -![screenshot](http://cesanta.com/images/tut_sharing/tut4.png) diff --git a/3rdparty/mongoose/docs/Internals.md b/3rdparty/mongoose/docs/Internals.md deleted file mode 100644 index 2ecde5c849a..00000000000 --- a/3rdparty/mongoose/docs/Internals.md +++ /dev/null @@ -1,44 +0,0 @@ -# Mongoose Internals - -Mongoose has single-threaded, event-driven, asynchronous, non-blocking core. -`mg_create_server()` creates a web server instance. An instance is a container -for the config options and list of active connections. To do the actual -serving, user must call `mg_poll_server()`, which iterates over all -active connections, performing `select()` syscall on all sockets with a -timeout of specified number of milliseconds. When `select()` returns, Mongoose -does an IO for each socket that has data to be sent or received. Application -code must call `mg_poll_server()` in a loop. - -Mongoose server instance is designed to be used by a single thread. -It is an error to have more then -one thread calling `mg_poll_server()`, `mg_set_option()` or any other function -that take `struct mg_server *` parameter. Mongoose does not -mutex-protect `struct mg_server *`, therefore the best practice is -to call server management functions from the same thread (an IO thread). -On a multi-core systems, many server instances can be created, sharing the -same listening socket and managed by separate threads (see [multi_threaded.c](https://github.com/cesanta/mongoose/blob/master/examples/multi_threaded.c)) -example. - -It is an error to pass and store `struct mg_connection *` pointers for -later use to send data. The reason is that they can be invalidated by the -next `mg_poll_server()` call. For such a task, -there is `mg_iterate_over_connections()` API -exists, which sends a callback function to the IO thread, then IO thread -calls specified function for all active connection. - -When mongoose buffers in HTTP request and successfully parses it, it calls -appropriate URI handler immediately for GET requests. For POST requests, -Mongoose delays the call until the whole POST request is buffered in memory. -POST data is available to the callback as `struct mg_connection::content`, -and POST data length is in `struct mg_connection::content_len`. - -Note that websocket connections are treated the same way. Mongoose buffers -websocket frame in memory, and calls URI handler when frame is fully -buffered. Frame data is available `struct mg_connection::content`, and -data length is in `struct mg_connection::content_len`, i.e. very similar to -the POST request. `struct mg_connection::is_websocket` flag indicates -whether the request is websocket or not. Also, for websocket requests, -there is `struct mg_connection::wsbits` field which contains first byte -of the websocket frame which URI handler can examine. Note that to -reply to the websocket client, `mg_websocket_write()` should be used. -To reply to the plain HTTP client, `mg_write()` should be used. diff --git a/3rdparty/mongoose/docs/Options.md b/3rdparty/mongoose/docs/Options.md deleted file mode 100644 index 116c61fb9e4..00000000000 --- a/3rdparty/mongoose/docs/Options.md +++ /dev/null @@ -1,154 +0,0 @@ -# Mongoose Configuration Options - -### access\_control\_list -An Access Control List (ACL) allows restrictions to be put on the list of IP -addresses which have access to the web server. In the case of the Mongoose -web server, the ACL is a comma separated list of IP subnets, where each -subnet is prepended by either a `-` or a `+` sign. A plus sign means allow, -where a minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`, -this means to deny only that single IP address. - -Subnet masks may vary from 0 to 32, inclusive. The default setting is to allow -all accesses. On each request the full list is traversed, and -the last match wins. Example: `$ mongoose -access_control_list -0.0.0.0/0,+192.168/16` to deny all acccesses except those from `192.168/16` subnet. Note that if the option is set, then all accesses are forbidden -by default. Thus in a previous example, `-0.0.0.0` part is not necessary. -For example, `$mongoose access_control_list +10.0.0.0/8` -means disallow all, allow subnet 10/8 only. - -To learn more about subnet masks, see the -[Wikipedia page on Subnetwork](http://en.wikipedia.org/wiki/Subnetwork) - -Default: not set, all accesses are allowed. - -### access\_log\_file -Path to a file for access logs. Either full path, or relative to the -mongoose executable. Default: not set, no query logging is done. - -### auth_domain -Authorization realm used in `.htpasswd` authorization. Default: `mydomain.com` - -### cgi_interpreter -Path to an executable to be used use as an interpreter for __all__ CGI scripts -regardless script extension. Default: not set, Mongoose looks at -[shebang line](http://en.wikipedia.org/wiki/Shebang_(Unix\). - -For example, if both PHP and perl CGIs are used, then -`#!/path/to/php-cgi.exe` and `#!/path/to/perl.exe` must be first lines of the -respective CGI scripts. Note that paths should be either full file paths, -or file paths relative to the directory where mongoose executable is located. - -If all CGIs use the same interpreter, for example they are all PHP, then -`cgi_interpreter` option can be set to the path to `php-cgi.exe` executable and -shebang line in the CGI scripts can be omitted. -**Note**: PHP scripts must use `php-cgi.exe`, not `php.exe`. - -### cgi_pattern -All files that match `cgi_pattern` are treated as CGI files. Default pattern -allows CGI files be anywhere. To restrict CGIs to a certain directory, -use `/path/to/cgi-bin/**.cgi` as a pattern. Note that **full file path** is -matched against the pattern, not the URI. - -When Mongoose starts CGI program, it creates new environment for it (in -contrast, usually child program inherits the environment from parent). Several -environment variables however are inherited from Mongoose's environment, -they are: `PATH`, `TMP`, `TEMP`, `TMPDIR`, `PERLLIB`, `MONGOOSE_CGI`. On UNIX -it is also `LD_LIBRARY_PATH`. On Windows it is also `COMSPEC`, `SYSTEMROOT`, -`SystemDrive`, `ProgramFiles`, `ProgramFiles(x86)`, `CommonProgramFiles(x86)`. - -Default: `**.cgi$|**.pl$|**.php$` - -### dav\_auth\_file -Authentication file for WebDAV mutation requests: `PUT`, `DELETE`, `MKCOL`. -The format of that file is the same as for the `.htpasswd` file -used for digest authentication. It can be created and managed by -`mongoose -A` command. Default: not set, WebDAV mutations are disallowed. - -### document_root -A directory to serve. Default: current working directory. - -### enable\_directory\_listing -Enable directory listing, either `yes` or `no`. Default: `yes`. - -### enable\_proxy -Enable proxy functionality, either `yes` or `no`. If set to `yes`, then -browsers can be configured to use Mongoose as a proxy. Default: `no`. - - -### extra\_mime\_types -Extra mime types to recognize, in form `extension1=type1,extension2=type2,...`. -Extension must include dot. Example: -`mongoose -extra_mime_types .cpp=plain/text,.java=plain/text`. Default: not set. - - -### global\_auth\_file -Path to a global passwords file, either full path or relative to the mongoose -executable. If set, per-directory `.htpasswd` files are ignored, -and all requests are authorised against that file. Use `mongoose -A` to -manage passwords, or third party utilities like -[htpasswd-generator](http://www.askapache.com/online-tools/htpasswd-generator). -Default: not set, per-directory `.htpasswd` files are respected. - -### hide\_files\_patterns -A pattern for the files to hide. Files that match the pattern will not -show up in directory listing and return `404 Not Found` if requested. Pattern -must be for a file name only, not including directory name, e.g. -`mongoose -hide_files_patterns secret.txt|even_more_secret.txt`. Default: -not set. - -### index_files -Comma-separated list of files to be treated as directory index -files. Default: `index.html,index.htm,index.cgi,index.shtml,index.php` - -### listening_port -Port to listen on. Port could be prepended by the specific IP address to bind -to, e.g. `mongoose -listening_port 127.0.0.1:8080`. Otherwise Mongoose -will bind to all addresses. To enable SSL, build Mongoose with -`-DNS_ENABLE_SSL` compilation option, and specify `listening_port` as -`ssl://PORT:SSL_CERTIFICATE.PEM`. Example SSL listener: -`mongoose -listening_port ssl://8043:ssl_cert.pem`. Note that PEM file should -be in PEM format, and must have both certificate and private key in it, -concatenated together. More than one listening port can be specified, -separated by comma, -for example `mongoose -listening_port 8080,8000`. Default: 8080. - -### run\_as\_user -Switch to given user credentials after startup. UNIX-only. This option is -required when mongoose needs to bind on privileged port on UNIX, e.g. - - $ sudo mongoose -listening_port 80 -run_as_user nobody - -Default: not set. - -### url\_rewrites -Comma-separated list of URL rewrites in the form of -`uri_pattern=file_or_directory_path`. When Mongoose receives the request, -it constructs the file name to show by combining `document_root` and the URI. -However, if the rewrite option is used and `uri_pattern` matches the -requested URI, then `document_root` is ignored. Instead, -`file_or_directory_path` is used, which should be a full path name or -a path relative to the web server's current working directory. Note that -`uri_pattern`, as all mongoose patterns, is a prefix pattern. If `uri_pattern` -is a number, then it is treated as HTTP error code, and `file_or_directory_path` -should be an URI to redirect to. Mongoose will issue `302` temporary redirect -to the specified URI with following parameters: -`?code=HTTP_ERROR_CODE&orig_uri=ORIGINAL_URI&query_string=QUERY_STRING`. - -If `uri_pattern` starts with `@` symbol, then Mongoose compares -it with the `HOST` header of the request. If they are equal, Mongoose sets -document root to `file_or_directory_path`, implementing virtual hosts support. - -Examples: - - # Redirect all accesses to `.doc` files to a special script - mongoose -url_rewrites **.doc$=/path/to/cgi-bin/handle_doc.cgi - - # Implement user home directories support - mongoose -url_rewrites /~joe/=/home/joe/,/~bill=/home/bill/ - - # Redirect 404 errors to a specific error page - mongoose -url_rewrites 404=/cgi-bin/error.cgi - - # Virtual hosts example: serve foo.com domain from different directory - mongoose -url_rewrites @foo.com=/var/www/foo.com - -Default: not set. diff --git a/3rdparty/mongoose/docs/PhpWebsite.md b/3rdparty/mongoose/docs/PhpWebsite.md deleted file mode 100644 index 3b503c64c2a..00000000000 --- a/3rdparty/mongoose/docs/PhpWebsite.md +++ /dev/null @@ -1,49 +0,0 @@ -How To Create A PHP Website With Mongoose -=========================================== - -## 1. Create a directory which will contain your website files. For example, on drive `C:\`, create a directory called `my_website`: - -![screenshot](http://cesanta.com/images/tut_php/tut1.png) - -## 2. Inside `my_website` directory, create a new file called "index". This will be the default web page shown when the website is visited. - -![screenshot](http://cesanta.com/images/tut_php/tut2.png) - -## 3. Open index file with your favorite editor (for example, Notepad) and enter some HTML / PHP code: - -![screenshot](http://cesanta.com/images/tut_php/tut3.png) - -## 4. Save this file as `index.php`: - -![screenshot](http://cesanta.com/images/tut_php/tut4.png) - - -## 5. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside `my_website` directory: - -![screenshot](http://cesanta.com/images/tut_php/tut5.png) - -## 6. Double-click mongoose executable. An icon will appear on a system tray in the bottom right corner of the desktop: - -![screenshot](http://cesanta.com/images/tut_php/tut6.png) - -## 7. Download PHP 5.3 zip (do NOT download PHP 5.5 cause you might have missing DLLs problem) from http://windows.php.net/download and extract it to `C:\php5` directory: -![screenshot](http://cesanta.com/images/tut_php/tut7.png) - -## 8. Click on the mongoose icon and choose "Edit Settings" menu.: -![screenshot](http://cesanta.com/images/tut_php/tut8.png) - -## 9. A settings dialog will appear. Click on `cgi_interpreter` button: - -![screenshot](http://cesanta.com/images/tut_php/tut9.png) - -## 10. Choose `C:\php5\php-cgi.exe` and click "Save Settings": - -![screenshot](http://cesanta.com/images/tut_php/tut10.png) - -## 11. Click on the mongoose icon and choose "Go to my address" menu: -![screenshot](http://cesanta.com/images/tut_php/tut11.png) - - -## 12. A browser will popup displaying `index.php`. - -![screenshot](http://cesanta.com/images/tut_php/tut12.png) diff --git a/3rdparty/mongoose/docs/ReleaseNotes.md b/3rdparty/mongoose/docs/ReleaseNotes.md deleted file mode 100644 index 10fd4592609..00000000000 --- a/3rdparty/mongoose/docs/ReleaseNotes.md +++ /dev/null @@ -1,218 +0,0 @@ -# Mongoose Release Notes - -## Release 5.6, 2015-03-17 - -Changes in Libmongoose library: - -- Added `-dav_root` configuration option that gives an ability to mount - a different root directory (not document_root) -- Fixes for build under Win23 and MinGW -- Bugfix: Double dots removal -- Bugfix: final chunked response double-send -- Fixed compilation in 64-bit environments -- Added OS/2 compatibility -- Added `getaddrinfo()` call and `NS_ENABLE_GETADDRINFO` -- Various SSL-related fixes -- Added integer overflow protection in `iobuf_append()` and `deliver_websocket_frame()` -- Fixed NetBSD build -- Enabled `NS_ENABLE_IPV6` build for Visual Studio 2008+ -- Enhanced comma detection in `parse_header()` -- Fixed unchanged memory accesses on ARM -- Added ability to use custom memory allocator through NS_MALLOC, NS_FREE, NS_REALLOC - -Changes in Mongoose binary: - -- Added `-start_browser` option to disable automatic browser launch -- Added experimental SSL support. To listen on HTTPS port, use `ssl://PORT:SSL_CERT` format. For example, to listen on HTTP port 8080 and HTTPS port 8043, use `-listening_port 8080,ssl://8043:ssl_cert.pem` - -## Release 5.5, October 28 2014 - -Changes in Libmongoose library: - -- Added new API function: `mg_forward()` for proxying functionality -- Added new API function: `mg_send_file_data()` for sending file data -- Added new utility API functions: `mg_mmap() and mg_munmap()` -- Changed the way SSL settings are handled: removed `ssl_certificate` and - `ssl_ca_certificate` options, and instead made `listening_port` accept - `ssl://PORT:SSL_CERT:CA_CERT` notation -- Added ability to listen on multiple ports, see `listening_port` documentation -- Added `enable_proxy` option -- Added [cookie_authentication](https://github.com/cesanta/mongoose/tree/master/examples/cookie_authentication) example -- Added [websocket\_ssl\_proxy](https://github.com/cesanta/mongoose/tree/master/examples/websocket_ssl_proxy) example -- Added [http_client](https://github.com/cesanta/mongoose/tree/master/examples/http_client) example -- Increased default 'idle connection' timeout from 30 to 300 seconds -- Fixed MinGW build -- Refactored all examples, put each in it's own directory with dedicated build -- Many smaller bugfixed, including SSL, CGI, API, proxy, etc - -Changes in pre-compiled binaries: - -- Support for multiple listening ports -- Fixed CGI handling for scripts that specify interpreter in the hashbang line - -## Release 5.4, July 28 2014 - -Changes in Libmongoose library: - -- Added `hexdump_file` option for low-level request/reply debugging -- Added `mg_template()` API function for generating HTML pages from - templates with expansions -- Fixed `struct mg_connection::local_ip` handling, `mg_set_option()` - behavior with NULL values -- Added `mg_send_file()` call to send arbitrary file to the client -- Added `mg_terminate_ssl()` for SSL termination functionality -- Added HTTP proxy support, `enable_proxy` config option -- Added `mg_next()` for iterating over existing active connections -- Added client-side SSL auth, `ssl_ca_certificate` option -- Added `mg_wakeup_server_ex()` for pushing messages to existing connections -- Added `MG_WS_HANDSHAKE` and `MG_WS_CONNECT` events that are sent on - Websocket handshake is connection establishment, respectively -- Removed server-side Lua support -- Filesystem access, reading from socket/SSL performance improvements -- DAV PROPFIND memory leak fixed -- Added `big_upload.c` and enhanced `upload.c` example -- Added `proxy.c` example that demonstrates proxy functionality and SSE pushes -- Added `websocket2.c` example that shows simple web chat implementation - over websockets -- Various minor fixes - - -Changes in pre-compiled binaries: - -- Created HTML administration console -- When server is started, browser is started automatically -- Fixed directory listing bug when directory contains `#` character -- Removed built-in Lua Server Pages in the binary, and instead - added Mongoose + Lua developer bundle which has Lua Server Pages support. - That also solves external Lua modules loading problem. - - -## Release 5.3, March 10 2014 - -Changes in Libmongoose library: - - * Moved to the evented API. Updated API documentation is at - http://cesanta.com/docs/Embed.shtml - http://cesanta.com/docs/API.shtml - * Added `MG_LUA` event for exporting custom variables to the Lua environment - * Added virtual hosts capability, see `url_rewrites` option description at - http://cesanta.com/docs/Options.shtml - * Added mjpg serving example - * Cleaned up and documented HTTP client API, with unit tests - * Added `mg_wakeup_server()` to awaken `mg_poll_server()` - from another thread - * Moved Mongoose IO core to [https://github.com/cesanta/net_skeleton](Net Skeleton) - * Added connection hexdump functionality for developers - * Bug fixes - -Changes in pre-compiled binaries: - - * New awesome Mongoose logos by our designer Katrin - thanks Katrin! - Check them out at http://cesanta.com/products.shtml - * Added Lua Server Pages support to the free version, quick intro is at - http://cesanta.com/docs/Lua.shtml - * Added quick "Set shared directory" menu item to set `document_root` - * Added SSI support to the Pro version - * Removed SSL support from the Pro version - -## Release 5.2, Feb 1 2014 - - * Windows binary made fully UNICODE aware. In previous versions, - the presence of non-ASCII chars in document root, CGI script name, - or directory name might have broken Mongoose as stand-alone - or as Windows service. Now Mongoose works with non-ASCII paths properly. - Internally, Mongoose uses UTF8 encoding. When making WinAPI calls, - mongoose converts UTF8 strings to wide chars and calls UNICODE API. - * Enhanced authorization API by providing `mg_set_auth_handler()` and - `mg_authorize_digest()` - * Removed `mg_add_uri_handler()`, added `mg_set_request_handler()`. - There is only oneURI handler that handles all requests, just like in 4.x. - The reason for this change is to provide an ability to catch all URIs, - and at the same time signal Mongoose to continue handling specific URIs. - * Added `mg_parse_multipart()` API for file uploads. - Note that the restriction on uploading huge files still exists, - and will be eliminated in the next release. - * Allowing mongoose to bind to port 0, in which case it'll bind to any - random unused port. - * Moved `idle_timeout_ms` run-time option to compile-time flag - * Added asynchronous HTTP client, not documented yet. Documentation and - examples are coming in the next couple of weeks. Async Websocket client - is scheduled for the next release. See usage examples at `unit_test.c` - * Windows and MacOS pre-built binaries are now split to free and paid ones, - paid binaries include CGI, SSL, Lua, Sqlite, support and updates. - Linux pre-built binary includes all functionality and is free, and will - continue to be free. Source code for Windows and MacOS GUI is closed. - Disclaimer: source code for the command line stand-alone server, - as well as Mongoose library itself, will never be closed. - * Multiple bug fixes and minor enhancements - -## Release 5.1, Jan 10 2014 - - * CGI-related bugs where fixed, primarily for Windows platform - * Bugs on Windows related to UNICODE support were fixed - * Added a feature to support "error pages" through redirect. - Done using `-url_redirects` option, details are on - http://cesanta.com/docs/Options.shtml - -## Release 5.0, Jan 6 2014 - - * Internal core has been changed from blocking, thread-per-connection to - non-blocking, asynchronous, one thread for all. - * API modification for server creation and response creation. That allowed - keep-alive support for dynamic requests, boosting the embedded performance - to 100+ thousands requests per second on a single core - (as measured on my development MacBook laptop) - * Unified handling of POST requests and Websocket requests by putting a - payload into `conn->content`, `conn->content_len` attributes. - That simplified user code and eliminated the need of `mg_read()`, - since mongoose buffers all data prior to calling the callback - * keep-alive support is the default - * Dropped SSI support and throttling support - * Several configuration parameters are gone: - * `cgi_environment` (replaced with MONGOOSE_CGI), - * `protect_uri` (not useful) - * `ssi_pattern` (SSI support is gone) - * `throttle` (throttling support is gone) - * `error_log_file` (not used) - * `enable_keep_alive` (enabled by default) - * `listening_ports` (renamed to listening_port) - * `num_threads` (core has changed to single thread) - * `put_delete_auth_file` (renamed to dav_auth_file) - * `authentication_domain` (renamed to auth_domain) - * Due to the async, non-blocking nature of the core, few restrictions - are now in place: - * user callbacks must not block - * POST and Websocket data are now buffered, and cannot be huge - * mongoose is now capable on listening on only one port - -## Release 4.1, Oct 2013 -## Release 4.0, Oct 2013 -## Release 3.8, Sep 2013 - -## Release 3.7, Feb 2 2013 - - * Added "redirect to SSL port" functionality, e.g. if you specify - `-listening_ports 8080r,8043s` - then all requests to HTTP port 8080 will be redirected to HTTPS port 8043 - * Added `mg_download()` API, an HTTP client interface! - * Lua server pages now must output HTTP headers -- full control for Lua - * Added pre-built binary for MacOS, with initial GUI support - * API change: got rid of events, moved to struct `mg_callbacks` - * Bugfixes, thanks to contributors - - -## Release 3.7, Jan 18 2013 - * Fixed source code archive (main.c was missing) - * Extended Windows GUI functionality: - * Added "Start browser" systray popup menu item - * Enhanced configuration editor - * Renamed config options: - * `put_delete_passwords_file` -> `put_delete_auth_file` - * `global_passwords_file` -> `global_auth_file` - * `select()` changed to `poll()`, to avoid big file descriptor - `FD_SET` problem on UNIX - * Couple of bugfixes, thanks to contributors - - -Earlier release notes could be found by searching -[Mongoose mailing list](https://groups.google.com/forum/#!forum/mongoose-users) diff --git a/3rdparty/mongoose/docs/SSL.md b/3rdparty/mongoose/docs/SSL.md deleted file mode 100644 index 09f16e9e756..00000000000 --- a/3rdparty/mongoose/docs/SSL.md +++ /dev/null @@ -1,70 +0,0 @@ -# Mongoose SSL guide - -SSL is a protocol that makes web communication secure. To enable SSL -in mongoose, 2 steps are required: - - 1. Create valid SSL certificate file - 2. Append SSL certificate file path to the `listening_ports` option - -Below is the `mongoose.conf` file snippet for typical SSL setup: - - document_root www_root # Serve files in www_root directory - listening_ports 80,443:cert.pem # Listen on ports 80 and 443 - -## How to create SSL certificate file - -SSL certificate file is a text file that must contain at least two -sections: - - 1. A private key - 2. A certificate - -Both sections should be chunks of text in PEM format. When PEM file is -opened in a text editor, it looks like this: - - -----BEGIN RSA PRIVATE KEY----- - MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH - hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg= - -----END RSA PRIVATE KEY----- - -----BEGIN CERTIFICATE----- - MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB - SEGI4JSxV56lYg== - -----END CERTIFICATE----- - -Two aforementioned sections are clearly seen. Typically, those section -are bigger then in the example shown. The text between the `BEGIN` and -`END` is the text representation of binary data, a private key and a -certificate. Therefore, in order to create a certificate file, - - * private key must be converted to PEM format - * certificate must be converted to PEM format - * those two should be concatenated into a single file - -If the certificate chain in used, a chain file also needs to be -converted into PEM format and appended to the certificate file. - -## How SSL works - -SSL is a protocol that can encrypt communication between two parties. If third -party observes all messages passed by, it would be very -hard for the third party (though not impossible) to decrypt the communication. - -The idea is based on so-called public key encryption. Communicating parties -have two keys: a public key and a private key. A public key is advertised -to everybody, and it is contained in a certificate. A private key is kept -secret. Security algorithm works in a way that anybody can encrypt -a message using public key, and only private key can decrypt it. - -This is why web server needs both private key and certificate: private key -is used to decrypt incoming messages, and certificate is used to tell the -public key to the other party. When communication starts, parties exchange -their public keys, and keep private keys to themselves. Man-in-the-middle -who observes the communication is unable to decrypt the messages cause -private keys are required for decryption. - -Encryption algorithms are built on top of hard mathematical problem, which -makes it very expensive for man-in-the-middle to compute private keys. -For example, RSA algorithm is based on a mathematical problem of factorization. -It is easy to generate two very large prime numbers `P` and `Q` and make -a product `P * Q`. But given a product, it is very hard to recover these -two prime numbers - this is called factorization. diff --git a/3rdparty/mongoose/docs/Usage.md b/3rdparty/mongoose/docs/Usage.md deleted file mode 100644 index b9f7052fa09..00000000000 --- a/3rdparty/mongoose/docs/Usage.md +++ /dev/null @@ -1,86 +0,0 @@ -# Mongoose User Guide - -Mongoose is small and easy to use web server built on top of -mongoose library. It is designed with maximum simplicity in mind. For example, -to share any directory, just drop mongoose executable in that directory, -double-click it (on UNIX, run it from shell) and launch a browser at -[http://localhost:8080](http://localhost:8080) Note that 'localhost' should -be changed to a machine's name if a folder is accessed from other computer. - -On Windows and Mac, Mongoose iconifies itself to the system tray when started. -Right-click on the icon to pop up a menu, where it is possible to stop -mongoose, or configure it. - -On UNIX, `mongoose` is a command line utility. Running `mongoose` in -terminal, optionally followed by configuration parameters -(`mongoose [OPTIONS]`) or configuration file name -(`mongoose [config_file_name]`) starts the -web server: - - $ mongoose -document_root /var/www # Running mongoose with cmdline options - $ mongoose /etc/my_config.txt # Running mongoose with config file - $ mongoose # Running with no parameters. This will - # serve current directory on port 8080 - -Mongoose does not detach from terminal. Pressing `Ctrl-C` keys -stops the server. - -When started, mongoose first searches for the configuration file. -If configuration file is specified explicitly in the command line, then -specified configuration file is used. -Otherwise, mongoose would search for file `mongoose.conf` in the same directory -where binary is located, and use it. Configuration file can be absent. - -Configuration file is a sequence of lines, each line containing -command line argument name and it's value. Empty lines and lines beginning -with `#` are ignored. Here is the example of `mongoose.conf` file: - - # This is a comment - document_root C:\www - listening_port 80 - ssl_certificate C:\mongoose\ssl_cert.pem - -Command line arguments are highest priority and can override -configuration file settings. For example, if `mongoose.conf` has line -`document_root /var/www`, and mongoose has been started as -`mongoose -document_root /etc`, then `/etc` directory will be used as -document root. - -Note that configuration options on the command line must start with `-`, -and their names are the same as in the config file. Exampli gratia, -the following two setups are equivalent: - - $ mongoose -listening_port 1234 -document_root /var/www - - $ cat > mongoose.conf - listening_ports 1234 - document_root /var/www - ^D - $ mongoose - -Mongoose can also be used to modify `.htpasswd` passwords file: - - $ mongoose -A .htpasswd mydomain.com user_name user_password - -Unlike other web servers, mongoose does not require CGI scripts be located in -a special directory. CGI scripts can be anywhere. CGI (and SSI) files are -recognized by the file name pattern. Mongoose uses shell-like glob -patterns. Pattern match starts at the beginning of the string, so essentially -patterns are prefix patterns. Syntax is as follows: - - ** Matches everything - * Matches everything but slash character, '/' - ? Matches any character - $ Matches the end of the string - | Matches if pattern on the left side or the right side matches. - -All other characters in the pattern match themselves. Examples: - - # Pattern Meaning - **.cgi$ Any string that ends with .cgi - /foo Any string that begins with /foo - **a$|**b$ Any string that ends with a or b - -To restrict CGI files only to `/cgi-bin/` directory, use this setting: - - $ mongoose -cgi_pattern /cgi-bin/*.cgi # Emulate /cgi-bin/ restriction diff --git a/3rdparty/mongoose/examples/.gitignore b/3rdparty/mongoose/examples/.gitignore deleted file mode 100644 index b883f1fdc6d..00000000000 --- a/3rdparty/mongoose/examples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.exe diff --git a/3rdparty/mongoose/examples/Makefile b/3rdparty/mongoose/examples/Makefile deleted file mode 100644 index 43483c3f860..00000000000 --- a/3rdparty/mongoose/examples/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -SUBDIRS = $(sort $(filter-out csharp/, $(dir $(wildcard */)))) -X = $(SUBDIRS) -ifdef WINDIR - # appending the Winsock2 library at the end of the compiler - # invocation - CFLAGS_EXTRA += -lws2_32 -endif - -.PHONY: $(SUBDIRS) - -all: $(SUBDIRS) - -$(SUBDIRS): - @$(MAKE) CFLAGS_EXTRA="$(CFLAGS_EXTRA)" -C $@ - -clean: - for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done diff --git a/3rdparty/mongoose/examples/array_vars/Makefile b/3rdparty/mongoose/examples/array_vars/Makefile deleted file mode 100644 index 5ce2d1db6cb..00000000000 --- a/3rdparty/mongoose/examples/array_vars/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = array_vars -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - wine $(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/3rdparty/mongoose/examples/array_vars/array_vars.c b/3rdparty/mongoose/examples/array_vars/array_vars.c deleted file mode 100644 index d631a7b0c79..00000000000 --- a/3rdparty/mongoose/examples/array_vars/array_vars.c +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates how to use array get variables using mg_get_n_var -// $Date: 2014-09-09 22:20:23 UTC $ - -#include -#include -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: - { - mg_printf_data(conn, "Hello! Requested URI is [%s] ", conn->uri); - char buffer[1024]; - int i, ret; - for(i=0; (ret = mg_get_var_n(conn, "foo[]", buffer, 1024, i)) > 0; i++) - mg_printf_data(conn, "\nfoo[%d] = %s", i, buffer); - - return MG_TRUE; - } - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/big_upload/Makefile b/3rdparty/mongoose/examples/big_upload/Makefile deleted file mode 100644 index a47d188489f..00000000000 --- a/3rdparty/mongoose/examples/big_upload/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = big_upload -CFLAGS = -W -Wall -pthread -I../.. -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/big_upload/big_upload.c b/3rdparty/mongoose/examples/big_upload/big_upload.c deleted file mode 100644 index a756ddd3a07..00000000000 --- a/3rdparty/mongoose/examples/big_upload/big_upload.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include "mongoose.h" - -static int handle_request(struct mg_connection *conn) { - if (strcmp(conn->uri, "/upload") == 0) { - FILE *fp = (FILE *) conn->connection_param; - if (fp != NULL) { - fwrite(conn->content, 1, conn->content_len, fp); // Write last bits - mg_printf(conn, "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Connection: close\r\n\r\n" - "Written %ld of POST data to a temp file:\n\n", - (long) ftell(fp)); - - // Temp file will be destroyed after fclose(), do something with the - // data here -- for example, parse it and extract uploaded files. - // As an example, we just echo the whole POST buffer back to the client. - rewind(fp); - mg_send_file_data(conn, fileno(fp)); - return MG_MORE; // Tell Mongoose reply is not completed yet - } else { - mg_printf_data(conn, "%s", "Had no data to write..."); - return MG_TRUE; // Tell Mongoose we're done with this request - } - } else { - mg_printf_data(conn, "%s", - "Upload example." - "
" - "
" - "" - "
"); - return MG_TRUE; // Tell mongoose to close this connection - } -} - -// Mongoose sends MG_RECV for every received POST chunk. -// When last POST chunk is received, Mongoose sends MG_REQUEST, then MG_CLOSE. -static int handle_recv(struct mg_connection *conn) { - FILE *fp = (FILE *) conn->connection_param; - - // Open temporary file where we going to write data - if (fp == NULL && ((conn->connection_param = fp = tmpfile())) == NULL) { - return -1; // Close connection on error - } - - // Return number of bytes written to a temporary file: that is how many - // bytes we want to discard from the receive buffer - return fwrite(conn->content, 1, conn->content_len, fp); -} - -// Make sure we free all allocated resources -static int handle_close(struct mg_connection *conn) { - if (conn->connection_param != NULL) { - fclose((FILE *) conn->connection_param); - conn->connection_param = NULL; - } - return MG_TRUE; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: return handle_request(conn); - case MG_RECV: return handle_recv(conn); - case MG_CLOSE: return handle_close(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - - for (;;) { - mg_poll_server(server, 1000); - } - - mg_destroy_server(&server); - return 0; -} diff --git a/3rdparty/mongoose/examples/cookie_authentication/Makefile b/3rdparty/mongoose/examples/cookie_authentication/Makefile deleted file mode 100644 index 1eb0652b961..00000000000 --- a/3rdparty/mongoose/examples/cookie_authentication/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = cookie_auth -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c b/3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c deleted file mode 100644 index c35e0445ef2..00000000000 --- a/3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved - -#include -#include -#include -#include "mongoose.h" - -static const char *s_login_uri = "/login.html"; -static const char *s_secret = ":-)"; // Must be known only to server - -static void generate_ssid(const char *user_name, const char *expiration_date, - char *ssid, size_t ssid_size) { - char hash[33]; - mg_md5(hash, user_name, ":", expiration_date, ":", s_secret, NULL); - snprintf(ssid, ssid_size, "%s|%s|%s", user_name, expiration_date, hash); -} - -static int check_auth(struct mg_connection *conn) { - char ssid[100], calculated_ssid[100], name[100], expire[100]; - - // Always authenticate requests to login page - if (strcmp(conn->uri, s_login_uri) == 0) { - return MG_TRUE; - } - - // Look for session ID in the Cookie. - // That session ID can be validated against the database that stores - // current active sessions. - mg_parse_header(mg_get_header(conn, "Cookie"), "ssid", ssid, sizeof(ssid)); - if (sscanf(ssid, "%[^|]|%[^|]|", name, expire) == 2) { - generate_ssid(name, expire, calculated_ssid, sizeof(calculated_ssid)); - if (strcmp(ssid, calculated_ssid) == 0) { - return MG_TRUE; // Authenticate - } - } - - // Auth failed, do NOT authenticate, redirect to login page - mg_printf(conn, "HTTP/1.1 302 Moved\r\nLocation: %s\r\n\r\n", s_login_uri); - return MG_FALSE; -} - -static int check_login_form_submission(struct mg_connection *conn) { - char name[100], password[100], ssid[100], expire[100], expire_epoch[100]; - - mg_get_var(conn, "name", name, sizeof(name)); - mg_get_var(conn, "password", password, sizeof(password)); - - // A real authentication mechanism should be employed here. - // Also, the whole site should be served through HTTPS. - if (strcmp(name, "Joe") == 0 && strcmp(password, "Doe") == 0) { - // Generate expiry date - time_t t = time(NULL) + 3600; // Valid for 1 hour - snprintf(expire_epoch, sizeof(expire_epoch), "%lu", (unsigned long) t); - strftime(expire, sizeof(expire), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); - generate_ssid(name, expire_epoch, ssid, sizeof(ssid)); - // Set "session id" cookie, there could be some data encoded in it. - mg_printf(conn, - "HTTP/1.1 302 Moved\r\n" - "Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n" - "Content-Length: 0\r\n" - "Location: /\r\n\r\n", - ssid, expire); - return MG_TRUE; - } - return MG_FALSE; -} - -static int serve_request(struct mg_connection *conn) { - if (strcmp(conn->uri, s_login_uri) == 0 && - strcmp(conn->request_method, "POST") == 0) { - return check_login_form_submission(conn); - } - return MG_FALSE; // Serve files in the document_root -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return check_auth(conn); - case MG_REQUEST: return serve_request(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - mg_set_option(server, "document_root", "."); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/cookie_authentication/index.html b/3rdparty/mongoose/examples/cookie_authentication/index.html deleted file mode 100644 index fc992fd03de..00000000000 --- a/3rdparty/mongoose/examples/cookie_authentication/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - WebSocket Test - - - - -
-

Mongoose Cookie Base Authentication

-

This is an index page. Authentication succeeded.

- - \ No newline at end of file diff --git a/3rdparty/mongoose/examples/cookie_authentication/login.html b/3rdparty/mongoose/examples/cookie_authentication/login.html deleted file mode 100644 index d3ff7056573..00000000000 --- a/3rdparty/mongoose/examples/cookie_authentication/login.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - WebSocket Test - - - - -
-

Mongoose Cookie Based Authentication

-

Use name "Joe", password "Doe" to login.

-
-
- - -
- - -
- -
-
- - \ No newline at end of file diff --git a/3rdparty/mongoose/examples/csharp/example.cs b/3rdparty/mongoose/examples/csharp/example.cs deleted file mode 100644 index 9736c6b991d..00000000000 --- a/3rdparty/mongoose/examples/csharp/example.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of mongoose web server project, -// https://github.com/cesanta/mongoose - -using System; - -public class Program { - static private int EventHandler(IntPtr conn_ptr, int ev) { - MongooseConnection conn = (MongooseConnection) - System.Runtime.InteropServices.Marshal.PtrToStructure( - conn_ptr , typeof(MongooseConnection)); - - if (ev == 102) { - // MG_AUTH - return 1; - } else if (ev == 103) { - // MG_REQUEST - Mongoose.send_data(conn_ptr, "Hello from C#!\n"); - Mongoose.send_data(conn_ptr, "URI: " + conn.uri + "\n"); - Mongoose.send_data(conn_ptr, "HTTP Headers:\n"); - - for (int i = 0; i < conn.num_headers; i++) { - IntPtr name = conn.http_headers[i].name; - IntPtr val = conn.http_headers[i].value; - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name); - Mongoose.send_data(conn_ptr, " " + - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name) + ": " + - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(val) + "\n"); - } - return 1; - } - return 0; - } - - static void Main() { - Mongoose web_server = new Mongoose(".", "9001", - new MongooseEventHandler(EventHandler)); - - Console.WriteLine("Mongoose started, press Ctrl-C to exit."); - for (;;) { - web_server.poll(1000); - } - } -} diff --git a/3rdparty/mongoose/examples/csharp/mongoose.cs b/3rdparty/mongoose/examples/csharp/mongoose.cs deleted file mode 100644 index f0953d22d58..00000000000 --- a/3rdparty/mongoose/examples/csharp/mongoose.cs +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of mongoose web server project, -// https://github.com/cesanta/mongoose - -using System; -using System.Runtime.InteropServices; - -[StructLayout(LayoutKind.Sequential)] public struct MongooseHeader { - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr name; - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr value; -}; - -// mongoose.h :: struct mg_connection -[StructLayout(LayoutKind.Sequential)] public struct MongooseConnection { - [MarshalAs(UnmanagedType.LPTStr)] public string request_method; - [MarshalAs(UnmanagedType.LPTStr)] public string uri; - [MarshalAs(UnmanagedType.LPTStr)] public string http_version; - [MarshalAs(UnmanagedType.LPTStr)] public string query_string; - - [MarshalAs(UnmanagedType.ByValArray,SizeConst=48)] public char[] remote_ip; - [MarshalAs(UnmanagedType.LPTStr)] public string local_ip; - [MarshalAs(UnmanagedType.U2)] public short remote_port; - [MarshalAs(UnmanagedType.U2)] public short local_port; - - [MarshalAs(UnmanagedType.SysInt)] public int num_headers; - [MarshalAs(UnmanagedType.ByValArray,SizeConst=30)] - public MongooseHeader[] http_headers; - - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr content; - [MarshalAs(UnmanagedType.SysInt)] public int content_len; - - [MarshalAs(UnmanagedType.SysInt)] public int is_websocket; - [MarshalAs(UnmanagedType.SysInt)] public int status_code; - [MarshalAs(UnmanagedType.SysInt)] public int wsbits; -}; - -public delegate int MongooseEventHandler(IntPtr c, int ev); - -public class Mongoose { - public const string dll_ = "mongoose"; - private IntPtr server_; - - [DllImport(dll_)] private static extern IntPtr - mg_create_server(IntPtr user_data, MongooseEventHandler eh); - [DllImport(dll_)] private static extern int - mg_poll_server(IntPtr server, int milli); - [DllImport(dll_)] private static extern IntPtr - mg_set_option(IntPtr server, string name, string value); - [DllImport(dll_)] public static extern int - mg_send_data(IntPtr conn, string data, int length); - - public Mongoose(string document_root, - string listening_port, - MongooseEventHandler event_handler) { - server_ = mg_create_server(IntPtr.Zero, event_handler); - mg_set_option(server_, "document_root", document_root); - mg_set_option(server_, "listening_port", listening_port); - } - - public static int send_data(IntPtr conn, string data) { - return mg_send_data(conn, data, data.Length); - } - - public void poll(int milli) { - mg_poll_server(server_, milli); - } - - // TODO: add destructor and call mg_destroy_server() -} diff --git a/3rdparty/mongoose/examples/digest_authentication/Makefile b/3rdparty/mongoose/examples/digest_authentication/Makefile deleted file mode 100644 index 86cd30db1d7..00000000000 --- a/3rdparty/mongoose/examples/digest_authentication/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = digest_auth -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/digest_authentication/digest_auth.c b/3rdparty/mongoose/examples/digest_authentication/digest_auth.c deleted file mode 100644 index 18835c729c7..00000000000 --- a/3rdparty/mongoose/examples/digest_authentication/digest_auth.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - - if (ev == MG_AUTH) { - int result = MG_FALSE; // Not authorized - FILE *fp; - - // To populate passwords file, do - // mongoose -A my_passwords.txt mydomain.com admin admin - if ((fp = fopen("my_passwords.txt", "r")) != NULL) { - result = mg_authorize_digest(conn, fp); - fclose(fp); - } - - return result; - } - - return MG_FALSE; -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - mg_set_option(server, "document_root", "."); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/file_upload/Makefile b/3rdparty/mongoose/examples/file_upload/Makefile deleted file mode 100644 index bf1e51dfc90..00000000000 --- a/3rdparty/mongoose/examples/file_upload/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = file_upload -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/3rdparty/mongoose/examples/file_upload/file_upload.c b/3rdparty/mongoose/examples/file_upload/file_upload.c deleted file mode 100644 index eedfc837c57..00000000000 --- a/3rdparty/mongoose/examples/file_upload/file_upload.c +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2004-2012 Sergey Lyubka -// This file is a part of mongoose project, http://github.com/valenok/mongoose - -#include -#include -#include "mongoose.h" - -static int send_index_page(struct mg_connection *conn) { - const char *data; - int data_len, n1, n2; - char var_name[100], file_name[100]; - - mg_printf_data(conn, "%s", - "Upload example." - "
" - "
" - "
" - "" - "
"); - - n1 = n2 = 0; - while ((n2 = mg_parse_multipart(conn->content + n1, conn->content_len - n1, - var_name, sizeof(var_name), file_name, - sizeof(file_name), &data, &data_len)) > 0) { - mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes
", - var_name, file_name, data_len); - n1 += n2; - } - - mg_printf_data(conn, "%s", ""); - - return MG_TRUE; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: return send_index_page(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/form_submit/Makefile b/3rdparty/mongoose/examples/form_submit/Makefile deleted file mode 100644 index b233f285774..00000000000 --- a/3rdparty/mongoose/examples/form_submit/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = form_submit -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/form_submit/form_submit.c b/3rdparty/mongoose/examples/form_submit/form_submit.c deleted file mode 100644 index f6893114d7f..00000000000 --- a/3rdparty/mongoose/examples/form_submit/form_submit.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include "mongoose.h" - -static const char *html_form = - "POST example." - "
" - "Input 1:
" - "Input 2:
" - "" - "
"; - -static void send_reply(struct mg_connection *conn) { - char var1[500], var2[500]; - - if (strcmp(conn->uri, "/handle_post_request") == 0) { - // User has submitted a form, show submitted data and a variable value - // Parse form data. var1 and var2 are guaranteed to be NUL-terminated - mg_get_var(conn, "input_1", var1, sizeof(var1)); - mg_get_var(conn, "input_2", var2, sizeof(var2)); - - // Send reply to the client, showing submitted form values. - // POST data is in conn->content, data length is in conn->content_len - mg_send_header(conn, "Content-Type", "text/plain"); - mg_printf_data(conn, - "Submitted data: [%.*s]\n" - "Submitted data length: %d bytes\n" - "input_1: [%s]\n" - "input_2: [%s]\n", - conn->content_len, conn->content, - conn->content_len, var1, var2); - } else { - // Show HTML form. - mg_send_data(conn, html_form, strlen(html_form)); - } -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_REQUEST) { - send_reply(conn); - return MG_TRUE; - } else if (ev == MG_AUTH) { - return MG_TRUE; - } else { - return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/hello_world/Makefile b/3rdparty/mongoose/examples/hello_world/Makefile deleted file mode 100644 index d1384e01723..00000000000 --- a/3rdparty/mongoose/examples/hello_world/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = hello_world -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - wine $(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/3rdparty/mongoose/examples/hello_world/hello_world.c b/3rdparty/mongoose/examples/hello_world/hello_world.c deleted file mode 100644 index 95056895d02..00000000000 --- a/3rdparty/mongoose/examples/hello_world/hello_world.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates basic use of Mongoose embedded web server. -// $Date: 2014-09-09 22:20:23 UTC $ - -#include -#include -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: - mg_printf_data(conn, "Hello! Requested URI is [%s]", conn->uri); - return MG_TRUE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/http_client/Makefile b/3rdparty/mongoose/examples/http_client/Makefile deleted file mode 100644 index 5769babf0f7..00000000000 --- a/3rdparty/mongoose/examples/http_client/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = http_client -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -unix: $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp *.o *.lib diff --git a/3rdparty/mongoose/examples/http_client/http_client.c b/3rdparty/mongoose/examples/http_client/http_client.c deleted file mode 100644 index 41eac581e90..00000000000 --- a/3rdparty/mongoose/examples/http_client/http_client.c +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates how to connect to the remote Web server, -// download data, process it and send back a reply. - -#include -#include - -#include "mongoose.h" - -static int s_received_signal = 0; -static struct mg_server *s_server = NULL; -static const char *s_remote_addr = "glosbe.com:80"; - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - struct mg_connection *client, *orig; - - switch (ev) { - case MG_AUTH: - return MG_TRUE; - - case MG_CONNECT: - // Send request to the remote host. - // TODO(lsm): handle connect error here. - mg_printf(conn, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", - "/gapi/translate?from=eng&dest=fra&format=json&phrase=cat", - s_remote_addr); - return MG_TRUE; - - case MG_REPLY: - // Send reply to the original connection - orig = (struct mg_connection *) conn->connection_param; - mg_send_status(orig, conn->status_code); - mg_send_header(orig, "Content-Type", "text/plain"); - mg_send_data(orig, conn->content, conn->content_len); - mg_send_data(orig, "", 0); // Last chunk: mark the end of reply - - // Disconnect connections - orig->connection_param = NULL; - conn->connection_param = NULL; - return MG_TRUE; - - case MG_REQUEST: - if ((client = mg_connect(s_server, s_remote_addr)) != NULL) { - // Interconnect requests - client->connection_param = conn; - conn->connection_param = client; - return MG_MORE; - } else { - mg_printf_data(conn, "%s", "cannot send API request"); - return MG_TRUE; - } - - default: - return MG_FALSE; - } -} - -int main(void) { - s_server = mg_create_server(NULL, ev_handler); - - mg_set_option(s_server, "listening_port", "8080"); - - // Setup signal handlers - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - printf("Listening on port %s\n", mg_get_option(s_server, "listening_port")); - while (s_received_signal == 0) { - mg_poll_server(s_server, 1000); - } - mg_destroy_server(&s_server); - printf("Existing on signal %d\n", s_received_signal); - - return EXIT_SUCCESS; -} diff --git a/3rdparty/mongoose/examples/mjpg_streamer/Makefile b/3rdparty/mongoose/examples/mjpg_streamer/Makefile deleted file mode 100644 index 35946c0a477..00000000000 --- a/3rdparty/mongoose/examples/mjpg_streamer/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = mjpg_streamer -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c b/3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c deleted file mode 100644 index 4bac6c14838..00000000000 --- a/3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include "mongoose.h" - -static void send_file(struct mg_connection *conn, const char *path) { - char buf[1024]; - struct stat st; - int n; - FILE *fp; - - if (stat(path, &st) == 0 && (fp = fopen(path, "rb")) != NULL) { - mg_printf(conn, "--w00t\r\nContent-Type: image/jpeg\r\n" - "Content-Length: %lu\r\n\r\n", (unsigned long) st.st_size); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { - mg_write(conn, buf, n); - } - fclose(fp); - mg_write(conn, "\r\n", 2); - } -} - -struct conn_state { - int file_index; - time_t last_poll; -}; - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - const char **file_names = (const char **) conn->server_param; - struct conn_state *state; - time_t now = time(NULL); - - switch (ev) { - - case MG_AUTH: - return MG_TRUE; - - case MG_REQUEST: - if (strcmp(conn->uri, "/stream") != 0) { - mg_send_header(conn, "Content-Type", "text/html"); - mg_printf_data(conn, "%s", - "Go to /stream for MJPG stream"); - return MG_TRUE; - } - - mg_printf(conn, "%s", - "HTTP/1.0 200 OK\r\n" "Cache-Control: no-cache\r\n" - "Pragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\n" - "Connection: close\r\nContent-Type: multipart/x-mixed-replace; " - "boundary=--w00t\r\n\r\n"); - - send_file(conn, file_names[0]); - - state = (struct conn_state *) malloc(sizeof(*state)); - conn->connection_param = state; - state->file_index = 1; // First file is already sent - state->last_poll = time(NULL); - return MG_MORE; - - case MG_POLL: - state = (struct conn_state *) conn->connection_param; - - if (state != NULL && now > state->last_poll) { - if (file_names[state->file_index] != NULL) { - send_file(conn, file_names[state->file_index]); - state->file_index++; - if (file_names[state->file_index] == NULL) { - return MG_TRUE; // No more images, close connection - } - } - state->last_poll = now; - } - return MG_FALSE; - - case MG_CLOSE: - free(conn->connection_param); - conn->connection_param = NULL; - return MG_FALSE; - - default: - return MG_FALSE; - } -} - -int main(int argc, char *argv[]) { - struct mg_server *server; - - if (argc < 3) { - printf("Usage: %s image1.jpg image2.jpg ...\n", argv[0]); - return 1; - } - - server = mg_create_server(&argv[1], ev_handler); - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/multi_threaded_server/Makefile b/3rdparty/mongoose/examples/multi_threaded_server/Makefile deleted file mode 100644 index 2b08db12c77..00000000000 --- a/3rdparty/mongoose/examples/multi_threaded_server/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = multi_threaded_server -CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c b/3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c deleted file mode 100644 index 30af3f10807..00000000000 --- a/3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "mongoose.h" - -// Start a browser and hit refresh couple of times. The replies will -// come from both server instances. -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_REQUEST) { - mg_send_header(conn, "Content-Type", "text/plain"); - mg_printf_data(conn, "This is a reply from server instance # %s", - (char *) conn->server_param); - return MG_TRUE; - } else if (ev == MG_AUTH) { - return MG_TRUE; - } else { - return MG_FALSE; - } -} - -static void *serve(void *server) { - for (;;) mg_poll_server((struct mg_server *) server, 1000); - return NULL; -} - -int main(void) { - struct mg_server *server1, *server2; - - server1 = mg_create_server((void *) "1", ev_handler); - server2 = mg_create_server((void *) "2", ev_handler); - - // Make both server1 and server2 listen on the same sockets - mg_set_option(server1, "listening_port", "8080"); - mg_copy_listeners(server1, server2); - - // server1 goes to separate thread, server 2 runs in main thread. - // IMPORTANT: NEVER LET DIFFERENT THREADS HANDLE THE SAME SERVER. - mg_start_thread(serve, server1); - mg_start_thread(serve, server2); - getchar(); - - return 0; -} diff --git a/3rdparty/mongoose/examples/proxy_server/Makefile b/3rdparty/mongoose/examples/proxy_server/Makefile deleted file mode 100644 index 7a5d2f7d41a..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = proxy_server -FLAGS = -I../.. -DNS_ENABLE_SSL -CFLAGS = -W -Wall -g -O0 -pthread -lssl -DMONGOOSE_ENABLE_THREADS $(FLAGS) $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -unix: $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/proxy_server/proxy_server.c b/3rdparty/mongoose/examples/proxy_server/proxy_server.c deleted file mode 100644 index cef0f24c9bb..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/proxy_server.c +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// To build and run this example: -// git clone https://github.com/cesanta/net_skeleton.git -// git clone https://github.com/cesanta/mongoose.git -// cd mongoose/examples -// make proxy -// ./proxy -// -// Configure your browser to use localhost:2014 as a proxy for all protocols -// Then, navigate to https://cesanta.com - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#define sleep(x) Sleep((x) * 1000) -#else -#include -#endif - -#include "mongoose.h" - -static int s_received_signal = 0; -static struct mg_server *s_server = NULL; - -#define SSE_CONNECTION ((void *) 1) - -static void elog(int do_exit, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); - if (do_exit) exit(EXIT_FAILURE); -} - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static int sse_push(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_POLL && conn->connection_param == SSE_CONNECTION) { - mg_printf(conn, "data: %s\r\n\r\n", (const char *) conn->callback_param); - } - return MG_TRUE; -} - -static void *sse_pusher_thread_func(void *param) { - while (s_received_signal == 0) { - mg_wakeup_server_ex(s_server, sse_push, "%lu %s", - (unsigned long) time(NULL), (const char *) param); - sleep(1); - } - return NULL; -} - -// Return: 1 if regular file, 2 if directory, 0 if not found -static int exists(const char *path) { - struct stat st; - return stat(path, &st) != 0 ? 0 : S_ISDIR(st.st_mode) == 0 ? 1 : 2; -} - -// Return: 1 if regular file, 2 if directory, 0 if not found -static int is_local_file(const char *uri, char *path, size_t path_len) { - snprintf(path, path_len, "%s/%s", - mg_get_option(s_server, "document_root"), uri); - return exists(path); -} - -static int try_to_serve_locally(struct mg_connection *conn) { - char path[500], buf[2000]; - int n, res; - FILE *fp = NULL; - - if ((res = is_local_file(conn->uri, path, sizeof(path))) == 2) { - strncat(path, "/index.html", sizeof(path) - strlen(path) - 1); - res = exists(path); - printf("PATH: [%s]\n", path); - } - if (res == 0) return MG_FALSE; - - if ((fp = fopen(path, "rb")) != NULL) { - printf("Serving [%s] locally \n", path); - mg_send_header(conn, "Connection", "close"); - mg_send_header(conn, "Content-Type", mg_get_mime_type(path, "text/plain")); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { - mg_send_data(conn, buf, n); - } - mg_send_data(conn, "", 0); - fclose(fp); - } - return fp == NULL ? MG_FALSE : MG_TRUE; -} - -static int is_resource_present_locally(const char *uri) { - char path[500]; - return is_local_file(uri, path, sizeof(path)) || strcmp(uri, "/api/sse") == 0; -} - -static int proxy_event_handler(struct mg_connection *conn, enum mg_event ev) { - static const char target_url[] = "http://cesanta.com"; - static int target_url_size = sizeof(target_url) - 1; - const char *host; - - switch (ev) { - case MG_REQUEST: - host = mg_get_header(conn, "Host"); - printf("[%s] [%s] [%s]\n", conn->request_method, conn->uri, - host == NULL ? "" : host); - if (strstr(conn->uri, "/qqq") != NULL) s_received_signal = SIGTERM; - - // Proxied HTTPS requests use "CONNECT foo.com:443" - // Proxied HTTP requests use "GET http://..... " - // Serve requests for target_url from the local FS. - if (memcmp(conn->uri, target_url, target_url_size) == 0 && - is_resource_present_locally(conn->uri + target_url_size)) { - conn->uri += target_url_size; // Leave only path in the URI - } - - if (strcmp(conn->uri, "/api/sse") == 0) { - conn->connection_param = SSE_CONNECTION; - mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n" - "Content-Type: text/event-stream\r\n" - "Cache-Control: no-cache\r\n\r\n"); - return MG_MORE; - } - - if (host != NULL && strstr(host, "cesanta") != NULL) { - return try_to_serve_locally(conn); - } - - // Enable man-in-the-middle SSL mode for oracle.com - if (!strcmp(conn->request_method, "CONNECT") && - !strcmp(host, "oracle.com")) { - mg_terminate_ssl(conn, "ssl_cert.pem"); // MUST return MG_MORE after - return MG_MORE; - } - - return MG_FALSE; - case MG_AUTH: - return MG_TRUE; - default: - return MG_FALSE; - } -} - -static void setopt(struct mg_server *s, const char *opt, const char *val) { - const char *err_msg = mg_set_option(s, opt, val); - if (err_msg != NULL) { - elog(1, "Error setting [%s]: [%s]", opt, err_msg); - } -} - -int main(int argc, char *argv[]) { - const char *port = "2014", *dump = NULL, *root = "proxy_web_root"; - int i; - - // Parse command line options - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) { - port = argv[++i]; - } else if (strcmp(argv[i], "-root") == 0 && i + 1 < argc) { - root = argv[++i]; - } else if (strcmp(argv[i], "-dump") == 0 && i + 1 < argc) { - dump = argv[++i]; - } else { - elog(1, "Usage: %s [-cert FILE] [-ca_cert FILE] [-port PORT]", argv[0]); - } - } - - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - // Create and configure proxy server - s_server = mg_create_server(NULL, &proxy_event_handler); - setopt(s_server, "enable_proxy", "yes"); - setopt(s_server, "document_root", root); - setopt(s_server, "listening_port", port); - setopt(s_server, "hexdump_file", dump); - - // Start two SSE pushing threads - mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_1"); - mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_2"); - - // Start serving in the main thread - printf("Starting on port %s\n", mg_get_option(s_server, "listening_port")); - while (s_received_signal == 0) { - mg_poll_server(s_server, 1000); - } - printf("Existing on signal %d\n", s_received_signal); - mg_destroy_server(&s_server); - - return EXIT_SUCCESS; -} diff --git a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html b/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html deleted file mode 100644 index 5b5c81677f2..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - App1 Index - - - - -

App1 index page. Served locally from the the proxy server filesystem

- -

image that references non-existent local resource. Forwarded to - the 'real' proxy target:

- - -

Google logo via HTTPS (external resource, served by remote host):

- - -

Same image via HTTP:

- - - - diff --git a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html b/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html deleted file mode 100644 index 28d4beadcdb..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - App2 Index - - - - -

App2 index page. Served locally from the - the proxy's filesystem.

-

- Following div shows proxy forwarding of websocket connection, served by - ws://echo.websocket.org: -

- -
- - diff --git a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html b/3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html deleted file mode 100644 index d8343bf3b71..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - proxy index - - - -

proxy index page.

-
    -
  • App1 - App1 root
  • -
  • App2 - App2 root
  • -
- -

SSE pushes, done by separate threads at random times:

-
- - - diff --git a/3rdparty/mongoose/examples/proxy_server/ssl_cert.pem b/3rdparty/mongoose/examples/proxy_server/ssl_cert.pem deleted file mode 100644 index e6045389a1a..00000000000 --- a/3rdparty/mongoose/examples/proxy_server/ssl_cert.pem +++ /dev/null @@ -1,50 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH -hMSGCcSV6y32hzhqR5lvTViaQez+xhc58NZRu+OUgEhodRBW/vAOjpz/xdMz5HaC -EhP3E9W1pkitVseS8B5rrgJo1BfCGai1fPav1nutPq2Kj7vMy24+g460Lonf6ln1 -di4aTIRtAqXtUU6RFpPJP35PkCXbTK65O8HJSxxt/XtfoezHCU5+UIwmZGYx46UB -Wzg3IfK6bGPSiHU3pdiTol0uMPt/GUK+x4NyZJ4/ImsNAicRwMBdja4ywHKXJehH -gXBthsVIHbL21x+4ibsg9eVM/XioTV6tW3IrdwIDAQABAoIBACFfdLutmkQFBcRN -HAJNNHmmsyr0vcUOVnXTFyYeDXV67qxrYHQlOHe6LqIpKq1Mon7O2kYMnWvooFAP -trOnsS6L+qaTYJdYg2TKjgo4ubw1hZXytyB/mdExuaMSkgMgtpia+tB5lD+V+LxN -x1DesZ+veFMO3Zluyckswt4qM5yVa04YFrt31H0E1rJfIen61lidXIKYmHHWuRxK -SadjFfbcqJ6P9ZF22BOkleg5Fm5NaxJmyQynOWaAkSZa5w1XySFfRjRfsbDr64G6 -+LSG8YtRuvfxnvUNhynVPHcpE40eiPo6v8Ho6yZKXpV5klCKciodXAORsswSoGJa -N3nnu/ECgYEA6Yb2rM3QUEPIALdL8f/OzZ1GBSdiQB2WSAxzl9pR/dLF2H+0pitS -to0830mk92ppVmRVD3JGxYDRZQ56tlFXyGaCzJBMRIcsotAhBoNbjV0i9n5bLJYf -BmjU9yvWcgsTt0tr3B0FrtYyp2tCvwHqlxvFpFdUCj2oRw2uGpkhmNkCgYEA03M6 -WxFhsix3y6eVCVvShfbLBSOqp8l0qiTEty+dgVQcWN4CO/5eyaZXKxlCG9KMmKxy -Yx+YgxZrDhfaZ0cxhHGPRKEAxM3IKwT2C8/wCaSiLWXZZpTifnSD99vtOt4wEfrG -+AghNd5kamFiM9tU0AyvhJc2vdJFuXrfeC7ntM8CgYBGDA+t4cZcbRhu7ow/OKYF -kulP3nJgHP/Y+LMrl3cEldZ2jEfZmCElVNQvfd2XwTl7injhOzvzPiKRF3jDez7D -g8w0JAxceddvttJRK9GoY4l7OoeKpjUELSnEQkf+yUfOsTbXPXVY7jMfeNL6jE6b -qN7t3qv8rmXtejMBE3G6cQKBgGR5W2BMiRSlxqKx1cKlrApV87BUe1HRCyuR3xuA -d6Item7Lx1oEi7vb242yKdSYnpApWQ06xTh83Y/Ly87JaIEbiM0+h+P8OEIg0F1a -iB+86AcUX1I8KseVy+Np0HbpfwP8GrFfA5DaRPK7pXMopEtby8cAJ1XZZaI1/ZvZ -BebHAoGAcQU9WvCkT+nIp9FpXfBybYUsvgkaizMIqp66/l3GYgYAq8p1VLGvN4v5 -ec0dW58SJrCpqsM3NP78DtEzQf9OOsk+FsjBFzDU2RkeUreyt2/nQBj/2mN/+hEy -hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg= ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTA4MTIwNzEwMjUyMloXDTE4MTIwNTEwMjUyMlowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMDjWizj+xHXoKo0bkCkg187x5hTGXwbn44RC4TY6OSrC+Inh4TEhgnElest9oc4 -akeZb01YmkHs/sYXOfDWUbvjlIBIaHUQVv7wDo6c/8XTM+R2ghIT9xPVtaZIrVbH -kvAea64CaNQXwhmotXz2r9Z7rT6tio+7zMtuPoOOtC6J3+pZ9XYuGkyEbQKl7VFO -kRaTyT9+T5Al20yuuTvByUscbf17X6HsxwlOflCMJmRmMeOlAVs4NyHyumxj0oh1 -N6XYk6JdLjD7fxlCvseDcmSePyJrDQInEcDAXY2uMsBylyXoR4FwbYbFSB2y9tcf -uIm7IPXlTP14qE1erVtyK3cCAwEAATANBgkqhkiG9w0BAQQFAAOCAQEAW4yZdqpB -oIdiuXRosr86Sg9FiMg/cn+2OwQ0QIaA8ZBwKsc+wIIHEgXCS8J6316BGQeUvMD+ -plNe0r4GWzzmlDMdobeQ5arPRB89qd9skE6pAMdLg3FyyfEjz3A0VpskolW5VBMr -P5R7uJ1FLgH12RyAjZCWYcCRqEMOffqvyMCH6oAjyDmQOA5IssRKX/HsHntSH/HW -W7slTcP45ty1b44Nq22/ubYk0CJRQgqKOIQ3cLgPomN1jNFQbAbfVTaK1DpEysrQ -5V8a8gNW+3sVZmV6d1Mj3pN2Le62wUKuV2g6BNU7iiwcoY8HI68aRxz2hVMS+t5f -SEGI4JSxV56lYg== ------END CERTIFICATE----- ------BEGIN DH PARAMETERS----- -MEYCQQD+ef8hZ4XbdoyIpJyCTF2UrUEfX6mYDvxuS5O1UNYcslUqlj6JkA11e/yS -6DK8Z86W6mSj5CEk4IjbyEOECXH7AgEC ------END DH PARAMETERS----- diff --git a/3rdparty/mongoose/examples/restful_api/Makefile b/3rdparty/mongoose/examples/restful_api/Makefile deleted file mode 100644 index 97fcf3f93db..00000000000 --- a/3rdparty/mongoose/examples/restful_api/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = restful_api -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/restful_api/index.html b/3rdparty/mongoose/examples/restful_api/index.html deleted file mode 100644 index 9051ff08ceb..00000000000 --- a/3rdparty/mongoose/examples/restful_api/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - RESTful API demo - - - - - - - -
-

RESTful API demo.

- -

- This page demonstrates how Mongoose web server could be used to implement - RESTful APIs. Enter numbers below, and press Submit. Browser will send - two numbers to /api/sum URI, Mongoose calclulates the sum of - two and returns the result. -

- -
- -
- -
-   -
- -
- - diff --git a/3rdparty/mongoose/examples/restful_api/restful_api.c b/3rdparty/mongoose/examples/restful_api/restful_api.c deleted file mode 100644 index ff0ac83a9f3..00000000000 --- a/3rdparty/mongoose/examples/restful_api/restful_api.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include "mongoose.h" - -static const char *s_no_cache_header = - "Cache-Control: max-age=0, post-check=0, " - "pre-check=0, no-store, no-cache, must-revalidate\r\n"; - -static void handle_restful_call(struct mg_connection *conn) { - char n1[100], n2[100]; - - // Get form variables - mg_get_var(conn, "n1", n1, sizeof(n1)); - mg_get_var(conn, "n2", n2, sizeof(n2)); - - mg_printf_data(conn, "{ \"result\": %lf }", strtod(n1, NULL) + strtod(n2, NULL)); -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: - if (!strcmp(conn->uri, "/api/sum")) { - handle_restful_call(conn); - return MG_TRUE; - } - mg_send_file(conn, "index.html", s_no_cache_header); - return MG_MORE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8000"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/send_file/Makefile b/3rdparty/mongoose/examples/send_file/Makefile deleted file mode 100644 index 4c20d6ac4b6..00000000000 --- a/3rdparty/mongoose/examples/send_file/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = send_file -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - wine $(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/3rdparty/mongoose/examples/send_file/send_file.c b/3rdparty/mongoose/examples/send_file/send_file.c deleted file mode 100644 index 345c3af694b..00000000000 --- a/3rdparty/mongoose/examples/send_file/send_file.c +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates how to send arbitrary files to the client. - -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_REQUEST: - mg_send_file(conn, "send_file.c", NULL); // Also could be a dir, or CGI - return MG_MORE; // It is important to return MG_MORE after mg_send_file! - case MG_AUTH: return MG_TRUE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) mg_poll_server(server, 1000); - mg_destroy_server(&server); - - return 0; -} diff --git a/3rdparty/mongoose/examples/web_server/Makefile b/3rdparty/mongoose/examples/web_server/Makefile deleted file mode 100644 index 4f9eacb6d06..00000000000 --- a/3rdparty/mongoose/examples/web_server/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = web_server -CFLAGS = -W -Wall -I../.. -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c -OPENSSL_FLAGS = -DNS_ENABLE_SSL -lssl - -# PolarSSL paths and flags -POLARSSL_PATH = /usr/local -POLARSSLCOMPAT_PATH = ./../../../polar -SOURCES_POLAR = $(SOURCES) $(POLARSSLCOMPAT_PATH)/polarssl_compat.c -INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include -LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls -CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR) -DNS_ENABLE_SSL - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -$(PROG).exe: $(SOURCES) - cl -Fo $(PROG) $(SOURCES) -nologo -MD -I../.. - -openssl: - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) $(OPENSSL_FLAGS) - -polarssl: - $(CC) -o $(PROG) $(SOURCES_POLAR) $(LDFLAGS_POLAR) $(CFLAGS_POLAR) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/web_server/certs/cert.pem b/3rdparty/mongoose/examples/web_server/certs/cert.pem deleted file mode 100644 index f191e3c10a6..00000000000 --- a/3rdparty/mongoose/examples/web_server/certs/cert.pem +++ /dev/null @@ -1,46 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC+zCCAeOgAwIBAgIJAPhB8jbL+G82MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV -BAMMCTEyNy4wLjAuMTAeFw0xNTAzMDYxMjQzMzNaFw0yNTAzMDMxMjQzMzNaMBQx -EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALi3b3daMgzUEROKob1Caf68i+//cTRkPdBJv2cOBak21CdQzY0Nvx73GLzf -5TKB347BCHNbYRKGJXDbYdmFp20/WeBHkY7RS3Ad2Q5lzyx66u9PxNx7hJIiqBgF -58VU+E3o/I+o8QNIoOT+wtCiq3Nwkp+zGBJmS32rzMEV9bcKxSzMrkfRhF+XAREd -DwM9vfPg6WRb/b+vv06uvVwcw390RprLautGfBdaRddVYkIAKJGRRTqZAvTRFW1J -FcIVOxlN+iA7qP7xjr3tUP78qMmlu0MXsHrUR2cgfveZK2sdUW5G804yHsU5sC8l -FbtLKMEOyLsk2bEIScOXgum7g2sCAwEAAaNQME4wHQYDVR0OBBYEFHtLzUqAsXkH -Il8S5sMhJuVhRJLdMB8GA1UdIwQYMBaAFHtLzUqAsXkHIl8S5sMhJuVhRJLdMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEzHc0AOr+qs0OFvWMfcSMi7 -O/aYlLS6f7Sos+lli69+61EcmCTJVarVeAVUsAoqmzBKDbeOpAK1hGX6/GGcXjR2 -BmuU0hUKyX9l1lwdMKU45BayH/riElwnvAyj2GxKoPpdIjlHns4SAITOCUx9NfpM -agd7kjolton0ZQ5DI/2a43PkqHv1lY4Dp60wJlxit9U68bsGOycCJ/BsAyrPROb2 -D1MkpMBIdfHc8uxRywM3/l9buFX8yrrMUGOYKgfjDwdzbj0iwIixoGpHL7IfeBtu -dvGO/g2rEhbtAP+xIgOR3GvzqjZh30er3no7zjDMn65tTME18Aq3tBQY7vPDKms= ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4t293WjIM1BET -iqG9Qmn+vIvv/3E0ZD3QSb9nDgWpNtQnUM2NDb8e9xi83+Uygd+OwQhzW2EShiVw -22HZhadtP1ngR5GO0UtwHdkOZc8seurvT8Tce4SSIqgYBefFVPhN6PyPqPEDSKDk -/sLQoqtzcJKfsxgSZkt9q8zBFfW3CsUszK5H0YRflwERHQ8DPb3z4OlkW/2/r79O -rr1cHMN/dEaay2rrRnwXWkXXVWJCACiRkUU6mQL00RVtSRXCFTsZTfogO6j+8Y69 -7VD+/KjJpbtDF7B61EdnIH73mStrHVFuRvNOMh7FObAvJRW7SyjBDsi7JNmxCEnD -l4Lpu4NrAgMBAAECggEAaFuqbAHXOQwuwZ2XFzgIblTTsrncmT7w9VZU/sIbTKif -X771AnX7vmDX5w2PjeN2DE7emV3NEAwd5w7qz1wFZWFfQ6jrgYaZWjRixxGZ5IVl -aeLlU7OtCGrwEPJ1KTWCO3IgDoHh+Hr1+6o7Imhk+QlmrTcfqHWGvO9s9MGVWt2S -RLAnSTFiOe5brdJnmlqq1sKZmnLmpydBaPUOYpZGAgRasrjdMZB+lZOazd1x23/5 -GAcm0rDREMnO9b2Jt+TNEZHT6d5KpVoExztZEZj8QCLXoic/SpFIqHGtpNlQXa+d -BVqgQbIYjO8ldldxZ8YIyJDVF+9e/uBBwu6jBIIsEQKBgQDspEHCyyuh4LG+7BbZ -eXlsfCxPTM6K9w31ZwHAwRtAuGqrOrE+pFJG9CEsFZbAI1aOGmZZdjexuSMcOlXl -TIVJTQHoFtoGEsanYEXO4O1t02Ab/DCYSpXusXUraRBRPpsTC77Sh5mxLUNd23d9 -NhnDBuwChAmC+IYexjkXeqPYFwKBgQDH08PEd+2PVo4MD8UVKUlEcgoyCr6ESiyp -HfYyhhfd5x3DbZLoKCkunDfBs/hakQk8DA2nn4tl4ZjfmzXmX0EBx+E5YTdYshW7 -ZcjN5x64B5PEOAR/NZA6agNlp3XGXXXgX+gnN6pgE49eVU22nZ4G+QBKD6NcCviB -LBPUxMbvzQKBgHgZYRqonGtaqzsXfP1AjmSFnMNeWtDiU95BOf2Gw/sT3WcrsXr2 -UJ+cFR3XkxvOk4YpVdp/igKT0ILqBGAMdvTdtWMB/gLpEpMt5B/7veRoS7XIRy1z -ZSawP6QZfWOOX4vKAT29/j2SmEcRNFKC245EfBFGy8EBuqfxuFX3MyJfAoGBAJ0y -tjsErVmpma1baosvI3g4zlR3p1CimWehLmCopHXorr1iocMIdP0535L+ZU258y3N -vaA0HpFTW9PsYgaMwLMJ7uAY3lVkIzx84e849i2HqHMgLkl0dbW+WFXL2xblxylv -yU2wuNNED/EB4lTawcpycAvTKYvrBXt4lVE4S9exAoGAGl6vZV3zyw4jpIw4uDfk -LTPYUrghFDDGKExyeOnC/W9pqR2veqzfBz02C3jqwhewoqgAcnNc2sg0rJmM+6Oz -Z2mmGZTHO9xR++7+W7e8AkQBbS6TB8a+7yNcM4USLP+b9sX5N+8gFhFs9tG7j/no -G44qLsJ/yve7/QsOA37uEMs= ------END PRIVATE KEY----- diff --git a/3rdparty/mongoose/examples/web_server/web_server.c b/3rdparty/mongoose/examples/web_server/web_server.c deleted file mode 100644 index 4d256a8fedf..00000000000 --- a/3rdparty/mongoose/examples/web_server/web_server.c +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright (c) 2004-2013 Sergey Lyubka -// Copyright (c) 2013-2014 Cesanta Software Limited - -#undef UNICODE // Use ANSI WinAPI functions -#undef _UNICODE // Use multibyte encoding on Windows -#define _MBCS // Use multibyte encoding on Windows -#define _WIN32_WINNT 0x500 // Enable MIIM_BITMAP -#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005 -#define _XOPEN_SOURCE 600 // For PATH_MAX on linux -#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mongoose.h" - -#ifdef _WIN32 -#include -#include // For chdir() -#include -#include - -#ifndef PATH_MAX -#define PATH_MAX MAX_PATH -#endif - -#ifndef S_ISDIR -#define S_ISDIR(x) ((x) & _S_IFDIR) -#endif - -#define DIRSEP '\\' -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#ifndef sleep -#define sleep(x) Sleep((x) * 1000) -#endif -#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size)) -#define SIGCHLD 0 -typedef struct _stat file_stat_t; -#define stat(x, y) _stat((x), (y)) -#else -typedef struct stat file_stat_t; -#include -#include - -#ifdef IOS -#include -#endif - -#define DIRSEP '/' -#define __cdecl -#define abs_path(rel, abs, abs_size) realpath((rel), (abs)) -#endif // _WIN32 - -#define MAX_OPTIONS 100 -#define MAX_CONF_FILE_LINE_SIZE (8 * 1024) - -#ifndef MVER -#define MVER MONGOOSE_VERSION -#endif - -static int exit_flag; -static char server_name[50]; // Set by init_server_name() -static char s_config_file[PATH_MAX]; // Set by process_command_line_arguments -static struct mg_server *server; // Set by start_mongoose() -static const char *s_default_document_root = "."; -static const char *s_default_listening_port = "8080"; -static char **s_argv = { NULL }; - -static void set_options(char *argv[]); - -#if !defined(CONFIG_FILE) -#define CONFIG_FILE "mongoose.conf" -#endif /* !CONFIG_FILE */ - -static void __cdecl signal_handler(int sig_num) { - // Reinstantiate signal handler - signal(sig_num, signal_handler); - -#ifndef _WIN32 - // Do not do the trick with ignoring SIGCHLD, cause not all OSes (e.g. QNX) - // reap zombies if SIGCHLD is ignored. On QNX, for example, waitpid() - // fails if SIGCHLD is ignored, making system() non-functional. - if (sig_num == SIGCHLD) { - do {} while (waitpid(-1, &sig_num, WNOHANG) > 0); - } else -#endif - { exit_flag = sig_num; } -} - -static void vnotify(const char *fmt, va_list ap, int must_exit) { - vfprintf(stderr, fmt, ap); - fputc('\n', stderr); - if (must_exit) { - exit(EXIT_FAILURE); - } -} - -static void notify(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vnotify(fmt, ap, 0); - va_end(ap); -} - -static void die(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vnotify(fmt, ap, 1); - va_end(ap); -} - -static void show_usage_and_exit(void) { - const char **names; - int i; - - fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n", - MVER, __DATE__); - fprintf(stderr, "Usage:\n"); -#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM) - fprintf(stderr, " mongoose -A \n"); -#endif - fprintf(stderr, " mongoose [config_file]\n"); - fprintf(stderr, " mongoose [-option value ...]\n"); - fprintf(stderr, "\nOPTIONS:\n"); - - names = mg_get_valid_option_names(); - for (i = 0; names[i] != NULL; i += 2) { - fprintf(stderr, " -%s %s\n", - names[i], names[i + 1] == NULL ? "" : names[i + 1]); - } - exit(EXIT_FAILURE); -} - -#define EV_HANDLER NULL - -static char *sdup(const char *str) { - char *p; - if ((p = (char *) malloc(strlen(str) + 1)) != NULL) { - strcpy(p, str); - } - return p; -} - -static void set_option(char **options, const char *name, const char *value) { - int i; - - for (i = 0; i < MAX_OPTIONS - 3; i++) { - if (options[i] == NULL) { - options[i] = sdup(name); - options[i + 1] = sdup(value); - options[i + 2] = NULL; - break; - } else if (!strcmp(options[i], name)) { - free(options[i + 1]); - options[i + 1] = sdup(value); - break; - } - } - - if (i == MAX_OPTIONS - 3) { - die("%s", "Too many options specified"); - } -} - -static void process_command_line_arguments(char *argv[], char **options) { - char line[MAX_CONF_FILE_LINE_SIZE], opt[sizeof(line)], val[sizeof(line)], - *p, cpath[PATH_MAX]; - FILE *fp = NULL; - size_t i, cmd_line_opts_start = 1, line_no = 0; - - // Should we use a config file ? - if (argv[1] != NULL && argv[1][0] != '-') { - snprintf(cpath, sizeof(cpath), "%s", argv[1]); - cmd_line_opts_start = 2; - } else if ((p = strrchr(argv[0], DIRSEP)) == NULL) { - // No command line flags specified. Look where binary lives - snprintf(cpath, sizeof(cpath), "%s", CONFIG_FILE); - } else { - snprintf(cpath, sizeof(cpath), "%.*s%c%s", - (int) (p - argv[0]), argv[0], DIRSEP, CONFIG_FILE); - } - abs_path(cpath, s_config_file, sizeof(s_config_file)); - - fp = fopen(s_config_file, "r"); - - // If config file was set in command line and open failed, die - if (cmd_line_opts_start == 2 && fp == NULL) { - die("Cannot open config file %s: %s", s_config_file, strerror(errno)); - } - - // Load config file settings first - if (fp != NULL) { - fprintf(stderr, "Loading config file %s\n", s_config_file); - - // Loop over the lines in config file - while (fgets(line, sizeof(line), fp) != NULL) { - line_no++; - - // Ignore empty lines and comments - for (i = 0; isspace(* (unsigned char *) &line[i]); ) i++; - if (line[i] == '#' || line[i] == '\0') { - continue; - } - - if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) { - printf("%s: line %d is invalid, ignoring it:\n %s", - s_config_file, (int) line_no, line); - } else { - set_option(options, opt, val); - } - } - - fclose(fp); - } - - // If we're under MacOS and started by launchd, then the second - // argument is process serial number, -psn_..... - // In this case, don't process arguments at all. - if (argv[1] == NULL || memcmp(argv[1], "-psn_", 5) != 0) { - // Handle command line flags. - // They override config file and default settings. - for (i = cmd_line_opts_start; argv[i] != NULL; i += 2) { - if (argv[i][0] != '-' || argv[i + 1] == NULL) { - show_usage_and_exit(); - } - set_option(options, &argv[i][1], argv[i + 1]); - } - } -} - -static void init_server_name(void) { - const char *descr = ""; - snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s%s", - MVER, descr); -} - -static int is_path_absolute(const char *path) { -#ifdef _WIN32 - return path != NULL && - ((path[0] == '\\' && path[1] == '\\') || // UNC path, e.g. \\server\dir - (isalpha(path[0]) && path[1] == ':' && path[2] == '\\')); // E.g. X:\dir -#else - return path != NULL && path[0] == '/'; -#endif -} - -static char *get_option(char **options, const char *option_name) { - int i; - - for (i = 0; options[i] != NULL; i++) - if (!strcmp(options[i], option_name)) - return options[i + 1]; - - return NULL; -} - -static void *serving_thread_func(void *param) { - struct mg_server *srv = (struct mg_server *) param; - while (exit_flag == 0) { - mg_poll_server(srv, 1000); - } - return NULL; -} - -static int path_exists(const char *path, int is_dir) { - file_stat_t st; - return path == NULL || (stat(path, &st) == 0 && - ((S_ISDIR(st.st_mode) ? 1 : 0) == is_dir)); -} - -static void verify_existence(char **options, const char *name, int is_dir) { - const char *path = get_option(options, name); - if (!path_exists(path, is_dir)) { - notify("Invalid path for %s: [%s]: (%s). Make sure that path is either " - "absolute, or it is relative to mongoose executable.", - name, path, strerror(errno)); - } -} - -static void set_absolute_path(char *options[], const char *option_name) { - char path[PATH_MAX], abs[PATH_MAX], *option_value; - const char *p; - - // Check whether option is already set - option_value = get_option(options, option_name); - - // If option is already set and it is an absolute path, - // leave it as it is -- it's already absolute. - if (option_value != NULL && !is_path_absolute(option_value)) { - // Not absolute. Use the directory where mongoose executable lives - // be the relative directory for everything. - // Extract mongoose executable directory into path. - if ((p = strrchr(s_config_file, DIRSEP)) == NULL) { - getcwd(path, sizeof(path)); - } else { - snprintf(path, sizeof(path), "%.*s", (int) (p - s_config_file), - s_config_file); - } - - strncat(path, "/", sizeof(path) - 1); - strncat(path, option_value, sizeof(path) - 1); - - // Absolutize the path, and set the option - abs_path(path, abs, sizeof(abs)); - set_option(options, option_name, abs); - } -} - -#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM) -int modify_passwords_file(const char *fname, const char *domain, - const char *user, const char *pass) { - int found; - char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX]; - FILE *fp, *fp2; - - found = 0; - fp = fp2 = NULL; - - // Regard empty password as no password - remove user record. - if (pass != NULL && pass[0] == '\0') { - pass = NULL; - } - - (void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname); - - // Create the file if does not exist - if ((fp = fopen(fname, "a+")) != NULL) { - fclose(fp); - } - - // Open the given file and temporary file - if ((fp = fopen(fname, "r")) == NULL) { - return 0; - } else if ((fp2 = fopen(tmp, "w+")) == NULL) { - fclose(fp); - return 0; - } - - // Copy the stuff to temporary file - while (fgets(line, sizeof(line), fp) != NULL) { - if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) { - continue; - } - - if (!strcmp(u, user) && !strcmp(d, domain)) { - found++; - if (pass != NULL) { - mg_md5(ha1, user, ":", domain, ":", pass, NULL); - fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); - } - } else { - fprintf(fp2, "%s", line); - } - } - - // If new user, just add it - if (!found && pass != NULL) { - mg_md5(ha1, user, ":", domain, ":", pass, NULL); - fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); - } - - // Close files - fclose(fp); - fclose(fp2); - - // Put the temp file in place of real file - remove(fname); - rename(tmp, fname); - - return 1; -} -#endif - -static void start_mongoose(int argc, char *argv[]) { - s_argv = argv; - if ((server = mg_create_server(NULL, EV_HANDLER)) == NULL) { - die("%s", "Failed to start Mongoose."); - } - -#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM) - // Edit passwords file if -A option is specified - if (argc > 1 && !strcmp(argv[1], "-A")) { - if (argc != 6) { - show_usage_and_exit(); - } - exit(modify_passwords_file(argv[2], argv[3], argv[4], argv[5]) ? - EXIT_SUCCESS : EXIT_FAILURE); - } -#endif - - // Show usage if -h or --help options are specified - if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { - show_usage_and_exit(); - } - set_options(argv); -} - -static void set_options(char *argv[]) { - char *options[MAX_OPTIONS]; - int i; - - options[0] = NULL; - set_option(options, "document_root", s_default_document_root); - set_option(options, "listening_port", s_default_listening_port); - - // Update config based on command line arguments - process_command_line_arguments(argv, options); - - // Make sure we have absolute paths for files and directories - // https://github.com/valenok/mongoose/issues/181 - set_absolute_path(options, "document_root"); - set_absolute_path(options, "dav_auth_file"); - set_absolute_path(options, "cgi_interpreter"); - set_absolute_path(options, "access_log_file"); - set_absolute_path(options, "global_auth_file"); - set_absolute_path(options, "ssl_certificate"); - - if (!path_exists(get_option(options, "document_root"), 1)) { - set_option(options, "document_root", s_default_document_root); - set_absolute_path(options, "document_root"); - notify("Setting document_root to [%s]", - mg_get_option(server, "document_root")); - } - - // Make extra verification for certain options - verify_existence(options, "document_root", 1); - verify_existence(options, "cgi_interpreter", 0); - verify_existence(options, "ssl_certificate", 0); - - for (i = 0; options[i] != NULL; i += 2) { - const char *msg = mg_set_option(server, options[i], options[i + 1]); - if (msg != NULL) { - notify("Failed to set option [%s] to [%s]: %s", - options[i], options[i + 1], msg); - if (!strcmp(options[i], "listening_port")) { - mg_set_option(server, "listening_port", s_default_listening_port); - notify("Setting %s to [%s]", options[i], s_default_listening_port); - } - } - free(options[i]); - free(options[i + 1]); - } - - // Change current working directory to document root. This way, - // scripts can use relative paths. - chdir(mg_get_option(server, "document_root")); - -#if 0 - // Add an ability to pass listening socket to mongoose - { - const char *env = getenv("MONGOOSE_LISTENING_SOCKET"); - if (env != NULL && atoi(env) > 0 ) { - mg_set_listening_socket(server, atoi(env)); - } - } -#endif - - // Setup signal handler: quit on Ctrl-C - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); -#ifndef _WIN32 - signal(SIGCHLD, signal_handler); -#endif -} - -int main(int argc, char *argv[]) { - init_server_name(); - start_mongoose(argc, argv); - printf("%s serving [%s] on port %s\n", - server_name, mg_get_option(server, "document_root"), - mg_get_option(server, "listening_port")); - fflush(stdout); // Needed, Windows terminals might not be line-buffered - serving_thread_func(server); - printf("Exiting on signal %d ...", exit_flag); - fflush(stdout); - mg_destroy_server(&server); - printf("%s\n", " done."); - - return EXIT_SUCCESS; -} diff --git a/3rdparty/mongoose/examples/websocket_chat/Makefile b/3rdparty/mongoose/examples/websocket_chat/Makefile deleted file mode 100644 index 780276ef46b..00000000000 --- a/3rdparty/mongoose/examples/websocket_chat/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = websocket_chat -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/websocket_chat/index.html b/3rdparty/mongoose/examples/websocket_chat/index.html deleted file mode 100644 index 5da84d30775..00000000000 --- a/3rdparty/mongoose/examples/websocket_chat/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - WebSocket Test - - - - - - -
-

Websocket PubSub Demonstration

- -

- This page demonstrates how Mongoose web server could be used to implement - - publish–subscribe pattern. Open this page in several browser - windows. Each window initiates persistent - WebSocket - connection with Mongoose, making each browser window a websocket client. - Join a room, send messages, and see messages sent by other clients. -

- -

- My ID: -

-

- Join room: -

- -
-
- -

- - -

-
- - diff --git a/3rdparty/mongoose/examples/websocket_chat/websocket_chat.c b/3rdparty/mongoose/examples/websocket_chat/websocket_chat.c deleted file mode 100644 index 5ba53801017..00000000000 --- a/3rdparty/mongoose/examples/websocket_chat/websocket_chat.c +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2013-2014 Cesanta Software Limited -// $Date: 2014-09-09 17:07:55 UTC $ - -#include -#include -#include -#include -#include "mongoose.h" - -static int s_signal_received = 0; -static struct mg_server *s_server = NULL; - -// Data associated with each websocket connection -struct conn_data { - int room; -}; - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); // Reinstantiate signal handler - s_signal_received = sig_num; -} - -static void handle_websocket_message(struct mg_connection *conn) { - struct conn_data *d = (struct conn_data *) conn->connection_param; - struct mg_connection *c; - - printf("[%.*s]\n", (int) conn->content_len, conn->content); - if (conn->content_len > 5 && !memcmp(conn->content, "join ", 5)) { - // Client joined new room - d->room = conn->content[5]; - } else if (conn->content_len > 4 && !memcmp(conn->content, "msg ", 4) && - d->room != 0 && d->room != '?') { - // Client has sent a message. Push this message to all clients - // that are subscribed to the same room as client - for (c = mg_next(s_server, NULL); c != NULL; c = mg_next(s_server, c)) { - struct conn_data *d2 = (struct conn_data *) c->connection_param; - if (!c->is_websocket || d2->room != d->room) continue; - mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, "msg %c %p %.*s", - (char) d->room, conn, - conn->content_len - 4, conn->content + 4); - } - } -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_REQUEST: - if (conn->is_websocket) { - handle_websocket_message(conn); - return MG_TRUE; - } else { - mg_send_file(conn, "index.html", NULL); // Return MG_MORE after! - return MG_MORE; - } - case MG_WS_CONNECT: - // New websocket connection. Send connection ID back to the client. - conn->connection_param = calloc(1, sizeof(struct conn_data)); - mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "id %p", conn); - return MG_FALSE; - case MG_CLOSE: - free(conn->connection_param); - return MG_TRUE; - case MG_AUTH: - return MG_TRUE; - default: - return MG_FALSE; - } -} - -int main(void) { - s_server = mg_create_server(NULL, ev_handler); - mg_set_option(s_server, "listening_port", "8080"); - - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - printf("Started on port %s\n", mg_get_option(s_server, "listening_port")); - while (s_signal_received == 0) { - mg_poll_server(s_server, 100); - } - mg_destroy_server(&s_server); - return 0; -} diff --git a/3rdparty/mongoose/examples/websocket_echo_server/Makefile b/3rdparty/mongoose/examples/websocket_echo_server/Makefile deleted file mode 100644 index f6b132dc9c6..00000000000 --- a/3rdparty/mongoose/examples/websocket_echo_server/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = websocket_echo_server -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/websocket_echo_server/index.html b/3rdparty/mongoose/examples/websocket_echo_server/index.html deleted file mode 100644 index 84e7078a7cb..00000000000 --- a/3rdparty/mongoose/examples/websocket_echo_server/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - -WebSocket Test - - -

Mongoose WebSocket Test

- -
- diff --git a/3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c b/3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c deleted file mode 100644 index 9001a8a4c23..00000000000 --- a/3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2013-2014 Cesanta Software Limited -// $Date: 2014-09-09 17:07:55 UTC $ - -#include -#include -#include "mongoose.h" - -static void push_message(struct mg_server *server, time_t current_time) { - struct mg_connection *c; - char buf[20]; - int len = sprintf(buf, "%lu", (unsigned long) current_time); - - // Iterate over all connections, and push current time message to websocket ones. - for (c = mg_next(server, NULL); c != NULL; c = mg_next(server, c)) { - if (c->is_websocket) { - mg_websocket_write(c, 1, buf, len); - } - } -} - -static int send_reply(struct mg_connection *conn) { - if (conn->is_websocket) { - // This handler is called for each incoming websocket frame, one or more - // times for connection lifetime. - // Echo websocket data back to the client. - mg_websocket_write(conn, 1, conn->content, conn->content_len); - return conn->content_len == 4 && !memcmp(conn->content, "exit", 4) ? - MG_FALSE : MG_TRUE; - } else { - mg_send_file(conn, "index.html", NULL); - return MG_MORE; - } -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: return send_reply(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - time_t current_timer = 0, last_timer = time(NULL); - - mg_set_option(server, "listening_port", "8080"); - - printf("Started on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 100); - current_timer = time(NULL); - if (current_timer - last_timer > 0) { - last_timer = current_timer; - push_message(server, current_timer); - } - } - - mg_destroy_server(&server); - return 0; -} diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile b/3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile deleted file mode 100644 index 968f1aca066..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = ws_ssl -CFLAGS = -W -Wall -I../.. -I. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS -DNS_ENABLE_SSL -DSSL_WRAPPER_USE_AS_LIBRARY $(CFLAGS_EXTRA) -LDFLAGS = -lssl -SOURCES = ws_ssl.c ../../mongoose.c ssl_wrapper.c - -# PolarSSL paths and flags -POLARSSL_PATH = /usr/local -POLARSSLCOMPAT_PATH = ./../../../polar -SOURCES_POLAR = $(SOURCES) $(POLARSSLCOMPAT_PATH)/polarssl_compat.c -INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include -LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls -CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR) -# - -all: $(PROG) - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(LDFLAGS) $(CFLAGS) - -polarssl: $(SOURCES_POLAR) - $(CC) -o $(PROG) $(SOURCES_POLAR) $(LDFLAGS_POLAR) $(CFLAGS_POLAR) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem deleted file mode 100644 index ebc7d8fd5eb..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAwizPnrCx+/kPSdEeSJFLDXrBH+cSQsSLrCm99G1hCjzqSlIk -1BhkZMEHxBaiVLky4+M/nwhjwwRHI10h6U2Or3tbPLv7z94cPf+uCx1aF7TE3Fm3 -6YnDk+CjrYVFN5GRPGOPPdFxGoc+vFvQJyAAimvchnS1ZoEQFvermwzOnKspA6gc -Px+7wnOeju9TyJuDr5ngtDXFnkcpkBNPxz3En4MJY4xJiaueafh9pIES2vSl7uP0 -J/qot9v2rdiL7nt1H1vwseeEkZhQ+NLB5e2z4psyktJcwDX7wQ6j7JnKfHeP+ixO -TUORgV4foBMVOqo//Guo92Q5HoLNK77V0y4+ZQIDAQABAoIBAGEsx+LlDs3JQQty -KjOq8uKWElyC6bKcZkIMydGvg6b6AU6ceW3jnyqFJ/vMUAUSghNmQQq3yiVo2Kks -DLKTa9sKYwisE0NeJsgoUtOhJttCTlrwU4f+t/AjtgY68f7zTLnqIV+Ql4ftM0pU -sIFEFMExZbWsZrQb1w+Hd0wrRqNEbSOfSjHeigvuw1T3GH2tSBUTGTpcoewCzy7U -PKS5pkYyiKySQQNqZTac3NHPjxdK6xxzwURZp1irKdiPdt04KHLVLX8KXelt/J0k -AeYkVbpFIeQ9rNBerMEp6uRBt+nE5mvP+xx1XPqKRxuxbMyTnBXeOM2zS/a/dBiz -fwokwcECgYEA9RSsv9AQ/AR8tt+aPEQvjhJ5pn/YbCb1DA9IDXpaq3tzacGd8JHj -3kUtb79nosu85LvSkAYmtzgfJs6xZyUkscra6q+xlsJ12QRxLzqfxcp9Y0wsdqM4 -AcOwuiPKrjkWxOQpyWPWRwbmAefLfRMekHt4Y/QY0CwhslpnsOsj3O0CgYEAytOE -8I4GBfSQfSjXwfrso++Oi75VSsl5ZeiMGihfEhYFTE8/3rEZf7nf9iFSkN3TT+7f -pFqQzddzPBZXlpVM6k1jcEjdpJizbeR8DmICpABFrZvKz1o8pQ2Yw+FYI86ih0x4 -806snMNgg/RgcVijXKFrC5joJOI+DVgwWoQyMFkCgYBxt4MkiV2oIkjf7ca6GgVa -zbXGjOGV5Umkq96J6nDxyplVw/IN8xOhScX4aP6kahaep4vfKguCzjaeIh/stS5e -lLqZVKZ5Roe6B7ag7HnAI+GkVm73KWrOXse8xui/iFvJRfkhqgJ9+HR3A9/GjD2N -Ws0Uy+lLhn6oLAya6bA9TQKBgAVfZP4aRP6TY+Bs3Io+41XUWqpI+GlqvNR+PHfU -6e/ItYs37jEv78T6X3xdlZpQxfAwG6x22a8aLetBjEBo5Aiw1Bl9VKGvidE3ZDHd -VsSRXUckAVNMyJ52pb1KktMf/h4nYGzRgLEGW+Ai8QsPlgQ2ImfEPSH8/DfORjmf -ltTBAoGBAMxIZ52DrJvuxogSOfA1MoCD6a90trkXCquvi+A/fXojZ8BHmMQshvhK -rAO7SDIV1i1Nh3jQ/oFWE8KOprqrOLO6jNTyF65vh+zk7ztGsEME9FkDhHasUiXf -t5PE9KeTChHRvIa4FGCl9We9GftE5Ii77LWMOIq22pyxYbvHQFEf ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIJAIOoO+AapJ5WMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNV -BAMTA3dzMTEMMAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVi -bGluMB4XDTE0MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMD -d3MxMQwwCgYDVQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZEdWJsaW4w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCLM+esLH7+Q9J0R5IkUsN -esEf5xJCxIusKb30bWEKPOpKUiTUGGRkwQfEFqJUuTLj4z+fCGPDBEcjXSHpTY6v -e1s8u/vP3hw9/64LHVoXtMTcWbfpicOT4KOthUU3kZE8Y4890XEahz68W9AnIACK -a9yGdLVmgRAW96ubDM6cqykDqBw/H7vCc56O71PIm4OvmeC0NcWeRymQE0/HPcSf -gwljjEmJq55p+H2kgRLa9KXu4/Qn+qi32/at2Ivue3UfW/Cx54SRmFD40sHl7bPi -mzKS0lzANfvBDqPsmcp8d4/6LE5NQ5GBXh+gExU6qj/8a6j3ZDkegs0rvtXTLj5l -AgMBAAGjgZwwgZkwHQYDVR0OBBYEFL54xAgtJTW6US4Mbr4QG0yKzvaxMGoGA1Ud -IwRjMGGAFL54xAgtJTW6US4Mbr4QG0yKzvaxoT6kPDA6MQwwCgYDVQQDEwN3czEx -DDAKBgNVBAoTA3dzMTELMAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1YmxpboIJAIOo -O+AapJ5WMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJz/RzMa9Wa2 -eEXed7ijH1gcWtgVsVT1xZo0ksFl+QJ5Be1AJpOIe8nKdzYjxPWUkofIoaGHdMLL -Uc/udRzsXncup+0mD+Yos6Cqyo9yHq7L1HbXfKYZtBXIjWHdF2+RP8j9tHfITXYI -Pb2zsQ+A6PYpp5OLGZTDAnI2qffqsmwXFNhPfFhOANrGlOjsvy1P7JDzvymj/90m -NomlO3vjxLHOf6MvedTgCB0dRcAoUWPgbxPWifjBmGBjQjA4ukMQ58wbBQgvIoCW -obrXmLCNZIkpWTw4gMRYquY880IYK/OuFNJH/dawxx/WzuVr7IdLmbFY15zf5TUb -ZpIpwqRCysg= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem deleted file mode 100644 index 82e99504cb8..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem +++ /dev/null @@ -1,45 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAwOp1RS9RnE8L5TszDPIOmpf/1pqb+ki99l/sGhqB/KZBKCuq -uoCc2VPK3PCByBE15/xJ7t691FnJfForI9DO5p2R0FPD6o357hqRsh0dJNBm0VgG -iNtLQ8lyYoE72HJbkgCAUZW4N0OBibOmvp/s3Fmr7rEjW5LmZxOtX+iULKIUZ0w6 -gJlM8G5QA1SuqndN0PbPx+RZKSXZCoJj+Nboqw03nyJUexzs+lynR9ITMziUaaVM -4rzG+P6joQAnUkDNydxo/d4tj4xaioZdKxWLYEbj2BUtOlJJydotWo2wcG85ONrT -Gw0ltR1vku1hidMm2QL30uGIL5SeqyE8TqWk4QIDAQABAoIBAQCxHtKauc45MA4g -4hCGAzvLTmETnRI2YlEfAoTYlpvf5pkOE8GFyI25r4gjACJ4GO0gWG9dBF7Pt7wZ -EwRmttEvxV3aIv5OvRnKNdSs7rQSV9D+xc4CGy1oSG1f6X2TxbMzQoiN32OqQa2O -S0Z94IFs8lu8JCDtc9tcqiFVXEmnC3RvJZOShWpsCsbmh5ue1Xed0MQQ47vt7Zt7 -I0cutvwSFJMsZkZUJp5+KjVNYo9TEJxVD3m2NJNJxBfBoRVHXNii3hUEHcTIdIAz -omtRwBU8AKgJirGIRo1h2ZFyubI8ScGOJWIiWMQvQqTHKiOaz3yUar1NSG+kFn0U -cj7s3FhdAoGBAOQbx8Jwhtp4iOkP6aW1nVTgiaTj4LMlyJZioFwgPFRIcA3oRHt9 -5SRetmgFZNvcuNw1udfeaObKmlzxwUruprwOpihgAQWJFTtOjQNrt2gsYuX4l3W6 -T46dO2W1pV+mW4A5gt0aqhLv7pCS4lpreNAqyHSPqcQWcCeiTzmp/LfDAoGBANiB -FQOTyMElR9OzKwmcGfIvnhUfJQwi5qNE3R+xXiP5x36a9HQBey5ri2lnBle0Ksr/ -G+RKoflmk1eFXVHN0w35yw0dVco//WE4vOknldNEnIT85k02ld8lDTa2Q/EJZtPH -un6zeU0Q2/4SZ/GXPssEZPlpPM7WtQzztlH3+sqLAoGBAKnhppvAgi4ippQsLa4j -29BiiSAsNiQ1d3XIbfUubL+4UvuIh7gQwp6biu1dVwgHEgWuXYHPOgDn0p51zaao -pbRYlJZtKVWeChnpHkv15NnIdL8grGwZHTbxElNlPIxHsM2GB1fzi8YeumUhf0In -2AnwUum8NIq8yzo5PxeK6ZNRAoGBAIEA2Q6ankJH/nZsCbbeJq+iI+Wd+ysyGI8s -Vz2tJ9Tz3iTYG9SLlWRhfF4/nw3fMqhmPa5Xsg+zSRQbSTGXHKz1LEISOq4aVtX5 -QscCaUnLVh//uRJE9iRSJX92NyGGYpjKJ5ubQSnkY9EOEpVnc2jwo2HhjPQKBzNC -fF53Dh5lAoGALwTN5uxrBZLPu4DtZkOosKkv4l+kzFoOjLJR4vA7ONBx2CSe9G7F -tSsH7lZS3b0mxBWjO90WhaSvtMWWrfqq8vrqmoTE795fYxNoLfCLK13W31aTDUsI -pQRJIL30MPvASbcFHN2MD2dXz2nQzY8C9lvtvap/krYiDKDU2L7+iP8= ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIC7DCCAdQCBRQHBXNHMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMTEM -MAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0 -MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMDd3MxMQwwCgYD -VQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA6nVFL1GcTwvlOzMM8g6al//Wmpv6SL32 -X+waGoH8pkEoK6q6gJzZU8rc8IHIETXn/Enu3r3UWcl8Wisj0M7mnZHQU8Pqjfnu -GpGyHR0k0GbRWAaI20tDyXJigTvYcluSAIBRlbg3Q4GJs6a+n+zcWavusSNbkuZn -E61f6JQsohRnTDqAmUzwblADVK6qd03Q9s/H5FkpJdkKgmP41uirDTefIlR7HOz6 -XKdH0hMzOJRppUzivMb4/qOhACdSQM3J3Gj93i2PjFqKhl0rFYtgRuPYFS06UknJ -2i1ajbBwbzk42tMbDSW1HW+S7WGJ0ybZAvfS4YgvlJ6rITxOpaThAgMBAAEwDQYJ -KoZIhvcNAQEFBQADggEBABPLmq6zKOMY0WRjtBoSymq6f+vXeEwtWCfVejdG6RlG -/PTdCKNvp3OL7FDnmQQ+r5rMs4+Os4fX/g315QFKXu01rqxmFb2XVNhhaECdUWtK -QP6ZoVZviUiDjhK6a+05aerPCJpkGy/lz0W6gmj4qhuAQbobxb6UbzqTRYY+ZwGk -+SI3TAVCdmXFlxN/M9b0DbmkseRG8GGFmyRYyRb84vbV6zemFI++5ROUT9zXT7ey -nYfFJvAAk5jJhY5UP2aMlVWYYa4jUZrrPLoiBLUuRrp67EKGebCH9mgCIf8ztNJF -fpuvcz++LUeRyTlAGDefe+FyHGIwFzIfZn39D7CaRvM= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem deleted file mode 100644 index 93ef657ec6f..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem +++ /dev/null @@ -1,45 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAyal0BZKRYd+Wpxv4MB8LjjgXv/MxSN5oSAKThlCZ/AWG0FEP -d4nrBACT2xUxwo+xbYl3joiwL/eCPAp6QNKRGhvXVOnSIFVSjKZWbdX+toqK9pDS -QMDTL4ZJvK6pLZXknyHjEr0PxZh22F7iS1+C8HxBPj0Xgg/u5/+jPhFPPZ1d5elv -4cm/z+xy6RjFlA80aIeK7dcWssOsOIPjUNFfmoYgR63ScZIlUZj6j8VX9oX7fJID -jumGajDxgD2nBWFbHcGKin6bz/wZ+OIhXOCDdY7oKuMW4JiBwbfBtedkQuQYS11s -PRFFYDLoZH59Ivcu0c4F2tomE86qM8THsI910wIDAQABAoIBAG55FAQRfO8/C0rU -eavy9eOdOvV+hltC66G3N5X3BcQYSvhHz89OkJ6KqnT0MWRCT5KQIhzFKK++SWwW -2U41jCPfaKEtzlzEIQrH/MUC3Byn3OSiBWxPteFtEWv5ytgcKzg52iljxQYcNc7m -e9WKpzKS/zLXSM+JZvlVA9p2pRA88kUZ/EE5H+FW3kHj5eGNqX+cxUVpL0VKTiLv -aXWjYotpmDJW/Rn9wRQethm6Gdx3bvo+LEVlJRELNq8NM5H/tZIVRzudJOgzsw5v -3OQGhfKB6Eg/vqSFoZxX6ApXDxmtaSO83B0kK550bDVv4sBnOExGjKCzybt04tet -KtLPPoECgYEA5WUD+mFL99sCX6pzIyUVlxp9eUhVy5nvhoF6u3mvhay2XsZUY0wy -+/qVqYSZTvuvJ6JSXc4iVIX8u/gj7914805AwujepIF/8E0AaXLBMndzDE4ze5S5 -2RHI7Cy4/3AWOcQ9wFFmUdSs7/6oAkcQtvzP40hGg3J2jAEhIdCqmbMCgYEA4Q0G -BYP9XeTdh0C+BcP9B5VUEC0jerYS8VqVqriB+9JfT3InI7K08sOG2DiQQBhAHuzL -RhCECU2a9j0+u5F5JNeY5m3IhU73Lw+lOlUkMaAO6x7JJEzhXhonE7Kv8fWygr/0 -OB7yzqz+YsWdQ2VOPZ88ntlAYE65vzcaVswZY2ECgYEAr7Gt2VA6Ei0A5Wq0Yr+d -iKz2WzUG2TkelqOG8B4kTDrbNz2qFp+fERV9GWgAz9i+75lIgqZF7vzsdL96LtYv -NBLEUURwegjhh5hCb4E/7bpFOLCQh9+CdHpFrHYYfzRHIZlnPmxZ9OTyS6J85bmu -WKjLRKXvs++wUkzvJmoesDcCgYEAkTOB6xUZ5/a+J4HSGI43NylVr4owFgBbgHVd -k2SwGPXGoM+aCSJINUmKOv9jsrbyyAEntfD5/7aegLlLPGHDs82WzTWP5tLoEOkb -ReOhEpOejHy0ckNYNQrSo5bqhkZsAogu3fa52jcrejbeHJnEPWX8CtFJA9pHZeP7 -jnzo9IECgYBefHg0dymSj2xxN0XmC+S5cvQu2K/NYUpatoWvHnPiQ87wIM0AWz0O -D0ghEI+Ze57NbtSrrcTE7hY/LHrAqXGAB9XNIM5g9Pp/lM+XjzKVr1FMf4xpuHf1 -VJJRHrOU14CvMvKbgbPrL6B0d5yrYmeex7GxNw0ZVvtjCa502Eck+w== ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIC7DCCAdQCBRQHBXNGMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMTEM -MAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0 -MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMDd3MxMQwwCgYD -VQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJqXQFkpFh35anG/gwHwuOOBe/8zFI3mhI -ApOGUJn8BYbQUQ93iesEAJPbFTHCj7FtiXeOiLAv94I8CnpA0pEaG9dU6dIgVVKM -plZt1f62ior2kNJAwNMvhkm8rqktleSfIeMSvQ/FmHbYXuJLX4LwfEE+PReCD+7n -/6M+EU89nV3l6W/hyb/P7HLpGMWUDzRoh4rt1xayw6w4g+NQ0V+ahiBHrdJxkiVR -mPqPxVf2hft8kgOO6YZqMPGAPacFYVsdwYqKfpvP/Bn44iFc4IN1jugq4xbgmIHB -t8G152RC5BhLXWw9EUVgMuhkfn0i9y7RzgXa2iYTzqozxMewj3XTAgMBAAEwDQYJ -KoZIhvcNAQEFBQADggEBAE20gAykuuaCoP49GnZ/Z6ZItFry4Fl6iCWBDdEsWI9R -wRNYumeaeejdFPXfSJdTT7UlrVK1WWGLQLq+ixHRDX+V9T67ou85F92H/OxbUoPr -iz/TZAEBTC1GvTJl49lsfPl1dTWH8T4Ej2hxCUvIJrkCkI2Ov4Wwef6A26USrwBt -S/CPInjCe6qkE5E8xfTDl8k5IIgMadTPhi5sbV2piBJoN4floJPqR0hdDKbgUymn -5WNSiRkuI6UIDZwQEp+A8TmFBHbSwfTGt2Sz5iI27P8J6pFvR5eRA1k57dRUWNXC -WAU1nqteP3QAjj9L3o8IO0T62scaiJX8x01gTmVVe2I= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem deleted file mode 100644 index 9345a94a60a..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAwXIMpHuTNsro2pxe6y1mu27md2Olhvfx26rO3maO0/stIC2z -G/xQatFDLIWzfKFYOT0iSEj252ENFDCw6aDRKpiaUFtXcMAWkNkkKntEyoEgE45k -rTrvpay0v0B+ojwjA1Jz/9v35cgvDwTs3vNFno5HhI0m2YF4ocTmeHJ6u0xRL/qy -atfKsfuVq5s5CXOYCXp3Ux6kJ1c22J0EdZMvS75SVjAZgRkqQpqt9L3e2ZBCEgUr -w0KwlERvpeJF+sJJOshXjfrDzvwL8IpPnGZLJNINFbSJMk5MFGcMyq/28pSZLB9E -Dh8vk5D5gUnxM60ONUy2nYPcYr5p1PLDiC8hfQIDAQABAoIBAB0Twpi6xn8W8vdh -R9c75NRJsDTD8q6d+GnXe+7sJY3xlG/gzqpnO8NCn0FC+57BNdystsl8xjgzW17s -jrsfZDFt7MwlXrhg90NgkFIeY1G5JRQrdDChykHx+t1AmYhTV8P5EdykuNd+RqyQ -RfahRJa3tkJTYUKSdoqCaU4zjwU2CSxltuJx24V+WoZE12EwewJ8HPg2XTnbsGE7 -Fnx5s29O4ItM70CC0536AY/OgfuPix5z573VQiilqqfOQkVkKa1fHd6tGpWU+3kH -X9FnhEBf9cN9tVgmaB0sCSVVrfgqSXg1EwKHqe/+FCumuesA68Q35+/K3b+QrNiR -ka2yliECgYEA+V/4pbgG/lPYvTwWhKxGXXdJmrSPgZC0mwE+fRuYkeptbIkS0pwt -/UDTXk9nttj1f1ZJ3NgQbT/1w8jpXfsCJ8VeGzL9+ADhRKWVFRlu/nyFCMXawLEV -rot7SEr8BW/m8moHgY5lYipM3dXJPk0F+KLrN60U/aNmFUtPGW802BkCgYEAxpWy -FGL2sEQ0QaRDTcqqF5faVqw+5rVGvN+EX5o26E0QWWnoo3L2c2/5X93iBl+Fqtnm -9jSIQUC3rYOawKnZ/HcIE2ergFit/p6JaV9NiLDRtDUmSzlffEGVCj0neYFsnWp5 -zcmkUyZ6fr19EmKQWfdteNBlXue32TjVlFbfUQUCgYAfMbgi0sBdNBPaqBeRBRPQ -QUm9xnRlGrrc4Oz2LWuKZS7G8uad3deK5H8MPxaUMtOS2DJpI8X6RJPzp8A5d1qv -quq4sEpAqauEMMpTV1khEGZ70HQqwnwZ12zWgDrCW1siW80QkcVw4CW5YjLITk4+ -6fJOhqInkDcG1uLQJa8QkQKBgQCfs8l4DbJ4RRGFbLXXvNGXkb68j18yqLxPrq3F -OL9JiJhKYBsAP7clVPrG9ykLmQxlP0I35D1jxMkymLD+mlo9Z/itqmTJHggnyZWW -kVdIQ3MSKuA2BNjek9tpVY8Gb2hLHFMChVRKrpo6jOclvvB5+bsnOukbLtyyq7tP -xaFohQKBgByCmlltjOBWZLFLeA1x8j3inm9zM/FAJuANbHUOZ1RwrRcNFbDv/FXm -rLPnPCaH5AwAWhVRJcNHo37Ee0s/xqe+Q4dG4xL943k+6KlopAw1SXhuXF6PnBfF -y+ArVlh9d2oWN5cBEzRddnWnKJuMi70kMzYf6dIW9s/dHbq/gFDy ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIJAJDtcXU2wiJIMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNV -BAMTA3dzMjEMMAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVi -bGluMB4XDTE0MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMD -d3MyMQwwCgYDVQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZEdWJsaW4w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBcgyke5M2yujanF7rLWa7 -buZ3Y6WG9/Hbqs7eZo7T+y0gLbMb/FBq0UMshbN8oVg5PSJISPbnYQ0UMLDpoNEq -mJpQW1dwwBaQ2SQqe0TKgSATjmStOu+lrLS/QH6iPCMDUnP/2/flyC8PBOze80We -jkeEjSbZgXihxOZ4cnq7TFEv+rJq18qx+5WrmzkJc5gJendTHqQnVzbYnQR1ky9L -vlJWMBmBGSpCmq30vd7ZkEISBSvDQrCURG+l4kX6wkk6yFeN+sPO/Avwik+cZksk -0g0VtIkyTkwUZwzKr/bylJksH0QOHy+TkPmBSfEzrQ41TLadg9xivmnU8sOILyF9 -AgMBAAGjgZwwgZkwHQYDVR0OBBYEFLK4flD5QD/mRufsPx63xlEKM8pwMGoGA1Ud -IwRjMGGAFLK4flD5QD/mRufsPx63xlEKM8pwoT6kPDA6MQwwCgYDVQQDEwN3czIx -DDAKBgNVBAoTA3dzMjELMAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1YmxpboIJAJDt -cXU2wiJIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEYD+CReikYr -Rzvk+/Vdi/7IcaH9CFknIdtineSIw1y98nxnbnNJqxwfNaRblbYvg6OFdUI3POuI -+rdYLCFl8z3tWqRHLkGqHSJA9xcng3jLJxz0+ctiVcekJvXaB3O6eSZjhGbmmI/s -CQhdy2zpEIVOeUq50DrSJp9CknyGu/IkaGx5GOZtkiHMrpig50CRjX1lS6qrMNYp -vB8gfuqpjsL4Ar3vg+lgMSwNWXBNHrIRPHB5VEzBEdmLFZlvueR0ooEMCklpwX/a -lFImVc6JcY1pBEkHTiTLGMpGAHG3I1aVUaWb3L+V+2ym/KNRNL5C2+1eiqql5u8m -HUaOcNC90ew= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem deleted file mode 100644 index 8021de3c8a3..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem +++ /dev/null @@ -1,45 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA0ucemqFwBFziVOgTgx4mZII4WnGDpA/rWAGHvUZOqy2dQ3Pz -woGKxBaVPAl5kxEosROVGa7dTuq5yFZ4XIGvwCKxF30vCmdGCytqq6MMp904jG32 -KikkmjCApIMGxMO4eoBHZZxiyVvKTbg9M2CRXErwnYWhFH/qGdPnuo0CEaHJA4VK -A9incT9dpeEhU30R6ajAe/je9rCj2OMLMFSMfd51L/VYfO60zDwUNY7YVIghQZgJ -e44EVGsp1pXaqaD6o3PvGY3ohw2aZjJzlJ7MJHbKV9lft98R3pklbpBzMH849cEy -Q/51L/rlfTUgCpTy7wEZpWHQNtHfu/1rhJjpNQIDAQABAoIBAQCUNIHXG/dBuZv7 -GpMLotZL7w520Co30lAJqhmfMpb5x7YpvoPffXTsUwpQBECAzqAPv7kZMT6nxF8F -n245Y5EDrd1QqlGyN9yK4Nm2/39XPygL1wITopHsIIVmFgVdpEQxIZAKoZjx8yT4 -9K1dO1Eq0CbCKzOE2lbCC51eBNUdWZIMxwC6O/j/KoIkZ/HwlG2hpUuXg8x/XawA -ZJDCoTcWHCjYP10FxKVN3vAyWM2IM44o9IbsAGEOswR4gUwRsgq6Ehc1U59XUHi+ -x30oda55I1/8xD+SfP/zk2dDPHkv/hq5+258GU/THsw2+AAexocvSIS/g9EppTEg -biFaDKzJAoGBAPqey10JeyiOlHbBjoSSa7lJYUjocQANFQ4ayOAgfNX72iyabrKF -p9sVAeO/nM00+DPrm2wWws03ScsPeh+9BDJMPRBUHfSNp7+F+oyj7PWHBEFHbyO9 -5HnYZP+1vhdG2dYPIY2gRSFXpiGn3j0M1D0w9c7Ilm8ee3krdR4E/mw3AoGBANdu -EfS1dK3+m7sEgc2+3U32z83GpuCHeUIKGPYMLI0fIb1CPpboHU9YjOFJZH9iIIdl -00JC963O3+pqLe0XbMOmBVt9QjZfhfB+AY+JHtbPgoQVLtq9X/WvW7h3xn6S971r -Crkhqay3Cs4BzsgYDYraQCTw3oq4twR9Nuy4etfzAoGAXOsG5wWe3diO/sCggFJx -Eg88vHVBgA1ZoxMXKtGgtw1bRHI1XIblRvqw6qmeDw72fvl5dEe0DbXT7C9ezemc -ZrGRaj5lpMfoS7/2trIIJrfaQgGkGRJMZUhvmcbeJW8lUJHnlMS5HLWMaKn+YZAi -GFXQrMv9ylD44mHUWD7tvV0CgYBNctPfvvCQsQ05ofgsiKa1Jbs1hmpuJCYy2MB6 -jIvjvEJ78PnhdNc8tGAJikIoDZYWN0RI+RxkDxCvDLcwGpDOkbwxVQnd1F+pwxM6 -kBhXL8kDRT5QA28hO4bk/aKN1LZeEcKMJg8C+ddXkozNoOAVgDs5TKMlCh057u41 -EmmPgwKBgQDOlYi7fPYOCy0yjHMxSrp2SZOS06AMWGbbCoGkjRtvuP+FmKSNB+LZ -pOSEPJgzjsRutKjneww4LpV6dViAyTcP5JoeQpokHf7UVo7yq2QH/iwF3zJwsC/S -OuVLkqpZzWuye/QCH5NOTfw27ye8jG8VcQW2QPbcbkLXLM7zg2yX7g== ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIC7DCCAdQCBRQHBXNJMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMjEM -MAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0 -MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMDd3MyMQwwCgYD -VQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS5x6aoXAEXOJU6BODHiZkgjhacYOkD+tY -AYe9Rk6rLZ1Dc/PCgYrEFpU8CXmTESixE5UZrt1O6rnIVnhcga/AIrEXfS8KZ0YL -K2qrowyn3TiMbfYqKSSaMICkgwbEw7h6gEdlnGLJW8pNuD0zYJFcSvCdhaEUf+oZ -0+e6jQIRockDhUoD2KdxP12l4SFTfRHpqMB7+N72sKPY4wswVIx93nUv9Vh87rTM -PBQ1jthUiCFBmAl7jgRUaynWldqpoPqjc+8ZjeiHDZpmMnOUnswkdspX2V+33xHe -mSVukHMwfzj1wTJD/nUv+uV9NSAKlPLvARmlYdA20d+7/WuEmOk1AgMBAAEwDQYJ -KoZIhvcNAQEFBQADggEBACCCAJypO9DFU6GeOH+FwE0JCLTypHoIwERWxNL7xfjg -rwVqIxwAEo+fJjL+QY7JbAb/eqKaXIBYkAF2lFc4iEmecXX/A3Aqw95AYi78o7HD -MwRPqJha9mxLcCWwjX8XK8pT152BvYFPNhi+6jd++rDRxKDfmNvgdUQ2/YW6a5Wv -zEmLDPUWRIuMQIEmOa2/JhlllDviMExTw51nbqYgCghycRvDACyQAuu8re7P6gcg -bXObNlfxcU/8Ph6MFI+2S9ODtQ4BHyuKd4kRNsYn8vV42a0h3bCYSGPk3kSIgxd7 -XijwHT/o8E9ddH2BvDv+6Nhno9C6/MbezEOIs4nlhRk= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem b/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem deleted file mode 100644 index b6b48ef23f4..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem +++ /dev/null @@ -1,45 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA29iFnMf4pjty6knOt4wT0joPUlU2dGCFWxQ5Eg77Yx3Lou2a -FOzNGp7zLYH8gauOK+mgY+B9cBv8PvVtUQQKB0SKTTV8ZNKVyP3O5F2gRSJ+tHtT -FqaPfG0WPOn/f02YbOpAe6Rk+NnlJoeuBxG4uapUSq7r0mTGJQe+52y1LcMs23ID -ENBfDoUMVt5vCnF+cYK5ndeFVLyPO3JjohDH1zv3a9ECG28rtjKHLpNYFDsPJaD7 -UPuyyk3hIvfPCZoJOUlEVfpLT/lM+9oCPnq9PwIp5NqYofkuc3eKooCo7N4r4IlP -Ajktaao6b0ScNwNQB3leOIdEUFSIYy8N1JszVwIDAQABAoIBAFlIvjrGG/2m9yyf -fQyeHw6p9b8CTHNHH+G1fNgQrZe7ahBpXsJQyZueIjTBLcOb4MmEwFbPvSHiu7b2 -Bcd5VHlPJLvmlPZ9b8eJDJVCUOzC7aJu03fHfU6THwzuG42f/d9942JTiY5nL+FO -CSdl0xfUTRdnou53buFrG+TxCUPj13HP1HY6DAVzEIq1H4TZwIZo7KRRTIYpTB3P -6yvr9xsISLlnmfQ4tp2pApl5o+bHJEhr1VO6SAT/pSyShi79KmMMqYtyTmOMz7w6 -VJkre5ybnXBDN6tfMHWqdobJ4gRWK9rqf+LIZig5XQnyzkue8k+I7aPgO4xNFh56 -dkejQcECgYEA9MDCWViqpfvof+epiKzccqnIRnz1EfHdRQjiKsKGRe39+K+pyaqJ -FOOPFy3aOw6M4cFWwcdMYzKTItvzyLVhDqMzT5eup/NVqo5tPoy93XPf2qRYiTl4 -2j5wvm0RVkYEONd3pk2lbfbUmn7XQXj0+AG60SvsqErF/UhIBGec/xsCgYEA5fLC -EdiiC98kr4sVaE8G854WI+aAkStqO5YXyrnsMzRsqk8KVVYE1yCC9rYyymDBYmlx -uEW+vbWqLc8PO3v4ty3o5ff303lPMWIrvKiUldjqMjS6ncWxsQjU0bygGVgOgHO7 -c8rjiDH5M0JgWSREYUVFT5mW/5+Y1LVT8mYNlHUCgYEAhMSX6N23XGkFW3Twu2qB -/1Vohgw86OoaDNvfzDBPpFmQ3rlz0ijHSeSTd5BxBH5FICXACUgygNErjcphOSxj -JQyUxgVTQlo2y1mNm1O/nwS/lxx1xqK9ky4x/Kqvr+w1WBxSFI2kQr2V4OUTobma -sXpGvDcmnrhJJLd0EaefO6cCgYEA3Xw/S9tC8nZjqqYn34nHI16Q6tF54tpTf8Np -dT4x8Xw8cqqhRGMPVHsfSi1irKYXfwgbnienuqlBmtAHVv9pKF+TJfb7gXkmO2XY -xOYIAHGn2uYJHjCun9vmyYKLHv4/MaDH3Jd/I88mviXgEdyp9Js5UJua4utB1Rg3 -HJMJ34UCgYEAr0PpHEBMbZXZBybNU96+jRTgkrNeJpzlnMy7et2IsRAtLjZ0mpbn -NaX8i8eO+ubweqFdhOvbh7Hd0zr7BzrYcUG1e3njhtxJE1MgWL5plnLVUbIyDAm3 -iBpIHIBASNCN3sqeq+VqXvavRmeZh5O0vyLP46/kxZx0rzR/NCi9xxU= ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIC7DCCAdQCBRQHBXNIMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMjEM -MAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0 -MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMDd3MyMQwwCgYD -VQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb2IWcx/imO3LqSc63jBPSOg9SVTZ0YIVb -FDkSDvtjHcui7ZoU7M0anvMtgfyBq44r6aBj4H1wG/w+9W1RBAoHRIpNNXxk0pXI -/c7kXaBFIn60e1MWpo98bRY86f9/TZhs6kB7pGT42eUmh64HEbi5qlRKruvSZMYl -B77nbLUtwyzbcgMQ0F8OhQxW3m8KcX5xgrmd14VUvI87cmOiEMfXO/dr0QIbbyu2 -Mocuk1gUOw8loPtQ+7LKTeEi988Jmgk5SURV+ktP+Uz72gI+er0/Aink2pih+S5z -d4qigKjs3ivgiU8COS1pqjpvRJw3A1AHeV44h0RQVIhjLw3UmzNXAgMBAAEwDQYJ -KoZIhvcNAQEFBQADggEBALi/RmqeXGazT/WRj9+ZqdcnbcHwK5wwr2/YkpFPJ0Hf -ZDm+2vgjDdTT6cJS6fau0M5nliYdz89aQQo1j9RSRZnzlc/2YCFXyRLCOJYaINbj -1MEUAvNDGL7xTpepK9hVkXASRkbyNXERXRKFI1N+vpKu6UorT6/osEV/qM+MFJ3s -24xE8/J3J4MirVQVt6eY6Jb+tkliOPMIugr6YQlLsqJygEWATP8Qsr81XSfcZhVq -rXzVt7QV8dO0nStMjKK5omrtEAhVnASk7w1tFHkpBF1rqXGoo9ML40RnFZ+E5zqi -iZtzp+NzzLnEnWMNs+fJpPJ96P0kbq2bQzuSBcUynq0= ------END CERTIFICATE----- diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h b/3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h deleted file mode 100644 index 4d1c33fc820..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// This software is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this software under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this software under a commercial -// license, as set out in . -// -// $Date: 2014-09-28 05:04:41 UTC $ - -#ifndef NS_SKELETON_HEADER_INCLUDED -#define NS_SKELETON_HEADER_INCLUDED - -#define NS_SKELETON_VERSION "2.1.0" - -#undef UNICODE // Use ANSI WinAPI functions -#undef _UNICODE // Use multibyte encoding on Windows -#define _MBCS // Use multibyte encoding on Windows -#define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows -#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+ -#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h -#define _XOPEN_SOURCE 600 // For flockfile() on Linux -#define __STDC_FORMAT_MACROS // wants this for C++ -#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX -#ifndef _LARGEFILE_SOURCE -#define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions -#endif -#define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets - -#ifdef _MSC_VER -#pragma warning (disable : 4127) // FD_SET() emits warning, disable it -#pragma warning (disable : 4204) // missing c99 support -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") // Linking with winsock library -#endif -#include -#include -#ifndef EINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif -#ifndef __func__ -#define STRX(x) #x -#define STR(x) STRX(x) -#define __func__ __FILE__ ":" STR(__LINE__) -#endif -#ifndef va_copy -#define va_copy(x,y) x = y -#endif // MINGW #defines va_copy -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define sleep(x) Sleep((x) * 1000) -#define to64(x) _atoi64(x) -typedef int socklen_t; -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned __int64 uint64_t; -typedef __int64 int64_t; -typedef SOCKET sock_t; -typedef struct _stati64 ns_stat_t; -#ifndef S_ISDIR -#define S_ISDIR(x) ((x) & _S_IFDIR) -#endif -#else -#include -#include -#include -#include -#include -#include -#include // For inet_pton() when NS_ENABLE_IPV6 is defined -#include -#include -#include -#define closesocket(x) close(x) -#define __cdecl -#define INVALID_SOCKET (-1) -#define to64(x) strtoll(x, NULL, 10) -typedef int sock_t; -typedef struct stat ns_stat_t; -#endif - -#ifdef NS_ENABLE_DEBUG -#define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ - fflush(stdout); } while(0) -#else -#define DBG(x) -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) -#endif - -#ifdef NS_ENABLE_SSL -#ifdef __APPLE__ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -#include -#else -typedef void *SSL; -typedef void *SSL_CTX; -#endif - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -union socket_address { - struct sockaddr sa; - struct sockaddr_in sin; -#ifdef NS_ENABLE_IPV6 - struct sockaddr_in6 sin6; -#else - struct sockaddr sin6; -#endif -}; - -// Describes chunk of memory -struct ns_str { - const char *p; - size_t len; -}; - -// IO buffers interface -struct iobuf { - char *buf; - size_t len; - size_t size; -}; - -void iobuf_init(struct iobuf *, size_t initial_size); -void iobuf_free(struct iobuf *); -size_t iobuf_append(struct iobuf *, const void *data, size_t data_size); -void iobuf_remove(struct iobuf *, size_t data_size); -void iobuf_resize(struct iobuf *, size_t new_size); - -// Callback function (event handler) prototype, must be defined by user. -// Net skeleton will call event handler, passing events defined above. -struct ns_connection; -typedef void (*ns_callback_t)(struct ns_connection *, int event_num, void *evp); - -// Events. Meaning of event parameter (evp) is given in the comment. -#define NS_POLL 0 // Sent to each connection on each call to ns_mgr_poll() -#define NS_ACCEPT 1 // New connection accept()-ed. union socket_address *addr -#define NS_CONNECT 2 // connect() succeeded or failed. int *success_status -#define NS_RECV 3 // Data has benn received. int *num_bytes -#define NS_SEND 4 // Data has been written to a socket. int *num_bytes -#define NS_CLOSE 5 // Connection is closed. NULL - - -struct ns_mgr { - struct ns_connection *active_connections; - const char *hexdump_file; // Debug hexdump file path - sock_t ctl[2]; // Socketpair for mg_wakeup() - void *user_data; // User data -}; - - -struct ns_connection { - struct ns_connection *next, *prev; // ns_mgr::active_connections linkage - struct ns_connection *listener; // Set only for accept()-ed connections - struct ns_mgr *mgr; - - sock_t sock; // Socket - union socket_address sa; // Peer address - struct iobuf recv_iobuf; // Received data - struct iobuf send_iobuf; // Data scheduled for sending - SSL *ssl; - SSL_CTX *ssl_ctx; - void *user_data; // User-specific data - void *proto_data; // Application protocol-specific data - time_t last_io_time; // Timestamp of the last socket IO - ns_callback_t callback; // Event handler function - - unsigned int flags; -#define NSF_FINISHED_SENDING_DATA (1 << 0) -#define NSF_BUFFER_BUT_DONT_SEND (1 << 1) -#define NSF_SSL_HANDSHAKE_DONE (1 << 2) -#define NSF_CONNECTING (1 << 3) -#define NSF_CLOSE_IMMEDIATELY (1 << 4) -#define NSF_WANT_READ (1 << 5) -#define NSF_WANT_WRITE (1 << 6) -#define NSF_LISTENING (1 << 7) -#define NSF_UDP (1 << 8) - -#define NSF_USER_1 (1 << 20) -#define NSF_USER_2 (1 << 21) -#define NSF_USER_3 (1 << 22) -#define NSF_USER_4 (1 << 23) -#define NSF_USER_5 (1 << 24) -#define NSF_USER_6 (1 << 25) -}; - -void ns_mgr_init(struct ns_mgr *, void *user_data); -void ns_mgr_free(struct ns_mgr *); -time_t ns_mgr_poll(struct ns_mgr *, int milli); -void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t); - -struct ns_connection *ns_next(struct ns_mgr *, struct ns_connection *); -struct ns_connection *ns_add_sock(struct ns_mgr *, sock_t, - ns_callback_t, void *); -struct ns_connection *ns_bind(struct ns_mgr *, const char *, - ns_callback_t, void *); -struct ns_connection *ns_connect(struct ns_mgr *, const char *, - ns_callback_t, void *); - -int ns_send(struct ns_connection *, const void *buf, int len); -int ns_printf(struct ns_connection *, const char *fmt, ...); -int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap); - -// Utility functions -void *ns_start_thread(void *(*f)(void *), void *p); -int ns_socketpair(sock_t [2]); -int ns_socketpair2(sock_t [2], int sock_type); // SOCK_STREAM or SOCK_DGRAM -void ns_set_close_on_exec(sock_t); -void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags); -int ns_hexdump(const void *buf, int len, char *dst, int dst_len); -int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap); -int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // NS_SKELETON_HEADER_INCLUDED diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c b/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c deleted file mode 100644 index 969aa979345..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// This software is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this software under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this software under a commercial -// license, as set out in . -// -// $Date$ - -#include "net_skeleton.h" -#include "ssl_wrapper.h" - -static void ev_handler(struct ns_connection *nc, int ev, void *p) { - const char *target_addr = (const char *) nc->mgr->user_data; - struct ns_connection *pc = (struct ns_connection *) nc->user_data; - struct iobuf *io = &nc->recv_iobuf; - - (void) p; - switch (ev) { - case NS_ACCEPT: - // Create a connection to the target, and interlink both connections - nc->user_data = ns_connect(nc->mgr, target_addr, ev_handler, nc); - if (nc->user_data == NULL) { - nc->flags |= NSF_CLOSE_IMMEDIATELY; - } - break; - - case NS_CLOSE: - // If either connection closes, unlink them and shedule closing - if (pc != NULL) { - pc->flags |= NSF_FINISHED_SENDING_DATA; - pc->user_data = NULL; - } - nc->user_data = NULL; - break; - - case NS_RECV: - // Forward arrived data to the other connection, and discard from buffer - if (pc != NULL) { - ns_send(pc, io->buf, io->len); - iobuf_remove(io, io->len); - } - break; - - default: - break; - } -} - -void *ssl_wrapper_init(const char *local_addr, const char *target_addr, - const char **err_msg) { - struct ns_mgr *mgr = (struct ns_mgr *) calloc(1, sizeof(mgr[0])); - *err_msg = NULL; - - if (mgr == NULL) { - *err_msg = "malloc failed"; - } else { - ns_mgr_init(mgr, (void *) target_addr); - if (ns_bind(mgr, local_addr, ev_handler, NULL) == NULL) { - *err_msg = "ns_bind() failed: bad listening_port"; - ns_mgr_free(mgr); - free(mgr); - mgr = NULL; - } - } - - return mgr; -} - -void ssl_wrapper_serve(void *param, volatile int *quit) { - struct ns_mgr *mgr = (struct ns_mgr *) param; - - while (*quit == 0) { - ns_mgr_poll(mgr, 1000); - } - ns_mgr_free(mgr); - free(mgr); -} - -#ifndef SSL_WRAPPER_USE_AS_LIBRARY -static int s_received_signal = 0; - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static void show_usage_and_exit(const char *prog) { - fprintf(stderr, "Usage: %s \n", prog); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - void *wrapper; - const char *err_msg; - - if (argc != 3) { - show_usage_and_exit(argv[0]); - } - - // Setup signal handlers - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGPIPE, SIG_IGN); - - if ((wrapper = ssl_wrapper_init(argv[1], argv[2], &err_msg)) == NULL) { - fprintf(stderr, "Error: %s\n", err_msg); - exit(EXIT_FAILURE); - } - ssl_wrapper_serve(wrapper, &s_received_signal); - - return EXIT_SUCCESS; -} -#endif // SSL_WRAPPER_USE_AS_LIBRARY diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h b/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h deleted file mode 100644 index ccdf780556c..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// This software is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this software under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this software under a commercial -// license, as set out in . -// -// $Date$ - -#ifndef SSL_WRAPPER_HEADER_INCLUDED -#define SSL_WRAPPER_HEADER_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -void *ssl_wrapper_init(const char *listen_addr, const char *target_addr, - const char **err_msg); -void ssl_wrapper_serve(void *, volatile int *stop_marker); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // SSL_WRAPPER_HEADER_INCLUDED diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c b/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c deleted file mode 100644 index d2fceee650e..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates proxying of WebSocket traffic, regardless of the -// protocol (ws:// or wss://). -// To use this example: -// 1. configure your browser to use a proxy on port 2014 -// 2. import certs/ws1_ca.pem and certs/ws2_ca.pem into the trusted -// certificates list on your browser -// 3. make && ./ws_ssl -// 4. Point your browser to http://ws_ssl.com -// A page with 4 sections should appear, showing websocket echoes - -#include "net_skeleton.h" -#include "mongoose.h" -#include "ssl_wrapper.h" - -#define S1_PEM "certs/ws1_server.pem" -#define C1_PEM "certs/ws1_client.pem" -#define CA1_PEM "certs/ws1_ca.pem" -#define S2_PEM "certs/ws2_server.pem" -#define C2_PEM "certs/ws2_client.pem" -#define CA2_PEM "certs/ws2_ca.pem" - -struct config { - const char *uri; - const char *wrapper_server_addr; - const char *wrapper_client_addr; - const char *target_addr; -}; - -static struct config s_wrappers[] = { - { - "ws1:80", - "tcp://127.0.0.1:7001", - "tcp://127.0.0.1:7001", - "tcp://127.0.0.1:9001" - }, - { - "ws1:443", - "ssl://127.0.0.1:7002:" S1_PEM, - "tcp://127.0.0.1:7002", - "tcp://127.0.0.1:9001" - }, - { - "ws2:80", - "tcp://127.0.0.1:7003", - "tcp://127.0.0.1:7003", - "ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM - }, - { - "ws2:443", - "ssl://127.0.0.1:7004:" S2_PEM, - "tcp://127.0.0.1:7004", - "ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM - }, -}; - -static int s_received_signal = 0; - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - int i; - - switch (ev) { - case MG_AUTH: - return MG_TRUE; - - case MG_REQUEST: - printf("==> [%s] [%s]\n", conn->request_method, conn->uri); - - if (strcmp(conn->request_method, "CONNECT") == 0) { - // Iterate over configured wrappers, see if we can use one of them - for (i = 0; i < (int) ARRAY_SIZE(s_wrappers); i++) { - if (strcmp(conn->uri, s_wrappers[i].uri) == 0) { - mg_forward(conn, s_wrappers[i].wrapper_client_addr); - return MG_MORE; - } - } - - // No suitable wrappers found. Disallow that CONNECT request. - mg_send_status(conn, 405); - return MG_TRUE; - } - - // Not a CONNECT request, serve HTML file. - mg_send_file(conn, "ws_ssl.html", NULL); - return MG_MORE; - - default: - return MG_FALSE; - } -} - -static int ws_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: - return MG_TRUE; - case MG_REQUEST: - if (conn->is_websocket) { - // Simple websocket echo server - mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, - conn->content, conn->content_len); - } else { - mg_printf_data(conn, "%s", "websocket connection expected"); - } - return MG_TRUE; - default: - return MG_FALSE; - } -} - -static void *serve_thread_func(void *param) { - struct mg_server *server = (struct mg_server *) param; - printf("Listening on port %s\n", mg_get_option(server, "listening_port")); - while (s_received_signal == 0) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - return NULL; -} - -static void *wrapper_thread_func(void *param) { - struct config *c = (struct config *) param; - const char *err_msg; - void *wrapper; - - wrapper = ssl_wrapper_init(c->wrapper_server_addr, c->target_addr, &err_msg); - if (wrapper == NULL) { - fprintf(stderr, "Error: %s\n", err_msg); - exit(EXIT_FAILURE); - } - //((struct ns_mgr *) wrapper)->hexdump_file = "/dev/stderr"; - ssl_wrapper_serve(wrapper, &s_received_signal); - - return NULL; -} - -int main(void) { - struct mg_server *proxy_server = mg_create_server(NULL, ev_handler); - struct mg_server *ws1_server = mg_create_server(NULL, ws_handler); - struct mg_server *ws2_server = mg_create_server(NULL, ws_handler); - size_t i; - - ((struct ns_mgr *) proxy_server)->hexdump_file = "/dev/stderr"; - - // Configure proxy server to listen on port 2014 - mg_set_option(proxy_server, "listening_port", "2014"); - //mg_set_option(proxy_server, "enable_proxy", "yes"); - - // Configure two websocket echo servers: - // ws1 is WS, listening on 9001 - // ws2 is WSS, listening on 9002 - // Note that HTML page thinks that ws1 is WSS, and ws2 is WS, - // where in reality it is vice versa and proxy server makes the decision. - mg_set_option(ws1_server, "listening_port", "tcp://127.0.0.1:9001"); - mg_set_option(ws2_server, "listening_port", - "ssl://127.0.0.1:9002:" S2_PEM ":" CA2_PEM); - - // Setup signal handlers - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - // Start SSL wrappers, each in it's own thread - for (i = 0; i < ARRAY_SIZE(s_wrappers); i++) { - ns_start_thread(wrapper_thread_func, &s_wrappers[i]); - } - - // Start websocket servers in separate threads - mg_start_thread(serve_thread_func, ws1_server); - mg_start_thread(serve_thread_func, ws2_server); - - // Finally, start proxy server in this thread: this call blocks - serve_thread_func(proxy_server); - - printf("Existing on signal %d\n", s_received_signal); - return EXIT_SUCCESS; -} diff --git a/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html b/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html deleted file mode 100644 index 23ab2506145..00000000000 --- a/3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html +++ /dev/null @@ -1,50 +0,0 @@ - - - Websocket Proxy SSL Test - - - - - - - \ No newline at end of file diff --git a/3rdparty/mongoose/jni/Android.mk b/3rdparty/mongoose/jni/Android.mk deleted file mode 100644 index 3a7daa061c1..00000000000 --- a/3rdparty/mongoose/jni/Android.mk +++ /dev/null @@ -1,8 +0,0 @@ -LOCAL_PATH := $(call my-dir)/.. -include $(CLEAR_VARS) - -LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(COPT) -LOCAL_MODULE := mongoose -LOCAL_SRC_FILES := examples/web_server/web_server.c mongoose.c - -include $(BUILD_EXECUTABLE) diff --git a/3rdparty/mongoose/mongoose.c b/3rdparty/mongoose/mongoose.c deleted file mode 100644 index 3fc2b63fd0a..00000000000 --- a/3rdparty/mongoose/mongoose.c +++ /dev/null @@ -1,5520 +0,0 @@ -// Copyright (c) 2004-2013 Sergey Lyubka -// Copyright (c) 2013-2014 Cesanta Software Limited -// All rights reserved -// -// This library is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this library under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this library under a commercial -// license, as set out in . - -#ifdef NOEMBED_NET_SKELETON -#include "net_skeleton.h" -#else -// net_skeleton start -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// This software is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this software under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this software under a commercial -// license, as set out in . - -#ifndef NS_SKELETON_HEADER_INCLUDED -#define NS_SKELETON_HEADER_INCLUDED - -#define NS_SKELETON_VERSION "2.1.0" - -#undef UNICODE // Use ANSI WinAPI functions -#undef _UNICODE // Use multibyte encoding on Windows -#define _MBCS // Use multibyte encoding on Windows -#define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+ -#endif -#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h -#ifdef __Linux__ -#define _XOPEN_SOURCE 600 // For flockfile() on Linux -#endif -#define __STDC_FORMAT_MACROS // wants this for C++ -#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX -#ifndef _LARGEFILE_SOURCE -#define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions -#endif -#define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets - -#ifdef _MSC_VER -#pragma warning (disable : 4127) // FD_SET() emits warning, disable it -#pragma warning (disable : 4204) // missing c99 support -#endif - -#if defined(_WIN32) && !defined(MONGOOSE_NO_CGI) && !defined(MONGOOSE_ENABLE_THREADS) -#define MONGOOSE_ENABLE_THREADS /* Windows uses stdio threads for CGI */ -#endif - -#ifndef MONGOOSE_ENABLE_THREADS -#define NS_DISABLE_THREADS -#endif - -#ifdef __OS2__ -#define _MMAP_DECLARED // Prevent dummy mmap() declaration in stdio.h -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") // Linking with winsock library -#include -typedef SSIZE_T ssize_t; -#endif -#ifndef FD_SETSIZE -#define FD_SETSIZE 1024 -#endif -#include -#include -#include -#include -#ifndef EINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif -#ifndef __func__ -#define STRX(x) #x -#define STR(x) STRX(x) -#define __func__ __FILE__ ":" STR(__LINE__) -#endif -#ifndef va_copy -#define va_copy(x,y) x = y -#endif // MINGW #defines va_copy -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define sleep(x) Sleep((x) * 1000) -#define to64(x) _atoi64(x) -typedef int socklen_t; -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned __int64 uint64_t; -typedef __int64 int64_t; -typedef SOCKET sock_t; -typedef struct _stati64 ns_stat_t; -#ifndef S_ISDIR -#define S_ISDIR(x) ((x) & _S_IFDIR) -#endif -#else -#include -#include -#include -#include -#include -#include -#include // For inet_pton() when NS_ENABLE_IPV6 is defined -#include -#include -#include -#define closesocket(x) close(x) -#ifndef __OS2__ -#define __cdecl -#else -#include -typedef int socklen_t; -#endif -#define INVALID_SOCKET (-1) -#define to64(x) strtoll(x, NULL, 10) -typedef int sock_t; -typedef struct stat ns_stat_t; -#endif - -#ifdef NS_ENABLE_DEBUG -#define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ - fflush(stdout); } while(0) -#else -#define DBG(x) -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) -#endif - -#ifdef NS_ENABLE_SSL -#ifdef __APPLE__ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -#include -#else -typedef void *SSL; -typedef void *SSL_CTX; -#endif - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -union socket_address { - struct sockaddr sa; - struct sockaddr_in sin; -#ifdef NS_ENABLE_IPV6 - struct sockaddr_in6 sin6; -#else - struct sockaddr sin6; -#endif -}; - -// Describes chunk of memory -struct ns_str { - const char *p; - size_t len; -}; - -// IO buffers interface -struct iobuf { - char *buf; - size_t len; - size_t size; -}; - -void iobuf_init(struct iobuf *, size_t initial_size); -void iobuf_free(struct iobuf *); -size_t iobuf_append(struct iobuf *, const void *data, size_t data_size); -void iobuf_remove(struct iobuf *, size_t data_size); -void iobuf_resize(struct iobuf *, size_t new_size); - -// Callback function (event handler) prototype, must be defined by user. -// Net skeleton will call event handler, passing events defined above. -struct ns_connection; -typedef void (*ns_callback_t)(struct ns_connection *, int event_num, void *evp); - -// Events. Meaning of event parameter (evp) is given in the comment. -#define NS_POLL 0 // Sent to each connection on each call to ns_mgr_poll() -#define NS_ACCEPT 1 // New connection accept()-ed. union socket_address *addr -#define NS_CONNECT 2 // connect() succeeded or failed. int *success_status -#define NS_RECV 3 // Data has benn received. int *num_bytes -#define NS_SEND 4 // Data has been written to a socket. int *num_bytes -#define NS_CLOSE 5 // Connection is closed. NULL - - -struct ns_mgr { - struct ns_connection *active_connections; - const char *hexdump_file; // Debug hexdump file path - sock_t ctl[2]; // Socketpair for mg_wakeup() - void *user_data; // User data -}; - - -struct ns_connection { - struct ns_connection *next, *prev; // ns_mgr::active_connections linkage - struct ns_connection *listener; // Set only for accept()-ed connections - struct ns_mgr *mgr; - - sock_t sock; // Socket - union socket_address sa; // Peer address - size_t recv_iobuf_limit; /* Max size of recv buffer */ - struct iobuf recv_iobuf; // Received data - struct iobuf send_iobuf; // Data scheduled for sending - SSL *ssl; - SSL_CTX *ssl_ctx; - void *user_data; // User-specific data - void *proto_data; // Application protocol-specific data - time_t last_io_time; // Timestamp of the last socket IO - ns_callback_t callback; // Event handler function - - unsigned int flags; -#define NSF_FINISHED_SENDING_DATA (1 << 0) -#define NSF_BUFFER_BUT_DONT_SEND (1 << 1) -#define NSF_SSL_HANDSHAKE_DONE (1 << 2) -#define NSF_CONNECTING (1 << 3) -#define NSF_CLOSE_IMMEDIATELY (1 << 4) -#define NSF_WANT_READ (1 << 5) -#define NSF_WANT_WRITE (1 << 6) -#define NSF_LISTENING (1 << 7) -#define NSF_UDP (1 << 8) -#define NSF_DISCARD (1 << 9) - -#define NSF_USER_1 (1 << 20) -#define NSF_USER_2 (1 << 21) -#define NSF_USER_3 (1 << 22) -#define NSF_USER_4 (1 << 23) -#define NSF_USER_5 (1 << 24) -#define NSF_USER_6 (1 << 25) -}; - -void ns_mgr_init(struct ns_mgr *, void *user_data); -void ns_mgr_free(struct ns_mgr *); -time_t ns_mgr_poll(struct ns_mgr *, int milli); -void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t); - -struct ns_connection *ns_next(struct ns_mgr *, struct ns_connection *); -struct ns_connection *ns_add_sock(struct ns_mgr *, sock_t, - ns_callback_t, void *); -struct ns_connection *ns_bind(struct ns_mgr *, const char *, - ns_callback_t, void *); -struct ns_connection *ns_connect(struct ns_mgr *, const char *, - ns_callback_t, void *); - -int ns_send(struct ns_connection *, const void *buf, size_t len); -int ns_printf(struct ns_connection *, const char *fmt, ...); -int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap); - -// Utility functions -void *ns_start_thread(void *(*f)(void *), void *p); -int ns_socketpair(sock_t [2]); -int ns_socketpair2(sock_t [2], int sock_type); // SOCK_STREAM or SOCK_DGRAM -void ns_set_close_on_exec(sock_t); -void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags); -int ns_hexdump(const void *buf, int len, char *dst, int dst_len); -int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap); -int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // NS_SKELETON_HEADER_INCLUDED -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// This software is dual-licensed: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. For the terms of this -// license, see . -// -// You are free to use this software under the terms of the GNU General -// Public License, but WITHOUT ANY WARRANTY; without even the implied -// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. -// -// Alternatively, you can license this software under a commercial -// license, as set out in . -// -// $Date: 2014-09-28 05:04:41 UTC $ - - -#ifndef NS_MALLOC -#define NS_MALLOC malloc -#endif - -#ifndef NS_REALLOC -#define NS_REALLOC realloc -#endif - -#ifndef NS_FREE -#define NS_FREE free -#endif - -#ifndef NS_CALLOC -#define NS_CALLOC calloc -#endif - -#define NS_MAX_SOCKETPAIR_ATTEMPTS 10 -#define NS_CTL_MSG_MESSAGE_SIZE (8 * 1024) -#define NS_READ_BUFFER_SIZE 2048 -#define NS_UDP_RECEIVE_BUFFER_SIZE 2000 -#define NS_VPRINTF_BUFFER_SIZE 500 - -struct ctl_msg { - ns_callback_t callback; - char message[NS_CTL_MSG_MESSAGE_SIZE]; -}; - -void iobuf_resize(struct iobuf *io, size_t new_size) { - char *p; - if ((new_size > io->size || (new_size < io->size && new_size >= io->len)) && - (p = (char *) NS_REALLOC(io->buf, new_size)) != NULL) { - io->size = new_size; - io->buf = p; - } -} - -void iobuf_init(struct iobuf *iobuf, size_t initial_size) { - iobuf->len = iobuf->size = 0; - iobuf->buf = NULL; - iobuf_resize(iobuf, initial_size); -} - -void iobuf_free(struct iobuf *iobuf) { - if (iobuf != NULL) { - if (iobuf->buf != NULL) NS_FREE(iobuf->buf); - iobuf_init(iobuf, 0); - } -} - -size_t iobuf_append(struct iobuf *io, const void *buf, size_t len) { - char *p = NULL; - - assert(io != NULL); - assert(io->len <= io->size); - - /* check overflow */ - if (len > ~(size_t)0 - (size_t)(io->buf + io->len)) { - return 0; - } - - if (len <= 0) { - } else if (io->len + len <= io->size) { - memcpy(io->buf + io->len, buf, len); - io->len += len; - } else if ((p = (char *) NS_REALLOC(io->buf, io->len + len)) != NULL) { - io->buf = p; - memcpy(io->buf + io->len, buf, len); - io->len += len; - io->size = io->len; - } else { - len = 0; - } - - return len; -} - -void iobuf_remove(struct iobuf *io, size_t n) { - if (n > 0 && n <= io->len) { - memmove(io->buf, io->buf + n, io->len - n); - io->len -= n; - } -} - -static size_t ns_out(struct ns_connection *nc, const void *buf, size_t len) { - if (nc->flags & NSF_UDP) { - long n = sendto(nc->sock, (const char *) buf, len, 0, &nc->sa.sa, - sizeof(nc->sa.sin)); - DBG(("%p %d send %ld (%d %s)", nc, nc->sock, n, errno, strerror(errno))); - return n < 0 ? 0 : n; - } else { - return iobuf_append(&nc->send_iobuf, buf, len); - } -} - -#ifndef NS_DISABLE_THREADS -void *ns_start_thread(void *(*f)(void *), void *p) { -#ifdef _WIN32 - return (void *) _beginthread((void (__cdecl *)(void *)) f, 0, p); -#else - pthread_t thread_id = (pthread_t) 0; - pthread_attr_t attr; - - (void) pthread_attr_init(&attr); - (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - -#if defined(NS_STACK_SIZE) && NS_STACK_SIZE > 1 - (void) pthread_attr_setstacksize(&attr, NS_STACK_SIZE); -#endif - - pthread_create(&thread_id, &attr, f, p); - pthread_attr_destroy(&attr); - - return (void *) thread_id; -#endif -} -#endif // NS_DISABLE_THREADS - -static void ns_add_conn(struct ns_mgr *mgr, struct ns_connection *c) { - c->next = mgr->active_connections; - mgr->active_connections = c; - c->prev = NULL; - if (c->next != NULL) c->next->prev = c; -} - -static void ns_remove_conn(struct ns_connection *conn) { - if (conn->prev == NULL) conn->mgr->active_connections = conn->next; - if (conn->prev) conn->prev->next = conn->next; - if (conn->next) conn->next->prev = conn->prev; -} - -// Print message to buffer. If buffer is large enough to hold the message, -// return buffer. If buffer is to small, allocate large enough buffer on heap, -// and return allocated buffer. -int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) { - va_list ap_copy; - int len; - - va_copy(ap_copy, ap); - len = vsnprintf(*buf, size, fmt, ap_copy); - va_end(ap_copy); - - if (len < 0) { - // eCos and Windows are not standard-compliant and return -1 when - // the buffer is too small. Keep allocating larger buffers until we - // succeed or out of memory. - *buf = NULL; - while (len < 0) { - if (*buf) NS_FREE(*buf); - size *= 2; - if ((*buf = (char *) NS_MALLOC(size)) == NULL) break; - va_copy(ap_copy, ap); - len = vsnprintf(*buf, size, fmt, ap_copy); - va_end(ap_copy); - } - } else if (len > (int) size) { - // Standard-compliant code path. Allocate a buffer that is large enough. - if ((*buf = (char *) NS_MALLOC(len + 1)) == NULL) { - len = -1; - } else { - va_copy(ap_copy, ap); - len = vsnprintf(*buf, len + 1, fmt, ap_copy); - va_end(ap_copy); - } - } - - return len; -} - -int ns_vprintf(struct ns_connection *nc, const char *fmt, va_list ap) { - char mem[NS_VPRINTF_BUFFER_SIZE], *buf = mem; - int len; - - if ((len = ns_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { - ns_out(nc, buf, len); - } - if (buf != mem && buf != NULL) { - NS_FREE(buf); - } - - return len; -} - -int ns_printf(struct ns_connection *conn, const char *fmt, ...) { - int len; - va_list ap; - va_start(ap, fmt); - len = ns_vprintf(conn, fmt, ap); - va_end(ap); - return len; -} - -static void hexdump(struct ns_connection *nc, const char *path, - int num_bytes, int ev) { - const struct iobuf *io = ev == NS_SEND ? &nc->send_iobuf : &nc->recv_iobuf; - FILE *fp; - char *buf, src[60], dst[60]; - int buf_size = num_bytes * 5 + 100; - - if ((fp = fopen(path, "a")) != NULL) { - ns_sock_to_str(nc->sock, src, sizeof(src), 3); - ns_sock_to_str(nc->sock, dst, sizeof(dst), 7); - fprintf(fp, "%lu %p %s %s %s %d\n", (unsigned long) time(NULL), - nc->user_data, src, - ev == NS_RECV ? "<-" : ev == NS_SEND ? "->" : - ev == NS_ACCEPT ? "" : "XX", - dst, num_bytes); - if (num_bytes > 0 && (buf = (char *) NS_MALLOC(buf_size)) != NULL) { - ns_hexdump(io->buf + (ev == NS_SEND ? 0 : io->len) - - (ev == NS_SEND ? 0 : num_bytes), num_bytes, buf, buf_size); - fprintf(fp, "%s", buf); - NS_FREE(buf); - } - fclose(fp); - } -} - -static void ns_call(struct ns_connection *nc, int ev, void *p) { - if (nc->mgr->hexdump_file != NULL && ev != NS_POLL) { - int len = (ev == NS_RECV || ev == NS_SEND) ? * (int *) p : 0; - hexdump(nc, nc->mgr->hexdump_file, len, ev); - } - - nc->callback(nc, ev, p); -} - -static void ns_destroy_conn(struct ns_connection *conn) { - closesocket(conn->sock); - iobuf_free(&conn->recv_iobuf); - iobuf_free(&conn->send_iobuf); -#ifdef NS_ENABLE_SSL - if (conn->ssl != NULL) { - SSL_free(conn->ssl); - } - if (conn->ssl_ctx != NULL) { - SSL_CTX_free(conn->ssl_ctx); - } -#endif - NS_FREE(conn); -} - -static void ns_close_conn(struct ns_connection *conn) { - DBG(("%p %d", conn, conn->flags)); - ns_call(conn, NS_CLOSE, NULL); - ns_remove_conn(conn); - ns_destroy_conn(conn); -} - -void ns_set_close_on_exec(sock_t sock) { -#ifdef _WIN32 - (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0); -#else - fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif -} - -static void ns_set_non_blocking_mode(sock_t sock) { -#ifdef _WIN32 - unsigned long on = 1; - ioctlsocket(sock, FIONBIO, &on); -#else - int flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); -#endif -} - -#ifndef NS_DISABLE_SOCKETPAIR -int ns_socketpair2(sock_t sp[2], int sock_type) { - union socket_address sa; - sock_t sock; - socklen_t len = sizeof(sa.sin); - int ret = 0; - - sp[0] = sp[1] = INVALID_SOCKET; - - (void) memset(&sa, 0, sizeof(sa)); - sa.sin.sin_family = AF_INET; - sa.sin.sin_port = htons(0); - sa.sin.sin_addr.s_addr = htonl(0x7f000001); - - if ((sock = socket(AF_INET, sock_type, 0)) != INVALID_SOCKET && - !bind(sock, &sa.sa, len) && - (sock_type == SOCK_DGRAM || !listen(sock, 1)) && - !getsockname(sock, &sa.sa, &len) && - (sp[0] = socket(AF_INET, sock_type, 0)) != INVALID_SOCKET && - !connect(sp[0], &sa.sa, len) && - (sock_type == SOCK_STREAM || - (!getsockname(sp[0], &sa.sa, &len) && !connect(sock, &sa.sa, len))) && - (sp[1] = (sock_type == SOCK_DGRAM ? sock : - accept(sock, &sa.sa, &len))) != INVALID_SOCKET) { - ns_set_close_on_exec(sp[0]); - ns_set_close_on_exec(sp[1]); - ret = 1; - } else { - if (sp[0] != INVALID_SOCKET) closesocket(sp[0]); - if (sp[1] != INVALID_SOCKET) closesocket(sp[1]); - sp[0] = sp[1] = INVALID_SOCKET; - } - if (sock_type != SOCK_DGRAM) closesocket(sock); - - return ret; -} - -int ns_socketpair(sock_t sp[2]) { - return ns_socketpair2(sp, SOCK_STREAM); -} -#endif // NS_DISABLE_SOCKETPAIR - -// TODO(lsm): use non-blocking resolver -static int ns_resolve2(const char *host, struct in_addr *ina) { -#ifdef NS_ENABLE_GETADDRINFO - int rv = 0; - struct addrinfo hints, *servinfo, *p; - struct sockaddr_in *h = NULL; - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - if((rv = getaddrinfo(host, NULL , NULL, &servinfo)) != 0) { - DBG(("getaddrinfo(%s) failed: %s", host, strerror(errno))); - return 0; - } - - for(p = servinfo; p != NULL; p = p->ai_next) { - memcpy(&h, &p->ai_addr, sizeof(struct sockaddr_in *)); - memcpy(ina, &h->sin_addr, sizeof(ina)); - } - - freeaddrinfo(servinfo); - return 1; -#else - struct hostent *he; - if ((he = gethostbyname(host)) == NULL) { - DBG(("gethostbyname(%s) failed: %s", host, strerror(errno))); - } else { - memcpy(ina, he->h_addr_list[0], sizeof(*ina)); - return 1; - } - return 0; -#endif -} - -// Resolve FDQN "host", store IP address in the "ip". -// Return > 0 (IP address length) on success. -int ns_resolve(const char *host, char *buf, size_t n) { - struct in_addr ad; - return ns_resolve2(host, &ad) ? snprintf(buf, n, "%s", inet_ntoa(ad)) : 0; -} - -// Address format: [PROTO://][IP_ADDRESS:]PORT[:CERT][:CA_CERT] -static int ns_parse_address(const char *str, union socket_address *sa, - int *proto, int *use_ssl, char *cert, char *ca) { - unsigned int a, b, c, d, port; - int n = 0, len = 0; - char host[200]; -#ifdef NS_ENABLE_IPV6 - char buf[100]; -#endif - - // MacOS needs that. If we do not zero it, subsequent bind() will fail. - // Also, all-zeroes in the socket address means binding to all addresses - // for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). - memset(sa, 0, sizeof(*sa)); - sa->sin.sin_family = AF_INET; - - *proto = SOCK_STREAM; - *use_ssl = 0; - cert[0] = ca[0] = '\0'; - - if (memcmp(str, "ssl://", 6) == 0) { - str += 6; - *use_ssl = 1; - } else if (memcmp(str, "udp://", 6) == 0) { - str += 6; - *proto = SOCK_DGRAM; - } else if (memcmp(str, "tcp://", 6) == 0) { - str += 6; - } - - if (sscanf(str, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) == 5) { - // Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 - sa->sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d); - sa->sin.sin_port = htons((uint16_t) port); -#ifdef NS_ENABLE_IPV6 - } else if (sscanf(str, "[%99[^]]]:%u%n", buf, &port, &len) == 2 && - inet_pton(AF_INET6, buf, &sa->sin6.sin6_addr)) { - // IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080 - sa->sin6.sin6_family = AF_INET6; - sa->sin6.sin6_port = htons((uint16_t) port); -#endif - } else if (sscanf(str, "%199[^ :]:%u%n", host, &port, &len) == 2) { - sa->sin.sin_port = htons((uint16_t) port); - ns_resolve2(host, &sa->sin.sin_addr); - } else if (sscanf(str, "%u%n", &port, &len) == 1) { - // If only port is specified, bind to IPv4, INADDR_ANY - sa->sin.sin_port = htons((uint16_t) port); - } - - if (*use_ssl && (sscanf(str + len, ":%99[^:,]:%99[^:,]%n", cert, ca, &n) == 2 || - sscanf(str + len, ":%99[^:,]%n", cert, &n) == 1)) { - len += n; - } - - return port < 0xffff && str[len] == '\0' ? len : 0; -} - -// 'sa' must be an initialized address to bind to -static sock_t ns_open_listening_socket(union socket_address *sa, int proto) { - socklen_t sa_len = (sa->sa.sa_family == AF_INET) ? - sizeof(sa->sin) : sizeof(sa->sin6); - sock_t sock = INVALID_SOCKET; -#ifndef _WIN32 - int on = 1; -#endif - - if ((sock = socket(sa->sa.sa_family, proto, 0)) != INVALID_SOCKET && -#ifndef _WIN32 - // SO_RESUSEADDR is not enabled on Windows because the semantics of - // SO_REUSEADDR on UNIX and Windows is different. On Windows, - // SO_REUSEADDR allows to bind a socket to a port without error even if - // the port is already open by another program. This is not the behavior - // SO_REUSEADDR was designed for, and leads to hard-to-track failure - // scenarios. Therefore, SO_REUSEADDR was disabled on Windows. - !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)) && -#endif - !bind(sock, &sa->sa, sa_len) && - (proto == SOCK_DGRAM || listen(sock, SOMAXCONN) == 0)) { - ns_set_non_blocking_mode(sock); - // In case port was set to 0, get the real port number - (void) getsockname(sock, &sa->sa, &sa_len); - } else if (sock != INVALID_SOCKET) { - closesocket(sock); - sock = INVALID_SOCKET; - } - - return sock; -} - -#ifdef NS_ENABLE_SSL -// Certificate generation script is at -// https://github.com/cesanta/net_skeleton/blob/master/scripts/gen_certs.sh - -static int ns_use_ca_cert(SSL_CTX *ctx, const char *cert) { - if (ctx == NULL) { - return -1; - } else if (cert == NULL || cert[0] == '\0') { - return 0; - } - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? 0 : -2; -} - -static int ns_use_cert(SSL_CTX *ctx, const char *pem_file) { - if (ctx == NULL) { - return -1; - } else if (pem_file == NULL || pem_file[0] == '\0') { - return 0; - } else if (SSL_CTX_use_certificate_file(ctx, pem_file, 1) == 0 || - SSL_CTX_use_PrivateKey_file(ctx, pem_file, 1) == 0) { - return -2; - } else { - SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - SSL_CTX_use_certificate_chain_file(ctx, pem_file); - return 0; - } -} -#endif // NS_ENABLE_SSL - -struct ns_connection *ns_bind(struct ns_mgr *srv, const char *str, - ns_callback_t callback, void *user_data) { - union socket_address sa; - struct ns_connection *nc = NULL; - int use_ssl, proto; - char cert[100], ca_cert[100]; - sock_t sock; - - ns_parse_address(str, &sa, &proto, &use_ssl, cert, ca_cert); - if (use_ssl && cert[0] == '\0') return NULL; - - if ((sock = ns_open_listening_socket(&sa, proto)) == INVALID_SOCKET) { - } else if ((nc = ns_add_sock(srv, sock, callback, NULL)) == NULL) { - closesocket(sock); - } else { - nc->sa = sa; - nc->flags |= NSF_LISTENING; - nc->user_data = user_data; - nc->callback = callback; - - if (proto == SOCK_DGRAM) { - nc->flags |= NSF_UDP; - } - -#ifdef NS_ENABLE_SSL - if (use_ssl) { - nc->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); - if (ns_use_cert(nc->ssl_ctx, cert) != 0 || - ns_use_ca_cert(nc->ssl_ctx, ca_cert) != 0) { - ns_close_conn(nc); - nc = NULL; - } - } -#endif - - DBG(("%p sock %d/%d ssl %p %p", nc, sock, proto, nc->ssl_ctx, nc->ssl)); - } - - return nc; -} - -static struct ns_connection *accept_conn(struct ns_connection *ls) { - struct ns_connection *c = NULL; - union socket_address sa; - socklen_t len = sizeof(sa); - sock_t sock = INVALID_SOCKET; - - // NOTE(lsm): on Windows, sock is always > FD_SETSIZE - if ((sock = accept(ls->sock, &sa.sa, &len)) == INVALID_SOCKET) { - } else if ((c = ns_add_sock(ls->mgr, sock, ls->callback, - ls->user_data)) == NULL) { - closesocket(sock); -#ifdef NS_ENABLE_SSL - } else if (ls->ssl_ctx != NULL && - ((c->ssl = SSL_new(ls->ssl_ctx)) == NULL || - SSL_set_fd(c->ssl, sock) != 1)) { - DBG(("SSL error")); - ns_close_conn(c); - c = NULL; -#endif - } else { - c->listener = ls; - c->proto_data = ls->proto_data; - ns_call(c, NS_ACCEPT, &sa); - DBG(("%p %d %p %p", c, c->sock, c->ssl_ctx, c->ssl)); - } - - return c; -} - -static int ns_is_error(int n) { - return n == 0 || - (n < 0 && errno != EINTR && errno != EINPROGRESS && - errno != EAGAIN && errno != EWOULDBLOCK -#ifdef _WIN32 - && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK -#endif - ) -#ifdef NS_ENABLE_SSL - /* - * OpenSSL can return an error when the peer is closing the socket. - * We don't encounter this error with openssl actually, but it's returned - * by our polarssl <-> openssl wrapper who tries to speak the openssl API - * as we understood it. - */ - || n == SSL_AD_CLOSE_NOTIFY -#endif - ; -} - -void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) { - union socket_address sa; - socklen_t slen = sizeof(sa); - - if (buf != NULL && len > 0) { - buf[0] = '\0'; - memset(&sa, 0, sizeof(sa)); - if (flags & 4) { - getpeername(sock, &sa.sa, &slen); - } else { - getsockname(sock, &sa.sa, &slen); - } - if (flags & 1) { -#if defined(NS_ENABLE_IPV6) - inet_ntop(sa.sa.sa_family, sa.sa.sa_family == AF_INET ? - (void *) &sa.sin.sin_addr : - (void *) &sa.sin6.sin6_addr, buf, len); -#elif defined(_WIN32) - // Only Windoze Vista (and newer) have inet_ntop() - strncpy(buf, inet_ntoa(sa.sin.sin_addr), len); -#else - inet_ntop(sa.sa.sa_family, (void *) &sa.sin.sin_addr, buf,(socklen_t)len); -#endif - } - if (flags & 2) { - snprintf(buf + strlen(buf), len - (strlen(buf) + 1), "%s%d", - flags & 1 ? ":" : "", (int) ntohs(sa.sin.sin_port)); - } - } -} - -int ns_hexdump(const void *buf, int len, char *dst, int dst_len) { - const unsigned char *p = (const unsigned char *) buf; - char ascii[17] = ""; - int i, idx, n = 0; - - for (i = 0; i < len; i++) { - idx = i % 16; - if (idx == 0) { - if (i > 0) n += snprintf(dst + n, dst_len - n, " %s\n", ascii); - n += snprintf(dst + n, dst_len - n, "%04x ", i); - } - n += snprintf(dst + n, dst_len - n, " %02x", p[i]); - ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]; - ascii[idx + 1] = '\0'; - } - - while (i++ % 16) n += snprintf(dst + n, dst_len - n, "%s", " "); - n += snprintf(dst + n, dst_len - n, " %s\n\n", ascii); - - return n; -} - -#ifdef NS_ENABLE_SSL -static int ns_ssl_err(struct ns_connection *conn, int res) { - int ssl_err = SSL_get_error(conn->ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) conn->flags |= NSF_WANT_READ; - if (ssl_err == SSL_ERROR_WANT_WRITE) conn->flags |= NSF_WANT_WRITE; - return ssl_err; -} -#endif - -static void ns_read_from_socket(struct ns_connection *conn) { - char buf[NS_READ_BUFFER_SIZE]; - int n = 0; - - if (conn->flags & NSF_CONNECTING) { - int ok = 1, ret; - socklen_t len = sizeof(ok); - - ret = getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len); - (void) ret; -#ifdef NS_ENABLE_SSL - if (ret == 0 && ok == 0 && conn->ssl != NULL) { - int res = SSL_connect(conn->ssl); - int ssl_err = ns_ssl_err(conn, res); - if (res == 1) { - conn->flags |= NSF_SSL_HANDSHAKE_DONE; - } else if (ssl_err == SSL_ERROR_WANT_READ || - ssl_err == SSL_ERROR_WANT_WRITE) { - return; // Call us again - } else { - ok = 1; - } - conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE); - } -#endif - conn->flags &= ~NSF_CONNECTING; - DBG(("%p ok=%d", conn, ok)); - if (ok != 0) { - conn->flags |= NSF_CLOSE_IMMEDIATELY; - } - ns_call(conn, NS_CONNECT, &ok); - return; - } - -#ifdef NS_ENABLE_SSL - if (conn->ssl != NULL) { - if (conn->flags & NSF_SSL_HANDSHAKE_DONE) { - // SSL library may have more bytes ready to read then we ask to read. - // Therefore, read in a loop until we read everything. Without the loop, - // we skip to the next select() cycle which can just timeout. - while ((n = SSL_read(conn->ssl, buf, sizeof(buf))) > 0) { - DBG(("%p %d <- %d bytes (SSL)", conn, conn->flags, n)); - iobuf_append(&conn->recv_iobuf, buf, n); - ns_call(conn, NS_RECV, &n); - } - ns_ssl_err(conn, n); - } else { - int res = SSL_accept(conn->ssl); - int ssl_err = ns_ssl_err(conn, res); - if (res == 1) { - conn->flags |= NSF_SSL_HANDSHAKE_DONE; - conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE); - } else if (ssl_err == SSL_ERROR_WANT_READ || - ssl_err == SSL_ERROR_WANT_WRITE) { - return; // Call us again - } else { - conn->flags |= NSF_CLOSE_IMMEDIATELY; - } - return; - } - } else -#endif - { - while ((n = (int) recv(conn->sock, buf, sizeof(buf), 0)) > 0) { - DBG(("%p %d <- %d bytes (PLAIN)", conn, conn->flags, n)); - iobuf_append(&conn->recv_iobuf, buf, n); - ns_call(conn, NS_RECV, &n); - } - } - - if (ns_is_error(n)) { - conn->flags |= NSF_CLOSE_IMMEDIATELY; - } -} - -static void ns_write_to_socket(struct ns_connection *conn) { - struct iobuf *io = &conn->send_iobuf; - int n = 0; - -#ifdef NS_ENABLE_SSL - if (conn->ssl != NULL) { - n = SSL_write(conn->ssl, io->buf, io->len); - if (n <= 0) { - int ssl_err = ns_ssl_err(conn, n); - if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { - return; // Call us again - } else { - conn->flags |= NSF_CLOSE_IMMEDIATELY; - } - } else { - conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE); - } - } else -#endif - { n = (int) send(conn->sock, io->buf, io->len, 0); } - - DBG(("%p %d -> %d bytes", conn, conn->flags, n)); - - ns_call(conn, NS_SEND, &n); - if (ns_is_error(n)) { - conn->flags |= NSF_CLOSE_IMMEDIATELY; - } else if (n > 0) { - iobuf_remove(io, n); - } -} - -int ns_send(struct ns_connection *conn, const void *buf, size_t len) { - return (int) ns_out(conn, buf, len); -} - -static void ns_handle_udp(struct ns_connection *ls) { - struct ns_connection nc; - char buf[NS_UDP_RECEIVE_BUFFER_SIZE]; - ssize_t n; - socklen_t s_len = sizeof(nc.sa); - - memset(&nc, 0, sizeof(nc)); - n = recvfrom(ls->sock, buf, sizeof(buf), 0, &nc.sa.sa, &s_len); - if (n <= 0) { - DBG(("%p recvfrom: %s", ls, strerror(errno))); - } else { - nc.mgr = ls->mgr; - nc.recv_iobuf.buf = buf; - nc.recv_iobuf.len = nc.recv_iobuf.size = n; - nc.sock = ls->sock; - nc.callback = ls->callback; - nc.user_data = ls->user_data; - nc.proto_data = ls->proto_data; - nc.mgr = ls->mgr; - nc.listener = ls; - nc.flags = NSF_UDP; - DBG(("%p %d bytes received", ls, n)); - ns_call(&nc, NS_RECV, &n); - } -} - -static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) { - if ( (sock != INVALID_SOCKET) && (sock < FD_SETSIZE) ) { - FD_SET(sock, set); - if (*max_fd == INVALID_SOCKET || sock > *max_fd) { - *max_fd = sock; - } - } -} - -time_t ns_mgr_poll(struct ns_mgr *mgr, int milli) { - struct ns_connection *conn, *tmp_conn; - struct timeval tv; - fd_set read_set, write_set; - sock_t max_fd = INVALID_SOCKET; - time_t current_time = time(NULL); - - FD_ZERO(&read_set); - FD_ZERO(&write_set); - ns_add_to_set(mgr->ctl[1], &read_set, &max_fd); - - for (conn = mgr->active_connections; conn != NULL; conn = tmp_conn) { - tmp_conn = conn->next; - if (!(conn->flags & (NSF_LISTENING | NSF_CONNECTING))) { - ns_call(conn, NS_POLL, ¤t_time); - } - if (conn->flags & NSF_CLOSE_IMMEDIATELY) { - ns_close_conn(conn); - } else { - if (!(conn->flags & NSF_WANT_WRITE)) { - //DBG(("%p read_set", conn)); - ns_add_to_set(conn->sock, &read_set, &max_fd); - } - if (((conn->flags & NSF_CONNECTING) && !(conn->flags & NSF_WANT_READ)) || - (conn->send_iobuf.len > 0 && !(conn->flags & NSF_CONNECTING) && - !(conn->flags & NSF_BUFFER_BUT_DONT_SEND))) { - //DBG(("%p write_set", conn)); - ns_add_to_set(conn->sock, &write_set, &max_fd); - } - } - } - - tv.tv_sec = milli / 1000; - tv.tv_usec = (milli % 1000) * 1000; - - if (select((int) max_fd + 1, &read_set, &write_set, NULL, &tv) < 0) { - return 0; - } else { - // select() might have been waiting for a long time, reset current_time - // now to prevent last_io_time being set to the past. - current_time = time(NULL); - - // Read wakeup messages - if (mgr->ctl[1] != INVALID_SOCKET && - FD_ISSET(mgr->ctl[1], &read_set)) { - struct ctl_msg ctl_msg; - int len = (int) recv(mgr->ctl[1], (char *) &ctl_msg, sizeof(ctl_msg), 0); - send(mgr->ctl[1], ctl_msg.message, 1, 0); - if (len >= (int) sizeof(ctl_msg.callback) && ctl_msg.callback != NULL) { - struct ns_connection *c; - for (c = ns_next(mgr, NULL); c != NULL; c = ns_next(mgr, c)) { - ctl_msg.callback(c, NS_POLL, ctl_msg.message); - } - } - } - - for (conn = mgr->active_connections; conn != NULL; conn = tmp_conn) { - tmp_conn = conn->next; - if (FD_ISSET(conn->sock, &read_set)) { - if (conn->flags & NSF_LISTENING) { - if (conn->flags & NSF_UDP) { - ns_handle_udp(conn); - } else { - // We're not looping here, and accepting just one connection at - // a time. The reason is that eCos does not respect non-blocking - // flag on a listening socket and hangs in a loop. - accept_conn(conn); - } - } else { - conn->last_io_time = current_time; - ns_read_from_socket(conn); - } - } - - if (FD_ISSET(conn->sock, &write_set)) { - if (conn->flags & NSF_CONNECTING) { - ns_read_from_socket(conn); - } else if (!(conn->flags & NSF_BUFFER_BUT_DONT_SEND)) { - conn->last_io_time = current_time; - ns_write_to_socket(conn); - } - } - } - } - - for (conn = mgr->active_connections; conn != NULL; conn = tmp_conn) { - tmp_conn = conn->next; - if ((conn->flags & NSF_CLOSE_IMMEDIATELY) || - (conn->send_iobuf.len == 0 && - (conn->flags & NSF_FINISHED_SENDING_DATA))) { - ns_close_conn(conn); - } - } - - return current_time; -} - -struct ns_connection *ns_connect(struct ns_mgr *mgr, const char *address, - ns_callback_t callback, void *user_data) { - sock_t sock = INVALID_SOCKET; - struct ns_connection *nc = NULL; - union socket_address sa; - char cert[100], ca_cert[100]; - int rc, use_ssl, proto; - - ns_parse_address(address, &sa, &proto, &use_ssl, cert, ca_cert); - if ((sock = socket(AF_INET, proto, 0)) == INVALID_SOCKET) { - return NULL; - } - ns_set_non_blocking_mode(sock); - rc = (proto == SOCK_DGRAM) ? 0 : connect(sock, &sa.sa, sizeof(sa.sin)); - - if (rc != 0 && ns_is_error(rc)) { - closesocket(sock); - return NULL; - } else if ((nc = ns_add_sock(mgr, sock, callback, user_data)) == NULL) { - closesocket(sock); - return NULL; - } - - nc->sa = sa; // Important, cause UDP conns will use sendto() - nc->flags = (proto == SOCK_DGRAM) ? NSF_UDP : NSF_CONNECTING; - -#ifdef NS_ENABLE_SSL - if (use_ssl) { - if ((nc->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL || - ns_use_cert(nc->ssl_ctx, cert) != 0 || - ns_use_ca_cert(nc->ssl_ctx, ca_cert) != 0 || - (nc->ssl = SSL_new(nc->ssl_ctx)) == NULL) { - ns_close_conn(nc); - return NULL; - } else { - SSL_set_fd(nc->ssl, sock); - } - } -#endif - - return nc; -} - -struct ns_connection *ns_add_sock(struct ns_mgr *s, sock_t sock, - ns_callback_t callback, void *user_data) { - struct ns_connection *conn; - if ((conn = (struct ns_connection *) NS_MALLOC(sizeof(*conn))) != NULL) { - memset(conn, 0, sizeof(*conn)); - ns_set_non_blocking_mode(sock); - ns_set_close_on_exec(sock); - conn->sock = sock; - conn->user_data = user_data; - conn->callback = callback; - conn->mgr = s; - conn->last_io_time = time(NULL); - ns_add_conn(s, conn); - DBG(("%p %d", conn, sock)); - } - return conn; -} - -struct ns_connection *ns_next(struct ns_mgr *s, struct ns_connection *conn) { - return conn == NULL ? s->active_connections : conn->next; -} - -void ns_broadcast(struct ns_mgr *mgr, ns_callback_t cb,void *data, size_t len) { - struct ctl_msg ctl_msg; - if (mgr->ctl[0] != INVALID_SOCKET && data != NULL && - len < sizeof(ctl_msg.message)) { - ctl_msg.callback = cb; - memcpy(ctl_msg.message, data, len); - send(mgr->ctl[0], (char *) &ctl_msg, - offsetof(struct ctl_msg, message) + len, 0); - recv(mgr->ctl[0], (char *) &len, 1, 0); - } -} - -void ns_mgr_init(struct ns_mgr *s, void *user_data) { - memset(s, 0, sizeof(*s)); - s->ctl[0] = s->ctl[1] = INVALID_SOCKET; - s->user_data = user_data; - -#ifdef _WIN32 - { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); } -#else - // Ignore SIGPIPE signal, so if client cancels the request, it - // won't kill the whole process. - signal(SIGPIPE, SIG_IGN); -#endif - -#ifndef NS_DISABLE_SOCKETPAIR - { - int attempts = 0, max_attempts = NS_MAX_SOCKETPAIR_ATTEMPTS; - do { - ns_socketpair2(s->ctl, SOCK_DGRAM); - } while (s->ctl[0] == INVALID_SOCKET && ++attempts < max_attempts); - } -#endif - -#ifdef NS_ENABLE_SSL - {static int init_done; if (!init_done) { SSL_library_init(); init_done++; }} -#endif -} - -void ns_mgr_free(struct ns_mgr *s) { - struct ns_connection *conn, *tmp_conn; - - DBG(("%p", s)); - if (s == NULL) return; - // Do one last poll, see https://github.com/cesanta/mongoose/issues/286 - ns_mgr_poll(s, 0); - - if (s->ctl[0] != INVALID_SOCKET) closesocket(s->ctl[0]); - if (s->ctl[1] != INVALID_SOCKET) closesocket(s->ctl[1]); - s->ctl[0] = s->ctl[1] = INVALID_SOCKET; - - for (conn = s->active_connections; conn != NULL; conn = tmp_conn) { - tmp_conn = conn->next; - ns_close_conn(conn); - } -} -// net_skeleton end -#endif // NOEMBED_NET_SKELETON - -#include - -#ifdef _WIN32 //////////////// Windows specific defines and includes -#include // For _lseeki64 -#include // For _mkdir -#ifndef S_ISDIR -#define S_ISDIR(x) ((x) & _S_IFDIR) -#endif -#ifdef stat -#undef stat -#endif -#ifdef lseek -#undef lseek -#endif -#ifdef popen -#undef popen -#endif -#ifdef pclose -#undef pclose -#endif -#define stat(x, y) mg_stat((x), (y)) -#define fopen(x, y) mg_fopen((x), (y)) -#define open(x, y, z) mg_open((x), (y), (z)) -#define close(x) _close(x) -#define fileno(x) _fileno(x) -#define lseek(x, y, z) _lseeki64((x), (y), (z)) -#define read(x, y, z) _read((x), (y), (z)) -#define write(x, y, z) _write((x), (y), (z)) -#define popen(x, y) _popen((x), (y)) -#define pclose(x) _pclose(x) -#define mkdir(x, y) _mkdir(x) -#define rmdir(x) _rmdir(x) -#define strdup(x) _strdup(x) -#ifndef __func__ -#define STRX(x) #x -#define STR(x) STRX(x) -#define __func__ __FILE__ ":" STR(__LINE__) -#endif -// find proper defines for this for VS and other compilers -#if defined(__USE_MINGW_ANSI_STDIO) -#define INT64_FMT "lld" -#else -#define INT64_FMT "I64d" -#endif -#define flockfile(x) ((void) (x)) -#define funlockfile(x) ((void) (x)) -typedef struct _stati64 file_stat_t; -typedef HANDLE process_id_t; - -#else ////////////// UNIX specific defines and includes - -#if !defined(MONGOOSE_NO_FILESYSTEM) &&\ - (!defined(MONGOOSE_NO_DAV) || !defined(MONGOOSE_NO_DIRECTORY_LISTING)) -#include -#endif -#if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_DL) -#include -#endif -#include -#include -#if !defined(O_BINARY) -#define O_BINARY 0 -#endif -#define INT64_FMT PRId64 -typedef struct stat file_stat_t; -typedef pid_t process_id_t; -#endif //////// End of platform-specific defines and includes - -#include "mongoose.h" - -#define MAX_REQUEST_SIZE 16384 -#define IOBUF_SIZE 8192 -#define MAX_PATH_SIZE 8192 -#define DEFAULT_CGI_PATTERN "**.cgi$|**.pl$|**.php$" -#define CGI_ENVIRONMENT_SIZE 8192 -#define MAX_CGI_ENVIR_VARS 64 -#define ENV_EXPORT_TO_CGI "MONGOOSE_CGI" -#define PASSWORDS_FILE_NAME ".htpasswd" - -#ifndef MONGOOSE_USE_WEBSOCKET_PING_INTERVAL -#define MONGOOSE_USE_WEBSOCKET_PING_INTERVAL 5 -#endif - -// Extra HTTP headers to send in every static file reply -#if !defined(MONGOOSE_USE_EXTRA_HTTP_HEADERS) -#define MONGOOSE_USE_EXTRA_HTTP_HEADERS "" -#endif - -#ifndef MONGOOSE_POST_SIZE_LIMIT -#define MONGOOSE_POST_SIZE_LIMIT 0 -#endif - -#ifndef MONGOOSE_IDLE_TIMEOUT_SECONDS -#define MONGOOSE_IDLE_TIMEOUT_SECONDS 300 -#endif - -#if defined(NS_DISABLE_SOCKETPAIR) && !defined(MONGOOSE_NO_CGI) -#define MONGOOSE_NO_CGI -#endif - -#ifdef MONGOOSE_NO_FILESYSTEM -#define MONGOOSE_NO_AUTH -#if !defined(MONGOOSE_NO_CGI) -#define MONGOOSE_NO_CGI -#endif -#define MONGOOSE_NO_DAV -#define MONGOOSE_NO_DIRECTORY_LISTING -#define MONGOOSE_NO_LOGGING -#define MONGOOSE_NO_SSI -#define MONGOOSE_NO_DL -#endif - -struct vec { - const char *ptr; - size_t len; -}; - -// For directory listing and WevDAV support -struct dir_entry { - struct connection *conn; - char *file_name; - file_stat_t st; -}; - -// NOTE(lsm): this enum should be in sync with the config_options. -enum { - ACCESS_CONTROL_LIST, -#ifndef MONGOOSE_NO_FILESYSTEM - ACCESS_LOG_FILE, -#ifndef MONGOOSE_NO_AUTH - AUTH_DOMAIN, -#endif -#ifndef MONGOOSE_NO_CGI - CGI_INTERPRETER, - CGI_PATTERN, -#endif - DAV_AUTH_FILE, - DAV_ROOT, - DOCUMENT_ROOT, -#ifndef MONGOOSE_NO_DIRECTORY_LISTING - ENABLE_DIRECTORY_LISTING, -#endif -#endif - ENABLE_PROXY, - EXTRA_MIME_TYPES, -#if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH) - GLOBAL_AUTH_FILE, -#endif -#ifndef MONGOOSE_NO_FILESYSTEM - HIDE_FILES_PATTERN, - HEXDUMP_FILE, - INDEX_FILES, -#endif - LISTENING_PORT, -#ifndef _WIN32 - RUN_AS_USER, -#endif -#ifndef MONGOOSE_NO_SSI - SSI_PATTERN, -#endif - URL_REWRITES, - NUM_OPTIONS -}; - -static const char *static_config_options[] = { - "access_control_list", NULL, -#ifndef MONGOOSE_NO_FILESYSTEM - "access_log_file", NULL, -#ifndef MONGOOSE_NO_AUTH - "auth_domain", "mydomain.com", -#endif -#ifndef MONGOOSE_NO_CGI - "cgi_interpreter", NULL, - "cgi_pattern", DEFAULT_CGI_PATTERN, -#endif - "dav_auth_file", NULL, - "dav_root", NULL, - "document_root", NULL, -#ifndef MONGOOSE_NO_DIRECTORY_LISTING - "enable_directory_listing", "yes", -#endif -#endif - "enable_proxy", NULL, - "extra_mime_types", NULL, -#if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH) - "global_auth_file", NULL, -#endif -#ifndef MONGOOSE_NO_FILESYSTEM - "hide_files_patterns", NULL, - "hexdump_file", NULL, - "index_files","index.html,index.htm,index.shtml,index.cgi,index.php", -#endif - "listening_port", NULL, -#ifndef _WIN32 - "run_as_user", NULL, -#endif -#ifndef MONGOOSE_NO_SSI - "ssi_pattern", "**.shtml$|**.shtm$", -#endif - "url_rewrites", NULL, - NULL -}; - -struct mg_server { - struct ns_mgr ns_mgr; - union socket_address lsa; // Listening socket address - mg_handler_t event_handler; - char *config_options[NUM_OPTIONS]; -}; - -// Local endpoint representation -union endpoint { - int fd; // Opened regular local file - struct ns_connection *nc; // CGI or proxy->target connection -}; - -enum endpoint_type { - EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT, EP_CLIENT, EP_PROXY -}; - -#define MG_HEADERS_SENT NSF_USER_1 -#define MG_USING_CHUNKED_API NSF_USER_2 -#define MG_CGI_CONN NSF_USER_3 -#define MG_PROXY_CONN NSF_USER_4 -#define MG_PROXY_DONT_PARSE NSF_USER_5 - -struct connection { - struct ns_connection *ns_conn; // NOTE(lsm): main.c depends on this order - struct mg_connection mg_conn; - struct mg_server *server; - union endpoint endpoint; - enum endpoint_type endpoint_type; - char *path_info; - char *request; - int64_t num_bytes_recv; // Total number of bytes received - int64_t cl; // Reply content length, for Range support - ssize_t request_len; // Request length, including last \r\n after last header -}; - -#define MG_CONN_2_CONN(c) ((struct connection *) ((char *) (c) - \ - offsetof(struct connection, mg_conn))) - -static void open_local_endpoint(struct connection *conn, int skip_user); -static void close_local_endpoint(struct connection *conn); -static void mg_ev_handler(struct ns_connection *nc, int ev, void *p); - -static const struct { - const char *extension; - size_t ext_len; - const char *mime_type; -} static_builtin_mime_types[] = { - {".html", 5, "text/html"}, - {".htm", 4, "text/html"}, - {".shtm", 5, "text/html"}, - {".shtml", 6, "text/html"}, - {".css", 4, "text/css"}, - {".js", 3, "application/javascript"}, - {".ico", 4, "image/x-icon"}, - {".gif", 4, "image/gif"}, - {".jpg", 4, "image/jpeg"}, - {".jpeg", 5, "image/jpeg"}, - {".png", 4, "image/png"}, - {".svg", 4, "image/svg+xml"}, - {".txt", 4, "text/plain"}, - {".torrent", 8, "application/x-bittorrent"}, - {".wav", 4, "audio/x-wav"}, - {".mp3", 4, "audio/x-mp3"}, - {".mid", 4, "audio/mid"}, - {".m3u", 4, "audio/x-mpegurl"}, - {".ogg", 4, "application/ogg"}, - {".ram", 4, "audio/x-pn-realaudio"}, - {".xml", 4, "text/xml"}, - {".json", 5, "application/json"}, - {".xslt", 5, "application/xml"}, - {".xsl", 4, "application/xml"}, - {".ra", 3, "audio/x-pn-realaudio"}, - {".doc", 4, "application/msword"}, - {".exe", 4, "application/octet-stream"}, - {".zip", 4, "application/x-zip-compressed"}, - {".xls", 4, "application/excel"}, - {".tgz", 4, "application/x-tar-gz"}, - {".tar", 4, "application/x-tar"}, - {".gz", 3, "application/x-gunzip"}, - {".arj", 4, "application/x-arj-compressed"}, - {".rar", 4, "application/x-rar-compressed"}, - {".rtf", 4, "application/rtf"}, - {".pdf", 4, "application/pdf"}, - {".swf", 4, "application/x-shockwave-flash"}, - {".mpg", 4, "video/mpeg"}, - {".webm", 5, "video/webm"}, - {".mpeg", 5, "video/mpeg"}, - {".mov", 4, "video/quicktime"}, - {".mp4", 4, "video/mp4"}, - {".m4v", 4, "video/x-m4v"}, - {".asf", 4, "video/x-ms-asf"}, - {".avi", 4, "video/x-msvideo"}, - {".bmp", 4, "image/bmp"}, - {".ttf", 4, "application/x-font-ttf"}, - {NULL, 0, NULL} -}; - -#ifdef MONGOOSE_ENABLE_THREADS -void *mg_start_thread(void *(*f)(void *), void *p) { - return ns_start_thread(f, p); -} -#endif // MONGOOSE_ENABLE_THREADS - -#ifndef MONGOOSE_NO_MMAP -#ifdef _WIN32 -static void *mmap(void *addr, int64_t len, int prot, int flags, int fd, - int offset) { - HANDLE fh = (HANDLE) _get_osfhandle(fd); - HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0); - void *p = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, (size_t) len); - CloseHandle(mh); - return p; -} -#define munmap(x, y) UnmapViewOfFile(x) -#define MAP_FAILED NULL -#define MAP_PRIVATE 0 -#define PROT_READ 0 -#elif defined(__OS2__) -static void *mmap(void *addr, int64_t len, int prot, int flags, int fd, - int offset) { - void *p; - - int pos = lseek( fd, 0, SEEK_CUR ); /* Get a current position */ - - if (pos == -1) - return NULL; - - /* Seek to offset offset */ - if (lseek( fd, offset, SEEK_SET) == -1) - return NULL; - - p = malloc(len); - - /* Read in a file */ - if (!p || read(fd, p, len) == -1) { - free(p); - p = NULL; - } - - /* Restore the position */ - lseek(fd, pos, SEEK_SET); - - return p; -} -#define munmap(x, y) free(x) -#define MAP_FAILED NULL -#define MAP_PRIVATE 0 -#define PROT_READ 0 -#else -#include -#endif - -void *mg_mmap(FILE *fp, size_t size) { - void *p = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fileno(fp), 0); - return p == MAP_FAILED ? NULL : p; -} - -void mg_munmap(void *p, size_t size) { - munmap(p, size); -} -#endif // MONGOOSE_NO_MMAP - -#if defined(_WIN32) && !defined(MONGOOSE_NO_FILESYSTEM) -// Encode 'path' which is assumed UTF-8 string, into UNICODE string. -// wbuf and wbuf_len is a target buffer and its length. -static void to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) { - char buf[MAX_PATH_SIZE * 2], buf2[MAX_PATH_SIZE * 2], *p; - - strncpy(buf, path, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; - - // Trim trailing slashes. Leave backslash for paths like "X:\" - p = buf + strlen(buf) - 1; - while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0'; - - // Convert to Unicode and back. If doubly-converted string does not - // match the original, something is fishy, reject. - memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); - WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), - NULL, NULL); - if (strcmp(buf, buf2) != 0) { - wbuf[0] = L'\0'; - } -} - -static int mg_stat(const char *path, file_stat_t *st) { - wchar_t wpath[MAX_PATH_SIZE]; - to_wchar(path, wpath, ARRAY_SIZE(wpath)); - DBG(("[%ls] -> %d", wpath, _wstati64(wpath, st))); - return _wstati64(wpath, st); -} - -static FILE *mg_fopen(const char *path, const char *mode) { - wchar_t wpath[MAX_PATH_SIZE], wmode[10]; - to_wchar(path, wpath, ARRAY_SIZE(wpath)); - to_wchar(mode, wmode, ARRAY_SIZE(wmode)); - return _wfopen(wpath, wmode); -} - -static int mg_open(const char *path, int flag, int mode) { - wchar_t wpath[MAX_PATH_SIZE]; - to_wchar(path, wpath, ARRAY_SIZE(wpath)); - return _wopen(wpath, flag, mode); -} -#endif // _WIN32 && !MONGOOSE_NO_FILESYSTEM - -// A helper function for traversing a comma separated list of values. -// It returns a list pointer shifted to the next value, or NULL if the end -// of the list found. -// Value is stored in val vector. If value has form "x=y", then eq_val -// vector is initialized to point to the "y" part, and val vector length -// is adjusted to point only to "x". -static const char *next_option(const char *list, struct vec *val, - struct vec *eq_val) { - if (list == NULL || *list == '\0') { - // End of the list - list = NULL; - } else { - val->ptr = list; - if ((list = strchr(val->ptr, ',')) != NULL) { - // Comma found. Store length and shift the list ptr - val->len = list - val->ptr; - list++; - } else { - // This value is the last one - list = val->ptr + strlen(val->ptr); - val->len = list - val->ptr; - } - - if (eq_val != NULL) { - // Value has form "x=y", adjust pointers and lengths - // so that val points to "x", and eq_val points to "y". - eq_val->len = 0; - eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len); - if (eq_val->ptr != NULL) { - eq_val->ptr++; // Skip over '=' character - eq_val->len = val->ptr + val->len - eq_val->ptr; - val->len = (eq_val->ptr - val->ptr) - 1; - } - } - } - - return list; -} - -// Like snprintf(), but never returns negative value, or a value -// that is larger than a supplied buffer. -static int mg_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap) { - int n; - if (buflen < 1) return 0; - n = vsnprintf(buf, buflen, fmt, ap); - if (n < 0) { - n = 0; - } else if (n >= (int) buflen) { - n = (int) buflen - 1; - } - buf[n] = '\0'; - return n; -} - -static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) { - va_list ap; - int n; - va_start(ap, fmt); - n = mg_vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - return n; -} - -// Check whether full request is buffered. Return: -// -1 if request is malformed -// 0 if request is not yet fully buffered -// >0 actual request length, including last \r\n\r\n -static int get_request_len(const char *s, size_t buf_len) { - const unsigned char *buf = (unsigned char *) s; - size_t i; - - for (i = 0; i < buf_len; i++) { - // Control characters are not allowed but >=128 are. - // Abort scan as soon as one malformed character is found. - if (!isprint(buf[i]) && buf[i] != '\r' && buf[i] != '\n' && buf[i] < 128) { - return -1; - } else if (buf[i] == '\n' && i + 1 < buf_len && buf[i + 1] == '\n') { - return i + 2; - } else if (buf[i] == '\n' && i + 2 < buf_len && buf[i + 1] == '\r' && - buf[i + 2] == '\n') { - return i + 3; - } - } - - return 0; -} - -// Skip the characters until one of the delimiters characters found. -// 0-terminate resulting word. Skip the rest of the delimiters if any. -// Advance pointer to buffer to the next word. Return found 0-terminated word. -static char *skip(char **buf, const char *delimiters) { - char *p, *begin_word, *end_word, *end_delimiters; - - begin_word = *buf; - end_word = begin_word + strcspn(begin_word, delimiters); - end_delimiters = end_word + strspn(end_word, delimiters); - - for (p = end_word; p < end_delimiters; p++) { - *p = '\0'; - } - - *buf = end_delimiters; - - return begin_word; -} - -// Parse HTTP headers from the given buffer, advance buffer to the point -// where parsing stopped. -static void parse_http_headers(char **buf, struct mg_connection *ri) { - size_t i; - - for (i = 0; i < ARRAY_SIZE(ri->http_headers); i++) { - ri->http_headers[i].name = skip(buf, ": "); - ri->http_headers[i].value = skip(buf, "\r\n"); - if (ri->http_headers[i].name[0] == '\0') - break; - ri->num_headers = i + 1; - } -} - -static const char *status_code_to_str(int status_code) { - switch (status_code) { - - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 102: return "Processing"; - - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 208: return "Already Reported"; - case 226: return "IM Used"; - - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 306: return "Switch Proxy"; - case 307: return "Temporary Redirect"; - case 308: return "Permanent Redirect"; - - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Payload Too Large"; - case 414: return "URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 418: return "I\'m a teapot"; - case 422: return "Unprocessable Entity"; - case 423: return "Locked"; - case 424: return "Failed Dependency"; - case 426: return "Upgrade Required"; - case 428: return "Precondition Required"; - case 429: return "Too Many Requests"; - case 431: return "Request Header Fields Too Large"; - case 451: return "Unavailable For Legal Reasons"; - - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "HTTP Version Not Supported"; - case 506: return "Variant Also Negotiates"; - case 507: return "Insufficient Storage"; - case 508: return "Loop Detected"; - case 510: return "Not Extended"; - case 511: return "Network Authentication Required"; - - default: return "Server Error"; - } -} - -static int call_user(struct connection *conn, enum mg_event ev) { - return conn != NULL && conn->server != NULL && - conn->server->event_handler != NULL ? - conn->server->event_handler(&conn->mg_conn, ev) : MG_FALSE; -} - -static void send_http_error(struct connection *conn, int code, - const char *fmt, ...) { - const char *message = status_code_to_str(code); - const char *rewrites = conn->server->config_options[URL_REWRITES]; - char headers[200], body[200]; - struct vec a, b; - va_list ap; - int body_len, headers_len, match_code; - - conn->mg_conn.status_code = code; - - // Invoke error handler if it is set - if (call_user(conn, MG_HTTP_ERROR) == MG_TRUE) { - close_local_endpoint(conn); - return; - } - - // Handle error code rewrites - while ((rewrites = next_option(rewrites, &a, &b)) != NULL) { - if ((match_code = atoi(a.ptr)) > 0 && match_code == code) { - struct mg_connection *c = &conn->mg_conn; - c->status_code = 302; - mg_printf(c, "HTTP/1.1 %d Moved\r\n" - "Location: %.*s?code=%d&orig_uri=%s&query_string=%s\r\n\r\n", - c->status_code, b.len, b.ptr, code, c->uri, - c->query_string == NULL ? "" : c->query_string); - close_local_endpoint(conn); - return; - } - } - - body_len = mg_snprintf(body, sizeof(body), "%d %s\n", code, message); - if (fmt != NULL) { - va_start(ap, fmt); - body_len += mg_vsnprintf(body + body_len, sizeof(body) - body_len, fmt, ap); - va_end(ap); - } - if ((code >= 300 && code <= 399) || code == 204) { - // 3xx errors do not have body - body_len = 0; - } - headers_len = mg_snprintf(headers, sizeof(headers), - "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n" - "Content-Type: text/plain\r\n\r\n", - code, message, body_len); - ns_send(conn->ns_conn, headers, headers_len); - ns_send(conn->ns_conn, body, body_len); - close_local_endpoint(conn); // This will write to the log file -} - -static void write_chunk(struct connection *conn, const char *buf, int len) { - char chunk_size[50]; - int n = mg_snprintf(chunk_size, sizeof(chunk_size), "%X\r\n", len); - ns_send(conn->ns_conn, chunk_size, n); - ns_send(conn->ns_conn, buf, len); - ns_send(conn->ns_conn, "\r\n", 2); -} - -size_t mg_printf(struct mg_connection *conn, const char *fmt, ...) { - va_list ap; - int ret; - - va_start(ap, fmt); - ret = mg_vprintf(conn, fmt, ap); - va_end(ap); - - return ret; -} - -size_t mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap) { - struct connection *c = MG_CONN_2_CONN(conn); - - ns_vprintf(c->ns_conn, fmt, ap); - - return c->ns_conn->send_iobuf.len; -} - -static void ns_forward(struct ns_connection *from, struct ns_connection *to) { - DBG(("%p -> %p %lu bytes", from, to, (unsigned long)from->recv_iobuf.len)); - ns_send(to, from->recv_iobuf.buf, from->recv_iobuf.len); - iobuf_remove(&from->recv_iobuf, from->recv_iobuf.len); -} - -#ifndef MONGOOSE_NO_CGI -#ifdef _WIN32 -struct threadparam { - sock_t s; - HANDLE hPipe; -}; - -static int wait_until_ready(sock_t sock, int for_read) { - fd_set set; - if ( (sock == INVALID_SOCKET) || (sock >= FD_SETSIZE) ) - return 0; - FD_ZERO(&set); - FD_SET(sock, &set); - select(sock + 1, for_read ? &set : 0, for_read ? 0 : &set, 0, 0); - return 1; -} - -static void *push_to_stdin(void *arg) { - struct threadparam *tp = (struct threadparam *)arg; - int n, sent, stop = 0; - DWORD k; - char buf[IOBUF_SIZE]; - - while (!stop && wait_until_ready(tp->s, 1) && - (n = recv(tp->s, buf, sizeof(buf), 0)) > 0) { - if (n == -1 && GetLastError() == WSAEWOULDBLOCK) continue; - for (sent = 0; !stop && sent < n; sent += k) { - if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1; - } - } - DBG(("%s", "FORWARDED EVERYTHING TO CGI")); - CloseHandle(tp->hPipe); - NS_FREE(tp); - _endthread(); - return NULL; -} - -static void *pull_from_stdout(void *arg) { - struct threadparam *tp = (struct threadparam *)arg; - int k = 0, stop = 0; - DWORD n, sent; - char buf[IOBUF_SIZE]; - - while (!stop && ReadFile(tp->hPipe, buf, sizeof(buf), &n, NULL)) { - for (sent = 0; !stop && sent < n; sent += k) { - if (wait_until_ready(tp->s, 0) && - (k = send(tp->s, buf + sent, n - sent, 0)) <= 0) stop = 1; - } - } - DBG(("%s", "EOF FROM CGI")); - CloseHandle(tp->hPipe); - shutdown(tp->s, 2); // Without this, IO thread may get truncated data - closesocket(tp->s); - NS_FREE(tp); - _endthread(); - return NULL; -} - -static void spawn_stdio_thread(sock_t sock, HANDLE hPipe, - void *(*func)(void *)) { - struct threadparam *tp = (struct threadparam *)NS_MALLOC(sizeof(*tp)); - if (tp != NULL) { - tp->s = sock; - tp->hPipe = hPipe; - mg_start_thread(func, tp); - } -} - -static void abs_path(const char *utf8_path, char *abs_path, size_t len) { - wchar_t buf[MAX_PATH_SIZE], buf2[MAX_PATH_SIZE]; - to_wchar(utf8_path, buf, ARRAY_SIZE(buf)); - GetFullPathNameW(buf, ARRAY_SIZE(buf2), buf2, NULL); - WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0); -} - -static process_id_t start_process(char *interp, const char *cmd, - const char *env, const char *envp[], - const char *dir, sock_t sock) { - STARTUPINFOW si; - PROCESS_INFORMATION pi; - HANDLE a[2], b[2], me = GetCurrentProcess(); - wchar_t wcmd[MAX_PATH_SIZE], full_dir[MAX_PATH_SIZE]; - char buf[MAX_PATH_SIZE], buf4[MAX_PATH_SIZE], buf5[MAX_PATH_SIZE], - cmdline[MAX_PATH_SIZE], *p; - DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; - FILE *fp; - - memset(&si, 0, sizeof(si)); - memset(&pi, 0, sizeof(pi)); - - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - CreatePipe(&a[0], &a[1], NULL, 0); - CreatePipe(&b[0], &b[1], NULL, 0); - DuplicateHandle(me, a[0], me, &si.hStdInput, 0, TRUE, flags); - DuplicateHandle(me, b[1], me, &si.hStdOutput, 0, TRUE, flags); - - if (interp == NULL && (fp = fopen(cmd, "r")) != NULL) { - buf[0] = buf[1] = '\0'; - fgets(buf, sizeof(buf), fp); - buf[sizeof(buf) - 1] = '\0'; - if (buf[0] == '#' && buf[1] == '!') { - interp = buf + 2; - for (p = interp + strlen(interp) - 1; - isspace(* (uint8_t *) p) && p > interp; p--) *p = '\0'; - } - fclose(fp); - } - - if (interp != NULL) { - abs_path(interp, buf4, ARRAY_SIZE(buf4)); - interp = buf4; - } - abs_path(dir, buf5, ARRAY_SIZE(buf5)); - to_wchar(dir, full_dir, ARRAY_SIZE(full_dir)); - mg_snprintf(cmdline, sizeof(cmdline), "%s%s\"%s\"", - interp ? interp : "", interp ? " " : "", cmd); - to_wchar(cmdline, wcmd, ARRAY_SIZE(wcmd)); - - if (CreateProcessW(NULL, wcmd, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, - (void *) env, full_dir, &si, &pi) != 0) { - spawn_stdio_thread(sock, a[1], push_to_stdin); - spawn_stdio_thread(sock, b[0], pull_from_stdout); - } else { - CloseHandle(a[1]); - CloseHandle(b[0]); - closesocket(sock); - } - DBG(("CGI command: [%ls] -> %p", wcmd, pi.hProcess)); - - // Not closing a[0] and b[1] because we've used DUPLICATE_CLOSE_SOURCE - CloseHandle(si.hStdOutput); - CloseHandle(si.hStdInput); - //CloseHandle(pi.hThread); - //CloseHandle(pi.hProcess); - - return pi.hProcess; -} -#else -static process_id_t start_process(const char *interp, const char *cmd, - const char *env, const char *envp[], - const char *dir, sock_t sock) { - char buf[500]; - process_id_t pid = fork(); - (void) env; - - if (pid == 0) { - (void) chdir(dir); - (void) dup2(sock, 0); - (void) dup2(sock, 1); - closesocket(sock); - - // After exec, all signal handlers are restored to their default values, - // with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's - // implementation, SIGCHLD's handler will leave unchanged after exec - // if it was set to be ignored. Restore it to default action. - signal(SIGCHLD, SIG_DFL); - - if (interp == NULL) { - execle(cmd, cmd, (char *) 0, envp); // Using (char *) 0 to avoid warning - } else { - execle(interp, interp, cmd, (char *) 0, envp); - } - snprintf(buf, sizeof(buf), "Status: 500\r\n\r\n" - "500 Server Error: %s%s%s: %s", interp == NULL ? "" : interp, - interp == NULL ? "" : " ", cmd, strerror(errno)); - send(1, buf, strlen(buf), 0); - exit(EXIT_FAILURE); // exec call failed - } - - return pid; -} -#endif // _WIN32 - -// This structure helps to create an environment for the spawned CGI program. -// Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings, -// last element must be NULL. -// However, on Windows there is a requirement that all these VARIABLE=VALUE\0 -// strings must reside in a contiguous buffer. The end of the buffer is -// marked by two '\0' characters. -// We satisfy both worlds: we create an envp array (which is vars), all -// entries are actually pointers inside buf. -struct cgi_env_block { - struct mg_connection *conn; - char buf[CGI_ENVIRONMENT_SIZE]; // Environment buffer - const char *vars[MAX_CGI_ENVIR_VARS]; // char *envp[] - int len; // Space taken - int nvars; // Number of variables in envp[] -}; - -// Append VARIABLE=VALUE\0 string to the buffer, and add a respective -// pointer into the vars array. -static char *addenv(struct cgi_env_block *block, const char *fmt, ...) { - int n, space; - char *added; - va_list ap; - - // Calculate how much space is left in the buffer - space = sizeof(block->buf) - block->len - 2; - assert(space >= 0); - - // Make a pointer to the free space int the buffer - added = block->buf + block->len; - - // Copy VARIABLE=VALUE\0 string into the free space - va_start(ap, fmt); - n = mg_vsnprintf(added, (size_t) space, fmt, ap); - va_end(ap); - - // Make sure we do not overflow buffer and the envp array - if (n > 0 && n + 1 < space && - block->nvars < (int) ARRAY_SIZE(block->vars) - 2) { - // Append a pointer to the added string into the envp array - block->vars[block->nvars++] = added; - // Bump up used length counter. Include \0 terminator - block->len += n + 1; - } - - return added; -} - -static void addenv2(struct cgi_env_block *blk, const char *name) { - const char *s; - if ((s = getenv(name)) != NULL) addenv(blk, "%s=%s", name, s); -} - -static void prepare_cgi_environment(struct connection *conn, - const char *prog, - struct cgi_env_block *blk) { - struct mg_connection *ri = &conn->mg_conn; - const char *s, *slash; - char *p, **opts = conn->server->config_options; - int i; - - blk->len = blk->nvars = 0; - blk->conn = ri; - - if ((s = getenv("SERVER_NAME")) != NULL) { - addenv(blk, "SERVER_NAME=%s", s); - } else { - addenv(blk, "SERVER_NAME=%s", ri->local_ip); - } - addenv(blk, "SERVER_ROOT=%s", opts[DOCUMENT_ROOT]); - addenv(blk, "DOCUMENT_ROOT=%s", opts[DOCUMENT_ROOT]); - addenv(blk, "SERVER_SOFTWARE=%s/%s", "Mongoose", MONGOOSE_VERSION); - - // Prepare the environment block - addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1"); - addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1"); - addenv(blk, "%s", "REDIRECT_STATUS=200"); // For PHP - - // TODO(lsm): fix this for IPv6 case - //addenv(blk, "SERVER_PORT=%d", ri->remote_port); - - addenv(blk, "REQUEST_METHOD=%s", ri->request_method); - addenv(blk, "REMOTE_ADDR=%s", ri->remote_ip); - addenv(blk, "REMOTE_PORT=%d", ri->remote_port); - addenv(blk, "REQUEST_URI=%s%s%s", ri->uri, - ri->query_string == NULL ? "" : "?", - ri->query_string == NULL ? "" : ri->query_string); - - // SCRIPT_NAME - if (conn->path_info != NULL) { - addenv(blk, "SCRIPT_NAME=%.*s", - (int) (strlen(ri->uri) - strlen(conn->path_info)), ri->uri); - addenv(blk, "PATH_INFO=%s", conn->path_info); - } else { - s = strrchr(prog, '/'); - slash = strrchr(ri->uri, '/'); - addenv(blk, "SCRIPT_NAME=%.*s%s", - slash == NULL ? 0 : (int) (slash - ri->uri), ri->uri, - s == NULL ? prog : s); - } - - addenv(blk, "SCRIPT_FILENAME=%s", prog); - addenv(blk, "PATH_TRANSLATED=%s", prog); - addenv(blk, "HTTPS=%s", conn->ns_conn->ssl != NULL ? "on" : "off"); - - if ((s = mg_get_header(ri, "Content-Type")) != NULL) - addenv(blk, "CONTENT_TYPE=%s", s); - - if (ri->query_string != NULL) - addenv(blk, "QUERY_STRING=%s", ri->query_string); - - if ((s = mg_get_header(ri, "Content-Length")) != NULL) - addenv(blk, "CONTENT_LENGTH=%s", s); - - addenv2(blk, "PATH"); - addenv2(blk, "TMP"); - addenv2(blk, "TEMP"); - addenv2(blk, "TMPDIR"); - addenv2(blk, "PERLLIB"); - addenv2(blk, ENV_EXPORT_TO_CGI); - -#if defined(_WIN32) - addenv2(blk, "COMSPEC"); - addenv2(blk, "SYSTEMROOT"); - addenv2(blk, "SystemDrive"); - addenv2(blk, "ProgramFiles"); - addenv2(blk, "ProgramFiles(x86)"); - addenv2(blk, "CommonProgramFiles(x86)"); -#else - addenv2(blk, "LD_LIBRARY_PATH"); -#endif // _WIN32 - - // Add all headers as HTTP_* variables - for (i = 0; i < ri->num_headers; i++) { - p = addenv(blk, "HTTP_%s=%s", - ri->http_headers[i].name, ri->http_headers[i].value); - - // Convert variable name into uppercase, and change - to _ - for (; *p != '=' && *p != '\0'; p++) { - if (*p == '-') - *p = '_'; - *p = (char) toupper(* (unsigned char *) p); - } - } - - blk->vars[blk->nvars++] = NULL; - blk->buf[blk->len++] = '\0'; - - assert(blk->nvars < (int) ARRAY_SIZE(blk->vars)); - assert(blk->len > 0); - assert(blk->len < (int) sizeof(blk->buf)); -} - -static const char cgi_status[] = "HTTP/1.1 200 OK\r\n"; - -static void open_cgi_endpoint(struct connection *conn, const char *prog) { - struct cgi_env_block blk; - char dir[MAX_PATH_SIZE]; - const char *p; - sock_t fds[2]; - - prepare_cgi_environment(conn, prog, &blk); - // CGI must be executed in its own directory. 'dir' must point to the - // directory containing executable program, 'p' must point to the - // executable program name relative to 'dir'. - if ((p = strrchr(prog, '/')) == NULL) { - mg_snprintf(dir, sizeof(dir), "%s", "."); - } else { - mg_snprintf(dir, sizeof(dir), "%.*s", (int) (p - prog), prog); - } - - // Try to create socketpair in a loop until success. ns_socketpair() - // can be interrupted by a signal and fail. - // TODO(lsm): use sigaction to restart interrupted syscall - { - int attempts = 0, max_attempts = NS_MAX_SOCKETPAIR_ATTEMPTS; - do { - ns_socketpair(fds); - } while (fds[0] == INVALID_SOCKET && ++attempts < max_attempts); - - if (fds[0] == INVALID_SOCKET) { - closesocket(fds[0]); - send_http_error(conn, 500, "ns_socketpair() failed"); - } - } - - if (start_process(conn->server->config_options[CGI_INTERPRETER], - prog, blk.buf, blk.vars, dir, fds[1]) != 0) { - conn->endpoint_type = EP_CGI; - conn->endpoint.nc = ns_add_sock(&conn->server->ns_mgr, fds[0], - mg_ev_handler, conn); - conn->endpoint.nc->flags |= MG_CGI_CONN; - ns_send(conn->ns_conn, cgi_status, sizeof(cgi_status) - 1); - conn->mg_conn.status_code = 200; - conn->ns_conn->flags |= NSF_BUFFER_BUT_DONT_SEND; - // Pass POST data to the CGI process - conn->endpoint.nc->send_iobuf = conn->ns_conn->recv_iobuf; - iobuf_init(&conn->ns_conn->recv_iobuf, 0); - } else { - closesocket(fds[0]); - send_http_error(conn, 500, "start_process(%s) failed", prog); - } - -#ifndef _WIN32 - closesocket(fds[1]); // On Windows, CGI stdio thread closes that socket -#endif -} - -static void on_cgi_data(struct ns_connection *nc) { - struct connection *conn = (struct connection *) nc->user_data; - const char *status = "500"; - struct mg_connection c; - - if (!conn) return; - - // Copy CGI data from CGI socket to the client send buffer - ns_forward(nc, conn->ns_conn); - - // If reply has not been parsed yet, parse it - if (conn->ns_conn->flags & NSF_BUFFER_BUT_DONT_SEND) { - struct iobuf *io = &conn->ns_conn->send_iobuf; - size_t s_len = sizeof(cgi_status) - 1; - int len = get_request_len(io->buf + s_len, io->len - s_len); - char buf[MAX_REQUEST_SIZE], *s = buf; - - if (len == 0) return; - - if (len < 0 || len > (int) sizeof(buf)) { - len = io->len; - iobuf_remove(io, io->len); - send_http_error(conn, 500, "CGI program sent malformed headers: [%.*s]", - len, io->buf); - } else { - memset(&c, 0, sizeof(c)); - memcpy(buf, io->buf + s_len, len); - buf[len - 1] = '\0'; - parse_http_headers(&s, &c); - if (mg_get_header(&c, "Location") != NULL) { - status = "302"; - } else if ((status = (char *) mg_get_header(&c, "Status")) == NULL) { - status = "200"; - } - memcpy(io->buf + 9, status, 3); - conn->mg_conn.status_code = atoi(status); - } - conn->ns_conn->flags &= ~NSF_BUFFER_BUT_DONT_SEND; - } -} -#endif // !MONGOOSE_NO_CGI - -static char *mg_strdup(const char *str) { - char *copy = (char *) NS_MALLOC(strlen(str) + 1); - if (copy != NULL) { - strcpy(copy, str); - } - return copy; -} - -static int isbyte(int n) { - return n >= 0 && n <= 255; -} - -static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) { - int n, a, b, c, d, slash = 32, len = 0; - - if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 || - sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && - isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && - slash >= 0 && slash < 33) { - len = n; - *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d; - *mask = slash ? 0xffffffffU << (32 - slash) : 0; - } - - return len; -} - -// Verify given socket address against the ACL. -// Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. -static int check_acl(const char *acl, uint32_t remote_ip) { - int allowed, flag; - uint32_t net, mask; - struct vec vec; - - // If any ACL is set, deny by default - allowed = acl == NULL ? '+' : '-'; - - while ((acl = next_option(acl, &vec, NULL)) != NULL) { - flag = vec.ptr[0]; - if ((flag != '+' && flag != '-') || - parse_net(&vec.ptr[1], &net, &mask) == 0) { - return -1; - } - - if (net == (remote_ip & mask)) { - allowed = flag; - } - } - - return allowed == '+'; -} - -// Protect against directory disclosure attack by removing '..', -// excessive '/' and '\' characters -static void remove_double_dots_and_double_slashes(char *s) { - char *p = s; - - while (*s != '\0') { - *p++ = *s++; - if (s[-1] == '/' || s[-1] == '\\') { - // Skip all following slashes, backslashes and double-dots - while (s[0] != '\0') { - if (s[0] == '/' || s[0] == '\\') { s++; } - else if (s[0] == '.' && (s[1] == '/' || s[1] == '\\')) { s += 2; } - else if (s[0] == '.' && s[1] == '.' && s[2] == '\0') { s += 2; } - else if (s[0] == '.' && s[1] == '.' && (s[2] == '/' || s[2] == '\\')) { s += 3; } - else { break; } - } - } - } - *p = '\0'; -} - -int mg_url_decode(const char *src, size_t src_len, char *dst, - size_t dst_len, int is_form_url_encoded) { - size_t i, j = 0; - int a, b; -#define HEXTOI(x) (isdigit(x) ? (x) - '0' : (x) - 'W') - - for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { - if (src[i] == '%' && i + 2 < src_len && - isxdigit(* (const unsigned char *) (src + i + 1)) && - isxdigit(* (const unsigned char *) (src + i + 2))) { - a = tolower(* (const unsigned char *) (src + i + 1)); - b = tolower(* (const unsigned char *) (src + i + 2)); - dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b)); - i += 2; - } else if (is_form_url_encoded && src[i] == '+') { - dst[j] = ' '; - } else { - dst[j] = src[i]; - } - } - - dst[j] = '\0'; // Null-terminate the destination - - return i >= src_len ? j : -1; -} - -static int is_valid_http_method(const char *s) { - return !strcmp(s, "GET") || !strcmp(s, "POST") || !strcmp(s, "HEAD") || - !strcmp(s, "CONNECT") || !strcmp(s, "PUT") || !strcmp(s, "DELETE") || - !strcmp(s, "OPTIONS") || !strcmp(s, "PROPFIND") || !strcmp(s, "MKCOL") || - !strcmp(s, "PATCH"); -} - -// Parse HTTP request, fill in mg_request structure. -// This function modifies the buffer by NUL-terminating -// HTTP request components, header names and header values. -// Note that len must point to the last \n of HTTP headers. -static size_t parse_http_message(char *buf, size_t len, - struct mg_connection *ri) { - int is_request, n; - - // Reset the connection. Make sure that we don't touch fields that are - // set elsewhere: remote_ip, remote_port, server_param - ri->request_method = ri->uri = ri->http_version = ri->query_string = NULL; - ri->num_headers = ri->status_code = ri->is_websocket = ri->content_len = 0; - - if (len < 1) return ~0; - - buf[len - 1] = '\0'; - - // RFC says that all initial whitespaces should be ignored - while (*buf != '\0' && isspace(* (unsigned char *) buf)) { - buf++; - } - ri->request_method = skip(&buf, " "); - ri->uri = skip(&buf, " "); - ri->http_version = skip(&buf, "\r\n"); - - // HTTP message could be either HTTP request or HTTP response, e.g. - // "GET / HTTP/1.0 ...." or "HTTP/1.0 200 OK ..." - is_request = is_valid_http_method(ri->request_method); - if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0) || - (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) { - len = ~0; - } else { - if (is_request) { - ri->http_version += 5; - } else { - ri->status_code = atoi(ri->uri); - } - parse_http_headers(&buf, ri); - - if ((ri->query_string = strchr(ri->uri, '?')) != NULL) { - *(char *) ri->query_string++ = '\0'; - } - n = (int) strlen(ri->uri); - mg_url_decode(ri->uri, n, (char *) ri->uri, n + 1, 0); - if (*ri->uri == '/' || *ri->uri == '.') { - remove_double_dots_and_double_slashes((char *) ri->uri); - } - } - - return len; -} - -static int lowercase(const char *s) { - return tolower(* (const unsigned char *) s); -} - -static int mg_strcasecmp(const char *s1, const char *s2) { - int diff; - - do { - diff = lowercase(s1++) - lowercase(s2++); - } while (diff == 0 && s1[-1] != '\0'); - - return diff; -} - -static int mg_strncasecmp(const char *s1, const char *s2, size_t len) { - int diff = 0; - - if (len > 0) - do { - diff = lowercase(s1++) - lowercase(s2++); - } while (diff == 0 && s1[-1] != '\0' && --len > 0); - - return diff; -} - -// Return HTTP header value, or NULL if not found. -const char *mg_get_header(const struct mg_connection *ri, const char *s) { - int i; - - for (i = 0; i < ri->num_headers; i++) - if (!mg_strcasecmp(s, ri->http_headers[i].name)) - return ri->http_headers[i].value; - - return NULL; -} - -// Perform case-insensitive match of string against pattern -int mg_match_prefix(const char *pattern, ssize_t pattern_len, const char *str) { - const char *or_str; - int len, res, i = 0, j = 0; - - if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) { - res = mg_match_prefix(pattern, or_str - pattern, str); - return res > 0 ? res : mg_match_prefix(or_str + 1, - (pattern + pattern_len) - (or_str + 1), str); - } - - for (; i < pattern_len; i++, j++) { - if (pattern[i] == '?' && str[j] != '\0') { - continue; - } else if (pattern[i] == '$') { - return str[j] == '\0' ? j : -1; - } else if (pattern[i] == '*') { - i++; - if (pattern[i] == '*') { - i++; - len = (int) strlen(str + j); - } else { - len = (int) strcspn(str + j, "/"); - } - if (i == pattern_len) { - return j + len; - } - do { - res = mg_match_prefix(pattern + i, pattern_len - i, str + j + len); - } while (res == -1 && len-- > 0); - return res == -1 ? -1 : j + res + len; - } else if (lowercase(&pattern[i]) != lowercase(&str[j])) { - return -1; - } - } - return j; -} - -// This function prints HTML pages, and expands "{{something}}" blocks -// inside HTML by calling appropriate callback functions. -// Note that {{@path/to/file}} construct outputs embedded file's contents, -// which provides SSI-like functionality. -void mg_template(struct mg_connection *conn, const char *s, - struct mg_expansion *expansions) { - int i, j, pos = 0, inside_marker = 0; - - for (i = 0; s[i] != '\0'; i++) { - if (inside_marker == 0 && !memcmp(&s[i], "{{", 2)) { - if (i > pos) { - mg_send_data(conn, &s[pos], i - pos); - } - pos = i; - inside_marker = 1; - } - if (inside_marker == 1 && !memcmp(&s[i], "}}", 2)) { - for (j = 0; expansions[j].keyword != NULL; j++) { - const char *kw = expansions[j].keyword; - if ((int) strlen(kw) == i - (pos + 2) && - memcmp(kw, &s[pos + 2], i - (pos + 2)) == 0) { - expansions[j].handler(conn); - pos = i + 2; - break; - } - } - inside_marker = 0; - } - } - if (i > pos) { - mg_send_data(conn, &s[pos], i - pos); - } -} - -#ifndef MONGOOSE_NO_FILESYSTEM -static int is_dav_request(const struct connection *conn) { - const char *s = conn->mg_conn.request_method; - return !strcmp(s, "PUT") || !strcmp(s, "DELETE") || - !strcmp(s, "MKCOL") || !strcmp(s, "PROPFIND"); -} - -static int must_hide_file(struct connection *conn, const char *path) { - const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$"; - const char *pattern = conn->server->config_options[HIDE_FILES_PATTERN]; - return mg_match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 || - (pattern != NULL && mg_match_prefix(pattern, strlen(pattern), path) > 0); -} - -// Return 1 if real file has been found, 0 otherwise -static int convert_uri_to_file_name(struct connection *conn, char *buf, - size_t buf_len, file_stat_t *st) { - struct vec a, b; - const char *rewrites = conn->server->config_options[URL_REWRITES]; - const char *root = -#ifndef MONGOOSE_NO_DAV - is_dav_request(conn) && conn->server->config_options[DAV_ROOT] != NULL ? - conn->server->config_options[DAV_ROOT] : -#endif - conn->server->config_options[DOCUMENT_ROOT]; -#ifndef MONGOOSE_NO_CGI - const char *cgi_pat = conn->server->config_options[CGI_PATTERN]; - char *p; -#endif - const char *uri = conn->mg_conn.uri; - const char *domain = mg_get_header(&conn->mg_conn, "Host"); - // Important: match_len has to be declared as int, unless rewrites break. - int match_len, root_len = root == NULL ? 0 : strlen(root); - - // Perform virtual hosting rewrites - if (rewrites != NULL && domain != NULL) { - const char *colon = strchr(domain, ':'); - size_t domain_len = colon == NULL ? strlen(domain) : colon - domain; - - while ((rewrites = next_option(rewrites, &a, &b)) != NULL) { - if (a.len > 1 && a.ptr[0] == '@' && a.len == domain_len + 1 && - mg_strncasecmp(a.ptr + 1, domain, domain_len) == 0) { - root = b.ptr; - root_len = b.len; - break; - } - } - } - - // No filesystem access - if (root == NULL || root_len == 0) return 0; - - // Handle URL rewrites - mg_snprintf(buf, buf_len, "%.*s%s", root_len, root, uri); - rewrites = conn->server->config_options[URL_REWRITES]; // Re-initialize! - while ((rewrites = next_option(rewrites, &a, &b)) != NULL) { - if ((match_len = mg_match_prefix(a.ptr, a.len, uri)) > 0) { - mg_snprintf(buf, buf_len, "%.*s%s", (int) b.len, b.ptr, uri + match_len); - break; - } - } - - if (stat(buf, st) == 0) return 1; - -#ifndef MONGOOSE_NO_CGI - // Support PATH_INFO for CGI scripts. - for (p = buf + strlen(root) + 2; *p != '\0'; p++) { - if (*p == '/') { - *p = '\0'; - if (mg_match_prefix(cgi_pat, strlen(cgi_pat), buf) > 0 && - !stat(buf, st)) { - DBG(("!!!! [%s]", buf)); - *p = '/'; - conn->path_info = mg_strdup(p); - *p = '\0'; - return 1; - } - *p = '/'; - } - } -#endif - - return 0; -} -#endif // MONGOOSE_NO_FILESYSTEM - -static int should_keep_alive(const struct mg_connection *conn) { - struct connection *c = MG_CONN_2_CONN(conn); - const char *method = conn->request_method; - const char *http_version = conn->http_version; - const char *header = mg_get_header(conn, "Connection"); - return method != NULL && - (!strcmp(method, "GET") || c->endpoint_type == EP_USER) && - ((header != NULL && !mg_strcasecmp(header, "keep-alive")) || - (header == NULL && http_version && !strcmp(http_version, "1.1"))); -} - -size_t mg_write(struct mg_connection *c, const void *buf, size_t len) { - struct connection *conn = MG_CONN_2_CONN(c); - ns_send(conn->ns_conn, buf, len); - return conn->ns_conn->send_iobuf.len; -} - -void mg_send_status(struct mg_connection *c, int status) { - struct connection *conn = MG_CONN_2_CONN(c); - if (c->status_code == 0) { - c->status_code = status; - mg_printf(c, "HTTP/1.1 %d %s\r\n", status, status_code_to_str(status)); - } - conn->ns_conn->flags |= MG_USING_CHUNKED_API; -} - -void mg_send_header(struct mg_connection *c, const char *name, const char *v) { - struct connection *conn = MG_CONN_2_CONN(c); - if (c->status_code == 0) { - c->status_code = 200; - mg_printf(c, "HTTP/1.1 %d %s\r\n", 200, status_code_to_str(200)); - } - mg_printf(c, "%s: %s\r\n", name, v); - conn->ns_conn->flags |= MG_USING_CHUNKED_API; -} - -static void terminate_headers(struct mg_connection *c) { - struct connection *conn = MG_CONN_2_CONN(c); - if (!(conn->ns_conn->flags & MG_HEADERS_SENT)) { - mg_send_header(c, "Transfer-Encoding", "chunked"); - mg_write(c, "\r\n", 2); - conn->ns_conn->flags |= MG_HEADERS_SENT; - } -} - -size_t mg_send_data(struct mg_connection *c, const void *data, int data_len) { - struct connection *conn = MG_CONN_2_CONN(c); - terminate_headers(c); - write_chunk(MG_CONN_2_CONN(c), (const char *) data, data_len); - return conn->ns_conn->send_iobuf.len; -} - -size_t mg_printf_data(struct mg_connection *c, const char *fmt, ...) { - va_list ap; - int ret; - - va_start(ap, fmt); - ret = mg_vprintf_data(c, fmt, ap); - va_end(ap); - - return ret; -} - -size_t mg_vprintf_data(struct mg_connection *c, const char *fmt, va_list ap) { - struct connection *conn = MG_CONN_2_CONN(c); - int len; - char mem[IOBUF_SIZE], *buf = mem; - - terminate_headers(c); - - len = ns_avprintf(&buf, sizeof(mem), fmt, ap); - - if (len >= 0) { - write_chunk((struct connection *) conn, buf, len); - } - if (buf != mem && buf != NULL) { - NS_FREE(buf); - } - return conn->ns_conn->send_iobuf.len; -} - -#if !defined(MONGOOSE_NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH) -static int is_big_endian(void) { - static const int n = 1; - return ((char *) &n)[0] == 0; -} -#endif - -#ifndef MONGOOSE_NO_WEBSOCKET -// START OF SHA-1 code -// Copyright(c) By Steve Reid -#define SHA1HANDSOFF -#if defined(__sun) -#include "solarisfixes.h" -#endif - -union char64long16 { unsigned char c[64]; uint32_t l[16]; }; - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -static uint32_t blk0(union char64long16 *block, int i) { - // Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN - if (!is_big_endian()) { - block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | - (rol(block->l[i], 8) & 0x00FF00FF); - } - return block->l[i]; -} - -/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */ -#undef blk -#undef R0 -#undef R1 -#undef R2 -#undef R3 -#undef R4 - -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(block, i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - -typedef struct { - uint32_t state[5]; - uint32_t count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) { - uint32_t a, b, c, d, e; - union char64long16 block[1]; - - memcpy(block, buffer, 64); - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - // Erase working structures. The order of operations is important, - // used to ensure that compiler doesn't optimize those out. - memset(block, 0, sizeof(block)); - a = b = c = d = e = 0; - (void) a; (void) b; (void) c; (void) d; (void) e; -} - -static void SHA1Init(SHA1_CTX *context) { - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - -static void SHA1Update(SHA1_CTX *context, const unsigned char *data, - size_t len) { - size_t i, j; - - j = context->count[0]; - if ((context->count[0] += len << 3) < j) - context->count[1]++; - context->count[1] += (len>>29); - j = (j >> 3) & 63; - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - -static void SHA1Final(unsigned char digest[20], SHA1_CTX *context) { - unsigned i; - unsigned char finalcount[8], c; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); - } - c = 0200; - SHA1Update(context, &c, 1); - while ((context->count[0] & 504) != 448) { - c = 0000; - SHA1Update(context, &c, 1); - } - SHA1Update(context, finalcount, 8); - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - memset(context, '\0', sizeof(*context)); - memset(&finalcount, '\0', sizeof(finalcount)); -} -// END OF SHA1 CODE - -static void base64_encode(const unsigned char *src, int src_len, char *dst) { - static const char *b64 = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int i, j, a, b, c; - - for (i = j = 0; i < src_len; i += 3) { - a = src[i]; - b = i + 1 >= src_len ? 0 : src[i + 1]; - c = i + 2 >= src_len ? 0 : src[i + 2]; - - dst[j++] = b64[a >> 2]; - dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; - if (i + 1 < src_len) { - dst[j++] = b64[(b & 15) << 2 | (c >> 6)]; - } - if (i + 2 < src_len) { - dst[j++] = b64[c & 63]; - } - } - while (j % 4 != 0) { - dst[j++] = '='; - } - dst[j++] = '\0'; -} - -static void send_websocket_handshake(struct mg_connection *conn, - const char *key) { - static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - char buf[500], sha[20], b64_sha[sizeof(sha) * 2]; - SHA1_CTX sha_ctx; - - mg_snprintf(buf, sizeof(buf), "%s%s", key, magic); - SHA1Init(&sha_ctx); - SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf)); - SHA1Final((unsigned char *) sha, &sha_ctx); - base64_encode((unsigned char *) sha, sizeof(sha), b64_sha); - mg_snprintf(buf, sizeof(buf), "%s%s%s", - "HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: ", b64_sha, "\r\n\r\n"); - - mg_write(conn, buf, strlen(buf)); -} - -static size_t deliver_websocket_frame(struct connection *conn) { - // Having buf unsigned char * is important, as it is used below in arithmetic - unsigned char *buf = (unsigned char *) conn->ns_conn->recv_iobuf.buf; - size_t i, len, buf_len = conn->ns_conn->recv_iobuf.len, frame_len = 0, - mask_len = 0, header_len = 0, data_len = 0, buffered = 0; - - if (buf_len >= 2) { - len = buf[1] & 127; - mask_len = buf[1] & 128 ? 4 : 0; - if (len < 126 && buf_len >= mask_len) { - data_len = len; - header_len = 2 + mask_len; - } else if (len == 126 && buf_len >= 4 + mask_len) { - header_len = 4 + mask_len; - data_len = ((((size_t) buf[2]) << 8) + buf[3]); - } else if (buf_len >= 10 + mask_len) { - header_len = 10 + mask_len; - data_len = (size_t) (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) + - htonl(* (uint32_t *) &buf[6]); - } - } - - frame_len = header_len + data_len; - buffered = frame_len > 0 && frame_len <= buf_len; - - if (buffered) { - conn->mg_conn.content_len = data_len; - conn->mg_conn.content = (char *) buf + header_len; - conn->mg_conn.wsbits = buf[0]; - - // Apply mask if necessary - if (mask_len > 0) { - for (i = 0; i < data_len; i++) { - buf[i + header_len] ^= (buf + header_len - mask_len)[i % 4]; - } - } - - // Call the handler and remove frame from the iobuf - if (call_user(conn, MG_REQUEST) == MG_FALSE || - (buf[0] & 0x0f) == WEBSOCKET_OPCODE_CONNECTION_CLOSE) { - conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA; - } - iobuf_remove(&conn->ns_conn->recv_iobuf, frame_len); - } - - return buffered; -} - -size_t mg_websocket_write(struct mg_connection *conn, int opcode, - const char *data, size_t data_len) { - unsigned char mem[4192], *copy = mem; - size_t copy_len = 0; - - /* Check overflow */ - if (data_len > ~(size_t)0 - (size_t)10) { - return 0; - } - - if (data_len + 10 > sizeof(mem) && - (copy = (unsigned char *) NS_MALLOC(data_len + 10)) == NULL) { - return 0; - } - - copy[0] = 0x80 + (opcode & 0x0f); - - // Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 - if (data_len < 126) { - // Inline 7-bit length field - copy[1] = data_len; - memcpy(copy + 2, data, data_len); - copy_len = 2 + data_len; - } else if (data_len <= 0xFFFF) { - // 16-bit length field - copy[1] = 126; - * (uint16_t *) (copy + 2) = (uint16_t) htons((uint16_t) data_len); - memcpy(copy + 4, data, data_len); - copy_len = 4 + data_len; - } else { - // 64-bit length field - const uint32_t hi = htonl((uint32_t) ((uint64_t) data_len >> 32)); - const uint32_t lo = htonl(data_len & 0xffffffff); - copy[1] = 127; - memcpy(copy+2,&hi,sizeof(hi)); - memcpy(copy+6,&lo,sizeof(lo)); - memcpy(copy + 10, data, data_len); - copy_len = 10 + data_len; - } - - if (copy_len > 0) { - mg_write(conn, copy, copy_len); - } - if (copy != mem) { - NS_FREE(copy); - } - - // If we send closing frame, schedule a connection to be closed after - // data is drained to the client. - if (opcode == WEBSOCKET_OPCODE_CONNECTION_CLOSE) { - MG_CONN_2_CONN(conn)->ns_conn->flags |= NSF_FINISHED_SENDING_DATA; - } - - return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len; -} - -size_t mg_websocket_printf(struct mg_connection *conn, int opcode, - const char *fmt, ...) { - char mem[4192], *buf = mem; - va_list ap; - int len; - - va_start(ap, fmt); - if ((len = ns_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { - mg_websocket_write(conn, opcode, buf, len); - } - va_end(ap); - - if (buf != mem && buf != NULL) { - NS_FREE(buf); - } - - return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len; -} - -static void send_websocket_handshake_if_requested(struct mg_connection *conn) { - const char *ver = mg_get_header(conn, "Sec-WebSocket-Version"), - *key = mg_get_header(conn, "Sec-WebSocket-Key"); - if (ver != NULL && key != NULL) { - conn->is_websocket = 1; - if (call_user(MG_CONN_2_CONN(conn), MG_WS_HANDSHAKE) == MG_FALSE) { - send_websocket_handshake(conn, key); - } - call_user(MG_CONN_2_CONN(conn), MG_WS_CONNECT); - } -} - -static void ping_idle_websocket_connection(struct connection *conn, time_t t) { - if (t - conn->ns_conn->last_io_time > MONGOOSE_USE_WEBSOCKET_PING_INTERVAL) { - mg_websocket_write(&conn->mg_conn, WEBSOCKET_OPCODE_PING, "", 0); - } -} -#else -#define ping_idle_websocket_connection(conn, t) -#endif // !MONGOOSE_NO_WEBSOCKET - -static void write_terminating_chunk(struct connection *conn) { - mg_write(&conn->mg_conn, "0\r\n\r\n", 5); -} - -static int call_request_handler(struct connection *conn) { - int result; - conn->mg_conn.content = conn->ns_conn->recv_iobuf.buf; - if ((result = call_user(conn, MG_REQUEST)) == MG_TRUE) { - if (conn->ns_conn->flags & MG_USING_CHUNKED_API) { - terminate_headers(&conn->mg_conn); - write_terminating_chunk(conn); - } - close_local_endpoint(conn); - } - return result; -} - -const char *mg_get_mime_type(const char *path, const char *default_mime_type) { - const char *ext; - size_t i, path_len; - - path_len = strlen(path); - - for (i = 0; static_builtin_mime_types[i].extension != NULL; i++) { - ext = path + (path_len - static_builtin_mime_types[i].ext_len); - if (path_len > static_builtin_mime_types[i].ext_len && - mg_strcasecmp(ext, static_builtin_mime_types[i].extension) == 0) { - return static_builtin_mime_types[i].mime_type; - } - } - - return default_mime_type; -} - -#ifndef MONGOOSE_NO_FILESYSTEM -// Convert month to the month number. Return -1 on error, or month number -static int get_month_index(const char *s) { - static const char *month_names[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" - }; - int i; - - for (i = 0; i < (int) ARRAY_SIZE(month_names); i++) - if (!strcmp(s, month_names[i])) - return i; - - return -1; -} - -static int num_leap_years(int year) { - return year / 4 - year / 100 + year / 400; -} - -// Parse UTC date-time string, and return the corresponding time_t value. -static time_t parse_date_string(const char *datetime) { - static const unsigned short days_before_month[] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 - }; - char month_str[32]; - int second, minute, hour, day, month, year, leap_days, days; - time_t result = (time_t) 0; - - if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d", - &day, month_str, &year, &hour, &minute, &second) == 6) || - (sscanf(datetime, "%d %3s %d %d:%d:%d", - &day, month_str, &year, &hour, &minute, &second) == 6) || - (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", - &day, month_str, &year, &hour, &minute, &second) == 6) || - (sscanf(datetime, "%d-%3s-%d %d:%d:%d", - &day, month_str, &year, &hour, &minute, &second) == 6)) && - year > 1970 && - (month = get_month_index(month_str)) != -1) { - leap_days = num_leap_years(year) - num_leap_years(1970); - year -= 1970; - days = year * 365 + days_before_month[month] + (day - 1) + leap_days; - result = days * 24 * 3600 + hour * 3600 + minute * 60 + second; - } - - return result; -} - -// Look at the "path" extension and figure what mime type it has. -// Store mime type in the vector. -static void get_mime_type(const struct mg_server *server, const char *path, - struct vec *vec) { - struct vec ext_vec, mime_vec; - const char *list, *ext; - size_t path_len; - - path_len = strlen(path); - - // Scan user-defined mime types first, in case user wants to - // override default mime types. - list = server->config_options[EXTRA_MIME_TYPES]; - while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) { - // ext now points to the path suffix - ext = path + path_len - ext_vec.len; - if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) { - *vec = mime_vec; - return; - } - } - - vec->ptr = mg_get_mime_type(path, "text/plain"); - vec->len = strlen(vec->ptr); -} - -static const char *suggest_connection_header(const struct mg_connection *conn) { - return should_keep_alive(conn) ? "keep-alive" : "close"; -} - -static void construct_etag(char *buf, size_t buf_len, const file_stat_t *st) { - mg_snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", - (unsigned long) st->st_mtime, (int64_t) st->st_size); -} - -// Return True if we should reply 304 Not Modified. -static int is_not_modified(const struct connection *conn, - const file_stat_t *stp) { - char etag[64]; - const char *ims = mg_get_header(&conn->mg_conn, "If-Modified-Since"); - const char *inm = mg_get_header(&conn->mg_conn, "If-None-Match"); - construct_etag(etag, sizeof(etag), stp); - return (inm != NULL && !mg_strcasecmp(etag, inm)) || - (ims != NULL && stp->st_mtime <= parse_date_string(ims)); -} - -// For given directory path, substitute it to valid index file. -// Return 0 if index file has been found, -1 if not found. -// If the file is found, it's stats is returned in stp. -static int find_index_file(struct connection *conn, char *path, - size_t path_len, file_stat_t *stp) { - const char *list = conn->server->config_options[INDEX_FILES]; - file_stat_t st; - struct vec filename_vec; - size_t n = strlen(path); - int found = 0; - - // The 'path' given to us points to the directory. Remove all trailing - // directory separator characters from the end of the path, and - // then append single directory separator character. - while (n > 0 && path[n - 1] == '/') { - n--; - } - path[n] = '/'; - - // Traverse index files list. For each entry, append it to the given - // path and see if the file exists. If it exists, break the loop - while ((list = next_option(list, &filename_vec, NULL)) != NULL) { - - if (path_len <= n + 2) { - continue; - } - - // Ignore too long entries that may overflow path buffer - if (filename_vec.len > (path_len - (n + 2))) - continue; - - // Prepare full path to the index file - strncpy(path + n + 1, filename_vec.ptr, filename_vec.len); - path[n + 1 + filename_vec.len] = '\0'; - - //DBG(("[%s]", path)); - - // Does it exist? - if (!stat(path, &st)) { - // Yes it does, break the loop - *stp = st; - found = 1; - break; - } - } - - // If no index file exists, restore directory path - if (!found) { - path[n] = '/'; - path[n + 1] = '\0'; - } - - return found; -} - -static int parse_range_header(const char *header, int64_t *a, int64_t *b) { -// return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b); -// return sscanf(header, "bytes=%ld-%ld" INT64_FMT, a, b); - return 0; -} - -static void gmt_time_string(char *buf, size_t buf_len, time_t *t) { - strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t)); -} - -static void open_file_endpoint(struct connection *conn, const char *path, - file_stat_t *st, const char *extra_headers) { - char date[64], lm[64], etag[64], range[64], headers[1000]; - const char *msg = "OK", *hdr; - time_t t, curtime = time(NULL); - int64_t r1, r2; - struct vec mime_vec; - int n; - - conn->endpoint_type = EP_FILE; - ns_set_close_on_exec(conn->endpoint.fd); - conn->mg_conn.status_code = 200; - - get_mime_type(conn->server, path, &mime_vec); - conn->cl = st->st_size; - range[0] = '\0'; - - // If Range: header specified, act accordingly - r1 = r2 = 0; - hdr = mg_get_header(&conn->mg_conn, "Range"); - if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && - r1 >= 0 && r2 >= 0) { - conn->mg_conn.status_code = 206; - conn->cl = n == 2 ? (r2 > conn->cl ? conn->cl : r2) - r1 + 1: conn->cl - r1; - mg_snprintf(range, sizeof(range), "Content-Range: bytes " - "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n", - r1, r1 + conn->cl - 1, (int64_t) st->st_size); - msg = "Partial Content"; - lseek(conn->endpoint.fd, r1, SEEK_SET); - } - - // Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 - gmt_time_string(date, sizeof(date), &curtime); - t = st->st_mtime; // store in local variable for NDK compile - gmt_time_string(lm, sizeof(lm), &t); - construct_etag(etag, sizeof(etag), st); - - n = mg_snprintf(headers, sizeof(headers), - "HTTP/1.1 %d %s\r\n" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "Etag: %s\r\n" - "Content-Type: %.*s\r\n" - "Content-Length: %" INT64_FMT "\r\n" - "Connection: %s\r\n" - "Accept-Ranges: bytes\r\n" - "%s%s%s\r\n", - conn->mg_conn.status_code, msg, date, lm, etag, - (int) mime_vec.len, mime_vec.ptr, conn->cl, - suggest_connection_header(&conn->mg_conn), - range, extra_headers == NULL ? "" : extra_headers, - MONGOOSE_USE_EXTRA_HTTP_HEADERS); - ns_send(conn->ns_conn, headers, n); - - if (!strcmp(conn->mg_conn.request_method, "HEAD")) { - conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA; - close(conn->endpoint.fd); - conn->endpoint_type = EP_NONE; - } -} - -void mg_send_file_data(struct mg_connection *c, int fd) { - struct connection *conn = MG_CONN_2_CONN(c); - conn->endpoint_type = EP_FILE; - conn->endpoint.fd = fd; - ns_set_close_on_exec(conn->endpoint.fd); -} -#endif // MONGOOSE_NO_FILESYSTEM - -static void call_request_handler_if_data_is_buffered(struct connection *conn) { -#ifndef MONGOOSE_NO_WEBSOCKET - if (conn->mg_conn.is_websocket) { - do { } while (deliver_websocket_frame(conn)); - } else -#endif - if (conn->num_bytes_recv >= (conn->cl + conn->request_len) && - call_request_handler(conn) == MG_FALSE) { - open_local_endpoint(conn, 1); - } -} - -#if !defined(MONGOOSE_NO_DIRECTORY_LISTING) || !defined(MONGOOSE_NO_DAV) - -#ifdef _WIN32 -struct dirent { - char d_name[MAX_PATH_SIZE]; -}; - -typedef struct DIR { - HANDLE handle; - WIN32_FIND_DATAW info; - struct dirent result; -} DIR; - -// Implementation of POSIX opendir/closedir/readdir for Windows. -static DIR *opendir(const char *name) { - DIR *dir = NULL; - wchar_t wpath[MAX_PATH_SIZE]; - DWORD attrs; - - if (name == NULL) { - SetLastError(ERROR_BAD_ARGUMENTS); - } else if ((dir = (DIR *) NS_MALLOC(sizeof(*dir))) == NULL) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } else { - to_wchar(name, wpath, ARRAY_SIZE(wpath)); - attrs = GetFileAttributesW(wpath); - if (attrs != 0xFFFFFFFF && - ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) { - (void) wcscat(wpath, L"\\*"); - dir->handle = FindFirstFileW(wpath, &dir->info); - dir->result.d_name[0] = '\0'; - } else { - NS_FREE(dir); - dir = NULL; - } - } - - return dir; -} - -static int closedir(DIR *dir) { - int result = 0; - - if (dir != NULL) { - if (dir->handle != INVALID_HANDLE_VALUE) - result = FindClose(dir->handle) ? 0 : -1; - - NS_FREE(dir); - } else { - result = -1; - SetLastError(ERROR_BAD_ARGUMENTS); - } - - return result; -} - -static struct dirent *readdir(DIR *dir) { - struct dirent *result = 0; - - if (dir) { - if (dir->handle != INVALID_HANDLE_VALUE) { - result = &dir->result; - (void) WideCharToMultiByte(CP_UTF8, 0, - dir->info.cFileName, -1, result->d_name, - sizeof(result->d_name), NULL, NULL); - - if (!FindNextFileW(dir->handle, &dir->info)) { - (void) FindClose(dir->handle); - dir->handle = INVALID_HANDLE_VALUE; - } - - } else { - SetLastError(ERROR_FILE_NOT_FOUND); - } - } else { - SetLastError(ERROR_BAD_ARGUMENTS); - } - - return result; -} -#endif // _WIN32 POSIX opendir/closedir/readdir implementation - -static int scan_directory(struct connection *conn, const char *dir, - struct dir_entry **arr) { - char path[MAX_PATH_SIZE]; - struct dir_entry *p; - struct dirent *dp; - int arr_size = 0, arr_ind = 0, inc = 100; - DIR *dirp; - - *arr = NULL; - if ((dirp = (opendir(dir))) == NULL) return 0; - - while ((dp = readdir(dirp)) != NULL) { - // Do not show current dir and hidden files - if (!strcmp(dp->d_name, ".") || - !strcmp(dp->d_name, "..") || - must_hide_file(conn, dp->d_name)) { - continue; - } - mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name); - - // Resize the array if necessary - if (arr_ind >= arr_size) { - if ((p = (struct dir_entry *) - NS_REALLOC(*arr, (inc + arr_size) * sizeof(**arr))) != NULL) { - // Memset new chunk to zero, otherwise st_mtime will have garbage which - // can make strftime() segfault, see - // http://code.google.com/p/mongoose/issues/detail?id=79 - memset(p + arr_size, 0, sizeof(**arr) * inc); - - *arr = p; - arr_size += inc; - } - } - - if (arr_ind < arr_size) { - (*arr)[arr_ind].conn = conn; - (*arr)[arr_ind].file_name = strdup(dp->d_name); - stat(path, &(*arr)[arr_ind].st); - arr_ind++; - } - } - closedir(dirp); - - return arr_ind; -} - -size_t mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len) { - static const char *dont_escape = "._-$,;~()"; - static const char *hex = "0123456789abcdef"; - size_t i = 0, j = 0; - - for (i = j = 0; dst_len > 0 && i < s_len && j + 2 < dst_len - 1; i++, j++) { - if (isalnum(* (const unsigned char *) (src + i)) || - strchr(dont_escape, * (const unsigned char *) (src + i)) != NULL) { - dst[j] = src[i]; - } else if (j + 3 < dst_len) { - dst[j] = '%'; - dst[j + 1] = hex[(* (const unsigned char *) (src + i)) >> 4]; - dst[j + 2] = hex[(* (const unsigned char *) (src + i)) & 0xf]; - j += 2; - } - } - - dst[j] = '\0'; - return j; -} -#endif // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV - -#ifndef MONGOOSE_NO_DIRECTORY_LISTING - -static void print_dir_entry(const struct dir_entry *de) { - char size[64], mod[64], href[MAX_PATH_SIZE * 3]; - int64_t fsize = de->st.st_size; - int is_dir = S_ISDIR(de->st.st_mode); - const char *slash = is_dir ? "/" : ""; - time_t t; - - if (is_dir) { - mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]"); - } else { - // We use (signed) cast below because MSVC 6 compiler cannot - // convert unsigned __int64 to double. - if (fsize < 1024) { - mg_snprintf(size, sizeof(size), "%d", (int) fsize); - } else if (fsize < 0x100000) { - mg_snprintf(size, sizeof(size), "%.1fk", (double) fsize / 1024.0); - } else if (fsize < 0x40000000) { - mg_snprintf(size, sizeof(size), "%.1fM", (double) fsize / 1048576); - } else { - mg_snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824); - } - } - t = de->st.st_mtime; // store in local variable for NDK compile - strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&t)); - mg_url_encode(de->file_name, strlen(de->file_name), href, sizeof(href)); - mg_printf_data(&de->conn->mg_conn, - "%s%s" - " %s  %s\n", - href, slash, de->file_name, slash, mod, size); -} - -// Sort directory entries by size, or name, or modification time. -// On windows, __cdecl specification is needed in case if project is built -// with __stdcall convention. qsort always requires __cdels callback. -static int __cdecl compare_dir_entries(const void *p1, const void *p2) { - const struct dir_entry *a = (const struct dir_entry *) p1, - *b = (const struct dir_entry *) p2; - const char *qs = a->conn->mg_conn.query_string ? - a->conn->mg_conn.query_string : "na"; - int cmp_result = 0; - - if (S_ISDIR(a->st.st_mode) && !S_ISDIR(b->st.st_mode)) { - return -1; // Always put directories on top - } else if (!S_ISDIR(a->st.st_mode) && S_ISDIR(b->st.st_mode)) { - return 1; // Always put directories on top - } else if (*qs == 'n') { - cmp_result = strcmp(a->file_name, b->file_name); - } else if (*qs == 's') { - cmp_result = a->st.st_size == b->st.st_size ? 0 : - a->st.st_size > b->st.st_size ? 1 : -1; - } else if (*qs == 'd') { - cmp_result = a->st.st_mtime == b->st.st_mtime ? 0 : - a->st.st_mtime > b->st.st_mtime ? 1 : -1; - } - - return qs[1] == 'd' ? -cmp_result : cmp_result; -} - -static void send_directory_listing(struct connection *conn, const char *dir) { - struct dir_entry *arr = NULL; - int i, num_entries, sort_direction = conn->mg_conn.query_string != NULL && - conn->mg_conn.query_string[1] == 'd' ? 'a' : 'd'; - - mg_send_header(&conn->mg_conn, "Transfer-Encoding", "chunked"); - mg_send_header(&conn->mg_conn, "Content-Type", "text/html; charset=utf-8"); - - mg_printf_data(&conn->mg_conn, - "Index of %s" - "" - "

Index of %s

"
-              ""
-              ""
-              ""
-              "",
-              conn->mg_conn.uri, conn->mg_conn.uri,
-              sort_direction, sort_direction, sort_direction);
-
-  num_entries = scan_directory(conn, dir, &arr);
-  if (arr) {
-      qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
-      for (i = 0; i < num_entries; i++) {
-        print_dir_entry(&arr[i]);
-        NS_FREE(arr[i].file_name);
-      }
-      NS_FREE(arr);
-  }
-
-  write_terminating_chunk(conn);
-  close_local_endpoint(conn);
-}
-#endif  // MONGOOSE_NO_DIRECTORY_LISTING
-
-#ifndef MONGOOSE_NO_DAV
-static void print_props(struct connection *conn, const char *uri,
-                        file_stat_t *stp) {
-  char mtime[64];
-  time_t t = stp->st_mtime;  // store in local variable for NDK compile
-  gmt_time_string(mtime, sizeof(mtime), &t);
-  mg_printf(&conn->mg_conn,
-      ""
-       "%s"
-       ""
-        ""
-         "%s"
-         "%" INT64_FMT ""
-         "%s"
-        ""
-        "HTTP/1.1 200 OK"
-       ""
-      "\n",
-      uri, S_ISDIR(stp->st_mode) ? "" : "",
-      (int64_t) stp->st_size, mtime);
-}
-
-static void handle_propfind(struct connection *conn, const char *path,
-                            file_stat_t *stp, int exists) {
-  static const char header[] = "HTTP/1.1 207 Multi-Status\r\n"
-    "Connection: close\r\n"
-    "Content-Type: text/xml; charset=utf-8\r\n\r\n"
-    ""
-    "\n";
-  static const char footer[] = "";
-  const char *depth = mg_get_header(&conn->mg_conn, "Depth");
-#ifdef MONGOOSE_NO_DIRECTORY_LISTING
-  const char *list_dir = "no";
-#else
-  const char *list_dir = conn->server->config_options[ENABLE_DIRECTORY_LISTING];
-#endif
-
-  conn->mg_conn.status_code = 207;
-
-  // Print properties for the requested resource itself
-  if (!exists) {
-    conn->mg_conn.status_code = 404;
-    mg_printf(&conn->mg_conn, "%s", "HTTP/1.1 404 Not Found\r\n\r\n");
-  } else if (S_ISDIR(stp->st_mode) && mg_strcasecmp(list_dir, "yes") != 0) {
-    conn->mg_conn.status_code = 403;
-    mg_printf(&conn->mg_conn, "%s",
-              "HTTP/1.1 403 Directory Listing Denied\r\n\r\n");
-  } else {
-    ns_send(conn->ns_conn, header, sizeof(header) - 1);
-    print_props(conn, conn->mg_conn.uri, stp);
-
-    if (S_ISDIR(stp->st_mode) &&
-             (depth == NULL || strcmp(depth, "0") != 0)) {
-      struct dir_entry *arr = NULL;
-      int i, num_entries = scan_directory(conn, path, &arr);
-
-      for (i = 0; i < num_entries; i++) {
-        char buf[MAX_PATH_SIZE * 3];
-        struct dir_entry *de = &arr[i];
-        mg_url_encode(de->file_name, strlen(de->file_name), buf, sizeof(buf));
-        print_props(conn, buf, &de->st);
-        NS_FREE(de->file_name);
-      }
-      NS_FREE(arr);
-    }
-    ns_send(conn->ns_conn, footer, sizeof(footer) - 1);
-  }
-
-  close_local_endpoint(conn);
-}
-
-static void handle_mkcol(struct connection *conn, const char *path) {
-  int status_code = 500;
-
-  if (conn->mg_conn.content_len > 0) {
-    status_code = 415;
-  } else if (!mkdir(path, 0755)) {
-    status_code = 201;
-  } else if (errno == EEXIST) {
-    status_code = 405;
-  } else if (errno == EACCES) {
-    status_code = 403;
-  } else if (errno == ENOENT) {
-    status_code = 409;
-  }
-  send_http_error(conn, status_code, NULL);
-}
-
-static int remove_directory(const char *dir) {
-  char path[MAX_PATH_SIZE];
-  struct dirent *dp;
-  file_stat_t st;
-  DIR *dirp;
-
-  if ((dirp = opendir(dir)) == NULL) return 0;
-
-  while ((dp = readdir(dirp)) != NULL) {
-    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
-    mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
-    stat(path, &st);
-    if (S_ISDIR(st.st_mode)) {
-      remove_directory(path);
-    } else {
-      remove(path);
-    }
-  }
-  closedir(dirp);
-  rmdir(dir);
-
-  return 1;
-}
-
-static void handle_delete(struct connection *conn, const char *path) {
-  file_stat_t st;
-
-  if (stat(path, &st) != 0) {
-    send_http_error(conn, 404, NULL);
-  } else if (S_ISDIR(st.st_mode)) {
-    remove_directory(path);
-    send_http_error(conn, 204, NULL);
-  } else if (remove(path) == 0) {
-    send_http_error(conn, 204, NULL);
-  } else {
-    send_http_error(conn, 423, NULL);
-  }
-}
-
-// For a given PUT path, create all intermediate subdirectories
-// for given path. Return 0 if the path itself is a directory,
-// or -1 on error, 1 if OK.
-static int put_dir(const char *path) {
-  char buf[MAX_PATH_SIZE];
-  const char *s, *p;
-  file_stat_t st;
-
-  // Create intermediate directories if they do not exist
-  for (s = p = path + 1; (p = strchr(s, '/')) != NULL; s = ++p) {
-    if (p - path >= (int) sizeof(buf)) return -1; // Buffer overflow
-    memcpy(buf, path, p - path);
-    buf[p - path] = '\0';
-    if (stat(buf, &st) != 0 && mkdir(buf, 0755) != 0) return -1;
-    if (p[1] == '\0') return 0;  // Path is a directory itself
-  }
-
-  return 1;
-}
-
-static void handle_put(struct connection *conn, const char *path) {
-  file_stat_t st;
-  const char *range, *cl_hdr = mg_get_header(&conn->mg_conn, "Content-Length");
-  int64_t r1, r2;
-  int rc;
-
-  conn->mg_conn.status_code = !stat(path, &st) ? 200 : 201;
-  if ((rc = put_dir(path)) == 0) {
-    mg_printf(&conn->mg_conn, "HTTP/1.1 %d OK\r\n\r\n",
-              conn->mg_conn.status_code);
-    close_local_endpoint(conn);
-  } else if (rc == -1) {
-    send_http_error(conn, 500, "put_dir: %s", strerror(errno));
-  } else if (cl_hdr == NULL) {
-    send_http_error(conn, 411, NULL);
-  } else if ((conn->endpoint.fd =
-              open(path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644)) < 0) {
-    send_http_error(conn, 500, "open(%s): %s", path, strerror(errno));
-  } else {
-    DBG(("PUT [%s] %lu", path, (unsigned long) conn->ns_conn->recv_iobuf.len));
-    conn->endpoint_type = EP_PUT;
-    ns_set_close_on_exec(conn->endpoint.fd);
-    range = mg_get_header(&conn->mg_conn, "Content-Range");
-    conn->cl = to64(cl_hdr);
-    r1 = r2 = 0;
-    if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
-      conn->mg_conn.status_code = 206;
-      lseek(conn->endpoint.fd, r1, SEEK_SET);
-      conn->cl = r2 > r1 ? r2 - r1 + 1: conn->cl - r1;
-    }
-    mg_printf(&conn->mg_conn, "HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n",
-              conn->mg_conn.status_code);
-  }
-}
-
-static void forward_put_data(struct connection *conn) {
-  struct iobuf *io = &conn->ns_conn->recv_iobuf;
-  size_t k = conn->cl < (int64_t) io->len ? conn->cl : (int64_t) io->len;   // To write
-  size_t n = write(conn->endpoint.fd, io->buf, k);   // Write them!
-  if (n > 0) {
-    iobuf_remove(io, n);
-    conn->cl -= n;
-  }
-  if (conn->cl <= 0) {
-    close_local_endpoint(conn);
-  }
-}
-#endif //  MONGOOSE_NO_DAV
-
-static void send_options(struct connection *conn) {
-  conn->mg_conn.status_code = 200;
-  mg_printf(&conn->mg_conn, "%s",
-            "HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, PUT, "
-            "DELETE, OPTIONS, PROPFIND, MKCOL\r\nDAV: 1\r\n\r\n");
-  close_local_endpoint(conn);
-}
-
-#ifndef MONGOOSE_NO_AUTH
-void mg_send_digest_auth_request(struct mg_connection *c) {
-  struct connection *conn = MG_CONN_2_CONN(c);
-  c->status_code = 401;
-  mg_printf(c,
-            "HTTP/1.1 401 Unauthorized\r\n"
-            "Content-Length: 0\r\n"
-            "WWW-Authenticate: Digest qop=\"auth\", "
-            "realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
-            conn->server->config_options[AUTH_DOMAIN],
-            (unsigned long) time(NULL));
-  if (conn->cl > 0) {
-    conn->ns_conn->flags |= NSF_DISCARD;
-  } else {
-    close_local_endpoint(conn);
-  }
-}
-
-// Use the global passwords file, if specified by auth_gpass option,
-// or search for .htpasswd in the requested directory.
-static FILE *open_auth_file(struct connection *conn, const char *path,
-                            int is_directory) {
-  char name[MAX_PATH_SIZE];
-  const char *p, *gpass = conn->server->config_options[GLOBAL_AUTH_FILE];
-  FILE *fp = NULL;
-
-  if (gpass != NULL) {
-    // Use global passwords file
-    fp = fopen(gpass, "r");
-  } else if (is_directory) {
-    mg_snprintf(name, sizeof(name), "%s%c%s", path, '/', PASSWORDS_FILE_NAME);
-    fp = fopen(name, "r");
-  } else {
-    // Try to find .htpasswd in requested directory.
-    if ((p = strrchr(path, '/')) == NULL) p = path;
-    mg_snprintf(name, sizeof(name), "%.*s%c%s",
-                (int) (p - path), path, '/', PASSWORDS_FILE_NAME);
-    fp = fopen(name, "r");
-  }
-
-  return fp;
-}
-
-#if !defined(HAVE_MD5) && !defined(MONGOOSE_NO_AUTH)
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest.	This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-typedef struct MD5Context {
-  uint32_t buf[4];
-  uint32_t bits[2];
-  unsigned char in[64];
-} MD5_CTX;
-
-static void byteReverse(unsigned char *buf, unsigned longs) {
-  uint32_t t;
-
-  // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN
-  if (is_big_endian()) {
-    do {
-      t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
-        ((unsigned) buf[1] << 8 | buf[0]);
-      * (uint32_t *) buf = t;
-      buf += 4;
-    } while (--longs);
-  }
-}
-
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, data, s) \
-  ( w += f(x, y, z) + data,  w = w<>(32-s),  w += x )
-
-// Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
-// initialization constants.
-static void MD5Init(MD5_CTX *ctx) {
-  ctx->buf[0] = 0x67452301;
-  ctx->buf[1] = 0xefcdab89;
-  ctx->buf[2] = 0x98badcfe;
-  ctx->buf[3] = 0x10325476;
-
-  ctx->bits[0] = 0;
-  ctx->bits[1] = 0;
-}
-
-static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
-  register uint32_t a, b, c, d;
-
-  a = buf[0];
-  b = buf[1];
-  c = buf[2];
-  d = buf[3];
-
-  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
-  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
-  buf[0] += a;
-  buf[1] += b;
-  buf[2] += c;
-  buf[3] += d;
-}
-
-static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) {
-  uint32_t t;
-
-  t = ctx->bits[0];
-  if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
-    ctx->bits[1]++;
-  ctx->bits[1] += len >> 29;
-
-  t = (t >> 3) & 0x3f;
-
-  if (t) {
-    unsigned char *p = (unsigned char *) ctx->in + t;
-
-    t = 64 - t;
-    if (len < t) {
-      memcpy(p, buf, len);
-      return;
-    }
-    memcpy(p, buf, t);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    buf += t;
-    len -= t;
-  }
-
-  while (len >= 64) {
-    memcpy(ctx->in, buf, 64);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    buf += 64;
-    len -= 64;
-  }
-
-  memcpy(ctx->in, buf, len);
-}
-
-static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) {
-  unsigned count;
-  unsigned char *p;
-  uint32_t *a;
-
-  count = (ctx->bits[0] >> 3) & 0x3F;
-
-  p = ctx->in + count;
-  *p++ = 0x80;
-  count = 64 - 1 - count;
-  if (count < 8) {
-    memset(p, 0, count);
-    byteReverse(ctx->in, 16);
-    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-    memset(ctx->in, 0, 56);
-  } else {
-    memset(p, 0, count - 8);
-  }
-  byteReverse(ctx->in, 14);
-
-  a = (uint32_t *)ctx->in;
-  a[14] = ctx->bits[0];
-  a[15] = ctx->bits[1];
-
-  MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-  byteReverse((unsigned char *) ctx->buf, 4);
-  memcpy(digest, ctx->buf, 16);
-  memset((char *) ctx, 0, sizeof(*ctx));
-}
-#endif // !HAVE_MD5
-
-
-
-// Stringify binary data. Output buffer must be twice as big as input,
-// because each byte takes 2 bytes in string representation
-static void bin2str(char *to, const unsigned char *p, size_t len) {
-  static const char *hex = "0123456789abcdef";
-
-  for (; len--; p++) {
-    *to++ = hex[p[0] >> 4];
-    *to++ = hex[p[0] & 0x0f];
-  }
-  *to = '\0';
-}
-
-// Return stringified MD5 hash for list of strings. Buffer must be 33 bytes.
-char *mg_md5(char buf[33], ...) {
-  unsigned char hash[16];
-  const char *p;
-  va_list ap;
-  MD5_CTX ctx;
-
-  MD5Init(&ctx);
-
-  va_start(ap, buf);
-  while ((p = va_arg(ap, const char *)) != NULL) {
-    MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p));
-  }
-  va_end(ap);
-
-  MD5Final(hash, &ctx);
-  bin2str(buf, hash, sizeof(hash));
-  return buf;
-}
-
-// Check the user's password, return 1 if OK
-static int check_password(const char *method, const char *ha1, const char *uri,
-                          const char *nonce, const char *nc, const char *cnonce,
-                          const char *qop, const char *response) {
-  char ha2[32 + 1], expected_response[32 + 1];
-
-#if 0
-  // Check for authentication timeout
-  if ((unsigned long) time(NULL) - (unsigned long) to64(nonce) > 3600 * 2) {
-    return 0;
-  }
-#endif
-
-  mg_md5(ha2, method, ":", uri, NULL);
-  mg_md5(expected_response, ha1, ":", nonce, ":", nc,
-      ":", cnonce, ":", qop, ":", ha2, NULL);
-
-  return mg_strcasecmp(response, expected_response) == 0 ? MG_TRUE : MG_FALSE;
-}
-
-
-// Authorize against the opened passwords file. Return 1 if authorized.
-int mg_authorize_digest(struct mg_connection *c, FILE *fp) {
-  struct connection *conn = MG_CONN_2_CONN(c);
-  const char *hdr;
-  char line[256], f_user[256], ha1[256], f_domain[256], user[100], nonce[100],
-       uri[MAX_REQUEST_SIZE], cnonce[100], resp[100], qop[100], nc[100];
-
-  if (c == NULL || fp == NULL) return 0;
-  if ((hdr = mg_get_header(c, "Authorization")) == NULL ||
-      mg_strncasecmp(hdr, "Digest ", 7) != 0) return 0;
-  if (!mg_parse_header(hdr, "username", user, sizeof(user))) return 0;
-  if (!mg_parse_header(hdr, "cnonce", cnonce, sizeof(cnonce))) return 0;
-  if (!mg_parse_header(hdr, "response", resp, sizeof(resp))) return 0;
-  if (!mg_parse_header(hdr, "uri", uri, sizeof(uri))) return 0;
-  if (!mg_parse_header(hdr, "qop", qop, sizeof(qop))) return 0;
-  if (!mg_parse_header(hdr, "nc", nc, sizeof(nc))) return 0;
-  if (!mg_parse_header(hdr, "nonce", nonce, sizeof(nonce))) return 0;
-
-  while (fgets(line, sizeof(line), fp) != NULL) {
-    if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) == 3 &&
-        !strcmp(user, f_user) &&
-        // NOTE(lsm): due to a bug in MSIE, we do not compare URIs
-        !strcmp(conn->server->config_options[AUTH_DOMAIN], f_domain))
-      return check_password(c->request_method, ha1, uri,
-                            nonce, nc, cnonce, qop, resp);
-  }
-  return MG_FALSE;
-}
-
-
-// Return 1 if request is authorised, 0 otherwise.
-static int is_authorized(struct connection *conn, const char *path,
-                         int is_directory) {
-  FILE *fp;
-  int authorized = MG_TRUE;
-
-  if ((fp = open_auth_file(conn, path, is_directory)) != NULL) {
-    authorized = mg_authorize_digest(&conn->mg_conn, fp);
-    fclose(fp);
-  }
-
-  return authorized;
-}
-
-static int is_authorized_for_dav(struct connection *conn) {
-  const char *auth_file = conn->server->config_options[DAV_AUTH_FILE];
-  const char *method = conn->mg_conn.request_method;
-  FILE *fp;
-  int authorized = MG_FALSE;
-
-  // If dav_auth_file is not set, allow non-authorized PROPFIND
-  if (method != NULL && !strcmp(method, "PROPFIND") && auth_file == NULL) {
-    authorized = MG_TRUE;
-  } else if (auth_file != NULL && (fp = fopen(auth_file, "r")) != NULL) {
-    authorized = mg_authorize_digest(&conn->mg_conn, fp);
-    fclose(fp);
-  }
-
-  return authorized;
-}
-#endif // MONGOOSE_NO_AUTH
-
-static int parse_header(const char *str, size_t str_len, const char *var_name,
-                        char *buf, size_t buf_size) {
-  int ch = ' ', ch1 = ',', len = 0;
-  size_t n = strlen(var_name);
-  const char *p, *end = str + str_len, *s = NULL;
-
-  if (buf != NULL && buf_size > 0) buf[0] = '\0';
-
-  // Find where variable starts
-  for (s = str; s != NULL && s + n < end; s++) {
-    if ((s == str || s[-1] == ch || s[-1] == ch1) && s[n] == '=' &&
-        !memcmp(s, var_name, n)) break;
-  }
-
-  if (s != NULL && &s[n + 1] < end) {
-    s += n + 1;
-    if (*s == '"' || *s == '\'') ch = ch1 = *s++;
-    p = s;
-    while (p < end && p[0] != ch && p[0] != ch1 && len < (int) buf_size) {
-      if (ch == ch1 && p[0] == '\\' && p[1] == ch) p++;
-      buf[len++] = *p++;
-    }
-    if (len >= (int) buf_size || (ch != ' ' && *p != ch)) {
-      len = 0;
-    } else {
-      if (len > 0 && s[len - 1] == ',') len--;
-      if (len > 0 && s[len - 1] == ';') len--;
-      buf[len] = '\0';
-    }
-  }
-
-  return len;
-}
-
-int mg_parse_header(const char *s, const char *var_name, char *buf,
-                    size_t buf_size) {
-  return parse_header(s, s == NULL ? 0 : strlen(s), var_name, buf, buf_size);
-}
-
-#ifndef MONGOOSE_NO_SSI
-static void send_ssi_file(struct mg_connection *, const char *, FILE *, int);
-
-static void send_file_data(struct mg_connection *conn, FILE *fp) {
-  char buf[IOBUF_SIZE];
-  size_t n;
-  while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
-    mg_write(conn, buf, n);
-  }
-}
-
-static void do_ssi_include(struct mg_connection *conn, const char *ssi,
-                           char *tag, int include_level) {
-  char file_name[IOBUF_SIZE], path[MAX_PATH_SIZE], *p;
-  char **opts = (MG_CONN_2_CONN(conn))->server->config_options;
-  FILE *fp;
-
-  // sscanf() is safe here, since send_ssi_file() also uses buffer
-  // of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN.
-  if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
-    // File name is relative to the webserver root
-    mg_snprintf(path, sizeof(path), "%s%c%s",
-                opts[DOCUMENT_ROOT], '/', file_name);
-  } else if (sscanf(tag, " abspath=\"%[^\"]\"", file_name) == 1) {
-    // File name is relative to the webserver working directory
-    // or it is absolute system path
-    mg_snprintf(path, sizeof(path), "%s", file_name);
-  } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
-             sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
-    // File name is relative to the current document
-    mg_snprintf(path, sizeof(path), "%s", ssi);
-    if ((p = strrchr(path, '/')) != NULL) {
-      p[1] = '\0';
-    }
-    mg_snprintf(path + strlen(path), sizeof(path) - strlen(path), "%s",
-                file_name);
-  } else {
-    mg_printf(conn, "Bad SSI #include: [%s]", tag);
-    return;
-  }
-
-  if ((fp = fopen(path, "rb")) == NULL) {
-    mg_printf(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s",
-              tag, path, strerror(errno));
-  } else {
-    ns_set_close_on_exec(fileno(fp));
-    if (mg_match_prefix(opts[SSI_PATTERN], strlen(opts[SSI_PATTERN]),
-        path) > 0) {
-      send_ssi_file(conn, path, fp, include_level + 1);
-    } else {
-      send_file_data(conn, fp);
-    }
-    fclose(fp);
-  }
-}
-
-#ifndef MONGOOSE_NO_POPEN
-static void do_ssi_exec(struct mg_connection *conn, char *tag) {
-  char cmd[IOBUF_SIZE];
-  FILE *fp;
-
-  if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) {
-    mg_printf(conn, "Bad SSI #exec: [%s]", tag);
-  } else if ((fp = popen(cmd, "r")) == NULL) {
-    mg_printf(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(errno));
-  } else {
-    send_file_data(conn, fp);
-    pclose(fp);
-  }
-}
-#endif // !MONGOOSE_NO_POPEN
-
-static void send_ssi_file(struct mg_connection *conn, const char *path,
-                          FILE *fp, int include_level) {
-  char buf[IOBUF_SIZE];
-  int ch, offset, len, in_ssi_tag;
-
-  if (include_level > 10) {
-    mg_printf(conn, "SSI #include level is too deep (%s)", path);
-    return;
-  }
-
-  in_ssi_tag = len = offset = 0;
-  while ((ch = fgetc(fp)) != EOF) {
-    if (in_ssi_tag && ch == '>') {
-      in_ssi_tag = 0;
-      buf[len++] = (char) ch;
-      buf[len] = '\0';
-      assert(len <= (int) sizeof(buf));
-      if (len < 6 || memcmp(buf, "
-	
-	   
-
-
-
-
-
-
NameModifiedSize

- - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
Name
Description
Year
Manufacturer
Parent
Source File
-
-
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
- -
-
- -
-

- - - - - - -
-

-
- - -
-

Select position to save to


- - - -
- 0 - 1 - 2 - 3 -
-
- 4 - 5 - 6 - 7 -
-
- 8 - 9 - A - B -
-
- C - D - E - F -
-
- G - H - I - J -
-
- K - L - M - N -
-
- O - P - Q - R -
-
- S - T - U - V -
-
- W - X - Y - Z -
- -




-
- - -
-

Select position to load from


- - - -
- 0 - 1 - 2 - 3 -
-
- 4 - 5 - 6 - 7 -
-
- 8 - 9 - A - B -
-
- C - D - E - F -
-
- G - H - I - J -
-
- K - L - M - N -
-
- O - P - Q - R -
-
- S - T - U - V -
-
- W - X - Y - Z -
- -




-
- - -
-

Paste Text to Keyboard

- -
-
- Exit - - -
-
- -
- -




-
- - -
-

Upload Text to Keyboard

- -
- -
- Exit - -
-
-
- -




-
-
- - -
-
-
- image -
- Home -
- -
-
-
-
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
- -
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
-
-
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
-
-
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
-
-
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-
- image -
- Home -
- -
-
-
-

Paste Upload Log

- -
-
-
- -
-

- - - - - - -
-

-
-
- - -
-
-

Confirm: Exit emulator?

-
- Yes - Cancel -
- - -
-
-

Confirm: Hard Reset?

-
- Yes - Cancel -
- - -
-
-

Confirm: Soft Reset?

-
- Yes - Cancel -
- - - - diff --git a/web/js/jquery.js b/web/js/jquery.js deleted file mode 100644 index da4170647dd..00000000000 --- a/web/js/jquery.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license -//@ sourceMappingURL=jquery-1.10.2.min.map -*/ -(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t -}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); -u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("