mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2026-08-28 10:37:12 +02:00
Discard unwanted libraries from discord integration attempt.
This commit is contained in:
+20
-2
@@ -6,8 +6,25 @@ add_library(CivetWeb STATIC
|
||||
# Configure include folders
|
||||
target_include_directories(CivetWeb PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(CivetWeb PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
# Configure macro options
|
||||
target_compile_definitions(CivetWeb PRIVATE _WIN32_WINNT=0x0601)
|
||||
# Feature selection
|
||||
target_compile_definitions(CivetWeb PUBLIC USE_WEBSOCKET=1 USE_HTTP2=1 USE_TIMERS=1)
|
||||
# Enable SSL
|
||||
find_package(OpenSSL REQUIRED)
|
||||
if (OPENSSL_FOUND)
|
||||
string(REPLACE "." ";" VERSION_LIST ${OPENSSL_VERSION})
|
||||
list(GET VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
|
||||
list(GET VERSION_LIST 1 OPENSSL_VERSION_MINOR)
|
||||
list(GET VERSION_LIST 2 OPENSSL_VERSION_PATCH)
|
||||
if(OPENSSL_VERSION_MAJOR EQUAL 1 AND OPENSSL_VERSION_MINOR EQUAL 0)
|
||||
target_compile_definitions(CivetWeb PUBLIC OPENSSL_API_1_0=1)
|
||||
elseif(OPENSSL_VERSION_MAJOR EQUAL 1 AND OPENSSL_VERSION_MINOR EQUAL 1)
|
||||
target_compile_definitions(CivetWeb PUBLIC OPENSSL_API_1_1=1)
|
||||
endif()
|
||||
target_include_directories(CivetWeb PRIVATE ${OPENSSL_INCLUDE_DIR})
|
||||
target_link_libraries(CivetWeb PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||
else()
|
||||
target_compile_definitions(CivetWeb PUBLIC NO_SSL=1)
|
||||
endif()
|
||||
# Enable LTO
|
||||
if (LTO_ENABLED)
|
||||
target_link_libraries(CivetWeb PRIVATE -flto)
|
||||
@@ -19,6 +36,7 @@ find_package(Threads)
|
||||
target_link_libraries(CivetWeb PUBLIC ${CMAKE_THREAD_LIBS_INIT})
|
||||
# OS and compiler checks.
|
||||
if(WIN32)
|
||||
target_compile_definitions(CivetWeb PRIVATE _WIN32_WINNT=0x0601)
|
||||
target_link_libraries(CivetWeb PUBLIC Ws2_32)
|
||||
endif()
|
||||
# Need the realtime library if we're using timers
|
||||
|
||||
Vendored
+6
@@ -43,6 +43,7 @@
|
||||
* Drew Wells
|
||||
* duong2179
|
||||
* ehlertjd
|
||||
* Elan P. Kugelmass
|
||||
* eugene
|
||||
* Eric Tsau
|
||||
* Erick Vieyra
|
||||
@@ -54,6 +55,8 @@
|
||||
* feneuilflo
|
||||
* Fernando G. Aranda
|
||||
* Frank Hilliger
|
||||
* Gábor Csárdi
|
||||
* goodmenzy
|
||||
* Grahack
|
||||
* Gregor Jasny
|
||||
* grenclave
|
||||
@@ -139,6 +142,8 @@
|
||||
* Philipp Hasper
|
||||
* Piotr Zierhoffer
|
||||
* pkvamme
|
||||
* Ponnuvel Palaniyappan
|
||||
* qinch
|
||||
* Radoslaw Zarzynski
|
||||
* Red54
|
||||
* Retallack Mark mark.retallack
|
||||
@@ -159,6 +164,7 @@
|
||||
* Simon Hailes
|
||||
* slidertom
|
||||
* SpaceLord
|
||||
* Stefan Codrescu
|
||||
* sunfch
|
||||
* suzukibitman
|
||||
* Símal Rasmussen
|
||||
|
||||
Vendored
+20
-18
@@ -118,27 +118,29 @@ Lua File System License
|
||||
|
||||
### Included only if built with Lua support.
|
||||
|
||||
http://keplerproject.github.io/luafilesystem/license.html
|
||||
https://github.com/keplerproject/luafilesystem/blob/master/LICENSE
|
||||
|
||||
> Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
|
||||
> Copyright © 2003-2014 Kepler Project.
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
> Permission is hereby granted, free of charge, to any person
|
||||
> obtaining a copy of this software and associated documentation
|
||||
> files (the "Software"), to deal in the Software without
|
||||
> restriction, including without limitation the rights to use, copy,
|
||||
> modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
> of the Software, and to permit persons to whom the Software is
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in
|
||||
> all copies or substantial portions of the Software.
|
||||
> The above copyright notice and this permission notice shall be
|
||||
> included in all copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
> THE SOFTWARE.
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
> ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
> SOFTWARE.
|
||||
|
||||
|
||||
LuaXML License
|
||||
@@ -188,9 +190,9 @@ https://github.com/svaarala/duktape/blob/master/LICENSE.txt
|
||||
> ===============
|
||||
> Duktape license
|
||||
> ===============
|
||||
>
|
||||
>
|
||||
> (http://opensource.org/licenses/MIT)
|
||||
>
|
||||
>
|
||||
> Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
||||
Vendored
+1246
-722
File diff suppressed because it is too large
Load Diff
+129
-58
@@ -23,9 +23,9 @@
|
||||
#ifndef CIVETWEB_HEADER_INCLUDED
|
||||
#define CIVETWEB_HEADER_INCLUDED
|
||||
|
||||
#define CIVETWEB_VERSION "1.13"
|
||||
#define CIVETWEB_VERSION "1.14"
|
||||
#define CIVETWEB_VERSION_MAJOR (1)
|
||||
#define CIVETWEB_VERSION_MINOR (13)
|
||||
#define CIVETWEB_VERSION_MINOR (14)
|
||||
#define CIVETWEB_VERSION_PATCH (0)
|
||||
|
||||
#ifndef CIVETWEB_API
|
||||
@@ -98,8 +98,13 @@ enum {
|
||||
/* Will only work, if USE_ZLIB is set. */
|
||||
MG_FEATURES_COMPRESSION = 0x200u,
|
||||
|
||||
/* Collect server status information. */
|
||||
/* Will only work, if USE_SERVER_STATS is set. */
|
||||
/* HTTP/2 support enabled. */
|
||||
MG_FEATURES_HTTP2 = 0x400u,
|
||||
|
||||
/* Support unix domain sockets. */
|
||||
MG_FEATURES_X_DOMAIN_SOCKET = 0x800u,
|
||||
|
||||
/* Bit mask for all feature defines. */
|
||||
MG_FEATURES_ALL = 0xFFFFu
|
||||
};
|
||||
|
||||
@@ -161,8 +166,11 @@ struct mg_request_info {
|
||||
|
||||
long long content_length; /* Length (in bytes) of the request body,
|
||||
can be -1 if no length was given. */
|
||||
int remote_port; /* Client's port */
|
||||
int is_ssl; /* 1 if SSL-ed, 0 if not */
|
||||
int remote_port; /* Port at client side */
|
||||
int server_port; /* Port at server side (one of the listening
|
||||
ports) */
|
||||
int is_ssl; /* 1 if HTTPS or WS is used (SSL/TLS used),
|
||||
0 if not */
|
||||
void *user_data; /* User data pointer passed to mg_start() */
|
||||
void *conn_data; /* Connection-specific user data */
|
||||
|
||||
@@ -293,21 +301,8 @@ struct mg_callbacks {
|
||||
void **ssl_ctx,
|
||||
void *user_data);
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2015-08-19 */ \
|
||||
|| defined(MG_EXPERIMENTAL_INTERFACES) /* 2019-11-03 */
|
||||
/* Called when websocket request is received, before websocket handshake.
|
||||
Return value:
|
||||
0: civetweb proceeds with websocket handshake.
|
||||
1: connection is closed immediately.
|
||||
This callback is deprecated: Use mg_set_websocket_handler instead. */
|
||||
int (*websocket_connect)(const struct mg_connection *);
|
||||
|
||||
/* Called when websocket handshake is successfully completed, and
|
||||
connection is ready for data exchange.
|
||||
This callback is deprecated: Use mg_set_websocket_handler instead. */
|
||||
void (*websocket_ready)(struct mg_connection *);
|
||||
|
||||
/* Called when data frame has been received from the client.
|
||||
#if defined(MG_EXPERIMENTAL_INTERFACES) /* 2019-11-03 */
|
||||
/* Called when data frame has been received from the peer.
|
||||
Parameters:
|
||||
bits: first byte of the websocket frame, see websocket RFC at
|
||||
http://tools.ietf.org/html/rfc6455, section 5.2
|
||||
@@ -355,14 +350,6 @@ struct mg_callbacks {
|
||||
void *lua_context,
|
||||
unsigned context_flags);
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2016-05-14 */
|
||||
/* Called when civetweb has uploaded a file to a temporary directory as a
|
||||
result of mg_upload() call.
|
||||
Note that mg_upload is deprecated. Use mg_handle_form_request instead.
|
||||
Parameters:
|
||||
file_name: full path name to the uploaded file. */
|
||||
void (*upload)(struct mg_connection *, const char *file_name);
|
||||
#endif
|
||||
|
||||
/* Called when civetweb is about to send HTTP error to the client.
|
||||
Implementing this callback allows to create custom error pages.
|
||||
@@ -580,7 +567,7 @@ typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
|
||||
*/
|
||||
struct mg_websocket_subprotocols {
|
||||
int nb_subprotocols;
|
||||
char **subprotocols;
|
||||
const char **subprotocols;
|
||||
};
|
||||
|
||||
/* mg_set_websocket_handler
|
||||
@@ -664,7 +651,14 @@ CIVETWEB_API void *mg_get_thread_pointer(const struct mg_connection *conn);
|
||||
|
||||
|
||||
/* Set user data for the current connection. */
|
||||
/* Note: This function is deprecated. Use the init_connection callback
|
||||
/* Note: CivetWeb callbacks use "struct mg_connection *conn" as input
|
||||
when mg_read/mg_write callbacks are allowed in the callback,
|
||||
while "const struct mg_connection *conn" is used as input in case
|
||||
calling mg_read/mg_write is not allowed.
|
||||
Setting the user connection data will modify the connection
|
||||
object represented by mg_connection *, but it will not read from
|
||||
or write to the connection. */
|
||||
/* Note: An alternative is to use the init_connection callback
|
||||
instead to initialize the user connection data pointer. It is
|
||||
reccomended to supply a pointer to some user defined data structure
|
||||
as conn_data initializer in init_connection. In case it is required
|
||||
@@ -672,7 +666,7 @@ CIVETWEB_API void *mg_get_thread_pointer(const struct mg_connection *conn);
|
||||
data pointer in the user defined data structure and modify that
|
||||
pointer. In either case, after the init_connection callback, only
|
||||
calls to mg_get_user_connection_data should be required. */
|
||||
CIVETWEB_API void mg_set_user_connection_data(struct mg_connection *conn,
|
||||
CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn,
|
||||
void *data);
|
||||
|
||||
|
||||
@@ -694,16 +688,6 @@ CIVETWEB_API int
|
||||
mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen);
|
||||
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2014-02-21 */
|
||||
/* Return array of strings that represent valid configuration options.
|
||||
For each option, option name and default value is returned, i.e. the
|
||||
number of entries in the array equals to number_of_options x 2.
|
||||
Array is NULL terminated. */
|
||||
/* Deprecated: Use mg_get_valid_options instead. */
|
||||
CIVETWEB_API const char **mg_get_valid_option_names(void);
|
||||
#endif
|
||||
|
||||
|
||||
struct mg_option {
|
||||
const char *name;
|
||||
int type;
|
||||
@@ -876,12 +860,6 @@ CIVETWEB_API void mg_lock_connection(struct mg_connection *conn);
|
||||
CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);
|
||||
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2014-06-21 */
|
||||
#define mg_lock mg_lock_connection
|
||||
#define mg_unlock mg_unlock_connection
|
||||
#endif
|
||||
|
||||
|
||||
/* Lock server context. This lock may be used to protect resources
|
||||
that are shared between different connection/worker threads.
|
||||
If the given context is not server, these functions do nothing. */
|
||||
@@ -1243,16 +1221,6 @@ mg_download(const char *host,
|
||||
CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
|
||||
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2016-05-14 */
|
||||
/* File upload functionality. Each uploaded file gets saved into a temporary
|
||||
file and MG_UPLOAD event is sent.
|
||||
Return number of uploaded files.
|
||||
Deprecated: Use mg_handle_form_request instead. */
|
||||
CIVETWEB_API int mg_upload(struct mg_connection *conn,
|
||||
const char *destination_dir);
|
||||
#endif
|
||||
|
||||
|
||||
/* This structure contains callback functions for handling form fields.
|
||||
It is used as an argument to mg_handle_form_request. */
|
||||
struct mg_form_data_handler {
|
||||
@@ -1468,6 +1436,19 @@ mg_connect_websocket_client(const char *host,
|
||||
mg_websocket_close_handler close_func,
|
||||
void *user_data);
|
||||
|
||||
CIVETWEB_API struct mg_connection *
|
||||
mg_connect_websocket_client_extensions(const char *host,
|
||||
int port,
|
||||
int use_ssl,
|
||||
char *error_buffer,
|
||||
size_t error_buffer_size,
|
||||
const char *path,
|
||||
const char *origin,
|
||||
const char *extensions,
|
||||
mg_websocket_data_handler data_func,
|
||||
mg_websocket_close_handler close_func,
|
||||
void *user_data);
|
||||
|
||||
|
||||
/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
|
||||
Parameters:
|
||||
@@ -1514,12 +1495,24 @@ CIVETWEB_API struct mg_connection *mg_connect_websocket_client_secure(
|
||||
mg_websocket_close_handler close_func,
|
||||
void *user_data);
|
||||
|
||||
CIVETWEB_API struct mg_connection *
|
||||
mg_connect_websocket_client_secure_extensions(
|
||||
const struct mg_client_options *client_options,
|
||||
char *error_buffer,
|
||||
size_t error_buffer_size,
|
||||
const char *path,
|
||||
const char *origin,
|
||||
const char *extensions,
|
||||
mg_websocket_data_handler data_func,
|
||||
mg_websocket_close_handler close_func,
|
||||
void *user_data);
|
||||
|
||||
#if defined(MG_LEGACY_INTERFACE) /* 2019-11-02 */
|
||||
enum { TIMEOUT_INFINITE = -1 };
|
||||
#endif
|
||||
enum { MG_TIMEOUT_INFINITE = -1 };
|
||||
|
||||
|
||||
/* Wait for a response from the server
|
||||
Parameters:
|
||||
conn: connection
|
||||
@@ -1537,6 +1530,76 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn,
|
||||
int timeout);
|
||||
|
||||
|
||||
/* mg_response_header_* functions can be used from server callbacks
|
||||
* to prepare HTTP server response headers. Using this function will
|
||||
* allow a callback to work with HTTP/1.x and HTTP/2.
|
||||
*/
|
||||
|
||||
/* Initialize a new HTTP response
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* status: HTTP status code (e.g., 200 for "OK").
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
*/
|
||||
CIVETWEB_API int mg_response_header_start(struct mg_connection *conn,
|
||||
int status);
|
||||
|
||||
|
||||
/* Add a new HTTP response header line
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* header: Header name.
|
||||
* value: Header value.
|
||||
* value_len: Length of header value, excluding the terminating zero.
|
||||
* Use -1 for "strlen(value)".
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
* -4: too many headers
|
||||
* -5: out of memory
|
||||
*/
|
||||
CIVETWEB_API int mg_response_header_add(struct mg_connection *conn,
|
||||
const char *header,
|
||||
const char *value,
|
||||
int value_len);
|
||||
|
||||
|
||||
/* Add a complete header string (key + value).
|
||||
* This function is less efficient as compared to mg_response_header_add,
|
||||
* and should only be used to convert complete HTTP/1.x header lines.
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* http1_headers: Header line(s) in the form "name: value\r\n".
|
||||
* Return:
|
||||
* >=0: no error, number of header lines added
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
* -4: too many headers
|
||||
* -5: out of memory
|
||||
*/
|
||||
CIVETWEB_API int mg_response_header_add_lines(struct mg_connection *conn,
|
||||
const char *http1_headers);
|
||||
|
||||
|
||||
/* Send http response
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
*/
|
||||
CIVETWEB_API int mg_response_header_send(struct mg_connection *conn);
|
||||
|
||||
|
||||
/* Check which features where set when the civetweb library has been compiled.
|
||||
The function explicitly addresses compile time defines used when building
|
||||
the library - it does not mean, the feature has been initialized using a
|
||||
@@ -1606,6 +1669,14 @@ CIVETWEB_API int
|
||||
mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen);
|
||||
|
||||
|
||||
/* Disable HTTP keep-alive on a per-connection basis.
|
||||
Reference: https://github.com/civetweb/civetweb/issues/727
|
||||
Parameters:
|
||||
conn: Current connection handle.
|
||||
*/
|
||||
CIVETWEB_API void mg_disable_connection_keep_alive(struct mg_connection *conn);
|
||||
|
||||
|
||||
#if defined(MG_EXPERIMENTAL_INTERFACES)
|
||||
/* Get connection information. Useful for server diagnosis.
|
||||
Parameters:
|
||||
|
||||
Vendored
+1851
File diff suppressed because it is too large
Load Diff
Vendored
+277
@@ -0,0 +1,277 @@
|
||||
/* Experimental implementation for on-the-fly compression */
|
||||
#if !defined(USE_ZLIB)
|
||||
#error "This file must only be included, if USE_ZLIB is set"
|
||||
#endif
|
||||
|
||||
#if !defined(MEM_LEVEL)
|
||||
#define MEM_LEVEL (8)
|
||||
#endif
|
||||
|
||||
static void *
|
||||
zalloc(void *opaque, uInt items, uInt size)
|
||||
{
|
||||
struct mg_connection *conn = (struct mg_connection *)opaque;
|
||||
void *ret = mg_calloc_ctx(items, size, conn->phys_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zfree(void *opaque, void *address)
|
||||
{
|
||||
struct mg_connection *conn = (struct mg_connection *)opaque;
|
||||
(void)conn; /* not required */
|
||||
|
||||
mg_free(address);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_compressed_data(struct mg_connection *conn, struct mg_file *filep)
|
||||
{
|
||||
|
||||
int zret;
|
||||
z_stream zstream;
|
||||
int do_flush;
|
||||
unsigned bytes_avail;
|
||||
unsigned char in_buf[MG_BUF_LEN];
|
||||
unsigned char out_buf[MG_BUF_LEN];
|
||||
FILE *in_file = filep->access.fp;
|
||||
|
||||
/* Prepare state buffer. User server context memory allocation. */
|
||||
memset(&zstream, 0, sizeof(zstream));
|
||||
zstream.zalloc = zalloc;
|
||||
zstream.zfree = zfree;
|
||||
zstream.opaque = (void *)conn;
|
||||
|
||||
/* Initialize for GZIP compression (MAX_WBITS | 16) */
|
||||
zret = deflateInit2(&zstream,
|
||||
Z_BEST_COMPRESSION,
|
||||
Z_DEFLATED,
|
||||
MAX_WBITS | 16,
|
||||
MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
|
||||
if (zret != Z_OK) {
|
||||
mg_cry_internal(conn,
|
||||
"GZIP init failed (%i): %s",
|
||||
zret,
|
||||
(zstream.msg ? zstream.msg : "<no error message>"));
|
||||
deflateEnd(&zstream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read until end of file */
|
||||
do {
|
||||
zstream.avail_in = fread(in_buf, 1, MG_BUF_LEN, in_file);
|
||||
if (ferror(in_file)) {
|
||||
mg_cry_internal(conn, "fread failed: %s", strerror(ERRNO));
|
||||
(void)deflateEnd(&zstream);
|
||||
return;
|
||||
}
|
||||
|
||||
do_flush = (feof(in_file) ? Z_FINISH : Z_NO_FLUSH);
|
||||
zstream.next_in = in_buf;
|
||||
|
||||
/* run deflate() on input until output buffer not full, finish
|
||||
* compression if all of source has been read in */
|
||||
do {
|
||||
zstream.avail_out = MG_BUF_LEN;
|
||||
zstream.next_out = out_buf;
|
||||
zret = deflate(&zstream, do_flush);
|
||||
|
||||
if (zret == Z_STREAM_ERROR) {
|
||||
/* deflate error */
|
||||
zret = -97;
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_avail = MG_BUF_LEN - zstream.avail_out;
|
||||
if (bytes_avail) {
|
||||
if (mg_send_chunk(conn, (char *)out_buf, bytes_avail) < 0) {
|
||||
zret = -98;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while (zstream.avail_out == 0);
|
||||
|
||||
if (zret < -90) {
|
||||
/* Forward write error */
|
||||
break;
|
||||
}
|
||||
|
||||
if (zstream.avail_in != 0) {
|
||||
/* all input will be used, otherwise GZIP is incomplete */
|
||||
zret = -99;
|
||||
break;
|
||||
}
|
||||
|
||||
/* done when last data in file processed */
|
||||
} while (do_flush != Z_FINISH);
|
||||
|
||||
if (zret != Z_STREAM_END) {
|
||||
/* Error: We did not compress everything. */
|
||||
mg_cry_internal(conn,
|
||||
"GZIP incomplete (%i): %s",
|
||||
zret,
|
||||
(zstream.msg ? zstream.msg : "<no error message>"));
|
||||
}
|
||||
|
||||
deflateEnd(&zstream);
|
||||
|
||||
/* Send "end of chunked data" marker */
|
||||
mg_write(conn, "0\r\n\r\n", 5);
|
||||
}
|
||||
|
||||
#if defined(USE_WEBSOCKET) && defined(MG_EXPERIMENTAL_INTERFACES)
|
||||
int
|
||||
websocket_deflate_initialize(struct mg_connection *conn, int server)
|
||||
{
|
||||
int zret =
|
||||
deflateInit2(&conn->websocket_deflate_state,
|
||||
Z_BEST_COMPRESSION,
|
||||
Z_DEFLATED,
|
||||
server
|
||||
? -1 * conn->websocket_deflate_server_max_windows_bits
|
||||
: -1 * conn->websocket_deflate_client_max_windows_bits,
|
||||
MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (zret != Z_OK) {
|
||||
mg_cry_internal(conn,
|
||||
"Websocket deflate init failed (%i): %s",
|
||||
zret,
|
||||
(conn->websocket_deflate_state.msg
|
||||
? conn->websocket_deflate_state.msg
|
||||
: "<no error message>"));
|
||||
deflateEnd(&conn->websocket_deflate_state);
|
||||
return zret;
|
||||
}
|
||||
|
||||
zret = inflateInit2(
|
||||
&conn->websocket_inflate_state,
|
||||
server ? -1 * conn->websocket_deflate_client_max_windows_bits
|
||||
: -1 * conn->websocket_deflate_server_max_windows_bits);
|
||||
if (zret != Z_OK) {
|
||||
mg_cry_internal(conn,
|
||||
"Websocket inflate init failed (%i): %s",
|
||||
zret,
|
||||
(conn->websocket_inflate_state.msg
|
||||
? conn->websocket_inflate_state.msg
|
||||
: "<no error message>"));
|
||||
inflateEnd(&conn->websocket_inflate_state);
|
||||
return zret;
|
||||
}
|
||||
if ((conn->websocket_deflate_server_no_context_takeover && server)
|
||||
|| (conn->websocket_deflate_client_no_context_takeover && !server))
|
||||
conn->websocket_deflate_flush = Z_FULL_FLUSH;
|
||||
else
|
||||
conn->websocket_deflate_flush = Z_SYNC_FLUSH;
|
||||
|
||||
conn->websocket_deflate_initialized = 1;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
void
|
||||
websocket_deflate_negotiate(struct mg_connection *conn)
|
||||
{
|
||||
const char *extensions = mg_get_header(conn, "Sec-WebSocket-Extensions");
|
||||
int val;
|
||||
if (extensions && !strncmp(extensions, "permessage-deflate", 18)) {
|
||||
conn->accept_gzip = 1;
|
||||
conn->websocket_deflate_client_max_windows_bits = 15;
|
||||
conn->websocket_deflate_server_max_windows_bits = 15;
|
||||
conn->websocket_deflate_server_no_context_takeover = 0;
|
||||
conn->websocket_deflate_client_no_context_takeover = 0;
|
||||
extensions += 18;
|
||||
while (*extensions != '\0') {
|
||||
if (*extensions == ';' || *extensions == ' ')
|
||||
++extensions;
|
||||
else if (!strncmp(extensions, "server_no_context_takeover", 26)) {
|
||||
extensions += 26;
|
||||
conn->websocket_deflate_server_no_context_takeover = 1;
|
||||
} else if (!strncmp(extensions, "client_no_context_takeover", 26)) {
|
||||
extensions += 26;
|
||||
conn->websocket_deflate_client_no_context_takeover = 1;
|
||||
} else if (!strncmp(extensions, "server_max_window_bits", 22)) {
|
||||
extensions += 22;
|
||||
if (*extensions == '=') {
|
||||
++extensions;
|
||||
if (*extensions == '"')
|
||||
++extensions;
|
||||
val = 0;
|
||||
while (*extensions >= '0' && *extensions <= '9') {
|
||||
val = val * 10 + (*extensions - '0');
|
||||
++extensions;
|
||||
}
|
||||
if (val < 9 || val > 15) {
|
||||
// The permessage-deflate spec specifies that a
|
||||
// value of 8 is also allowed, but zlib doesn't accept
|
||||
// that.
|
||||
mg_cry_internal(conn,
|
||||
"server-max-window-bits must be "
|
||||
"between 9 and 15. Got %i",
|
||||
val);
|
||||
} else
|
||||
conn->websocket_deflate_server_max_windows_bits = val;
|
||||
if (*extensions == '"')
|
||||
++extensions;
|
||||
}
|
||||
} else if (!strncmp(extensions, "client_max_window_bits", 22)) {
|
||||
extensions += 22;
|
||||
if (*extensions == '=') {
|
||||
++extensions;
|
||||
if (*extensions == '"')
|
||||
++extensions;
|
||||
val = 0;
|
||||
while (*extensions >= '0' && *extensions <= '9') {
|
||||
val = val * 10 + (*extensions - '0');
|
||||
++extensions;
|
||||
}
|
||||
if (val < 9 || val > 15)
|
||||
// The permessage-deflate spec specifies that a
|
||||
// value of 8 is also allowed, but zlib doesn't
|
||||
// accept that.
|
||||
mg_cry_internal(conn,
|
||||
"client-max-window-bits must be "
|
||||
"between 9 and 15. Got %i",
|
||||
val);
|
||||
else
|
||||
conn->websocket_deflate_client_max_windows_bits = val;
|
||||
if (*extensions == '"')
|
||||
++extensions;
|
||||
}
|
||||
} else {
|
||||
mg_cry_internal(conn,
|
||||
"Unknown parameter %s for permessage-deflate",
|
||||
extensions);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
conn->accept_gzip = 0;
|
||||
}
|
||||
conn->websocket_deflate_initialized = 0;
|
||||
}
|
||||
|
||||
void
|
||||
websocket_deflate_response(struct mg_connection *conn)
|
||||
{
|
||||
if (conn->accept_gzip) {
|
||||
mg_printf(conn,
|
||||
"Sec-WebSocket-Extensions: permessage-deflate; "
|
||||
"server_max_window_bits=%i; "
|
||||
"client_max_window_bits=%i"
|
||||
"%s%s\r\n",
|
||||
conn->websocket_deflate_server_max_windows_bits,
|
||||
conn->websocket_deflate_client_max_windows_bits,
|
||||
conn->websocket_deflate_client_no_context_takeover
|
||||
? "; client_no_context_takeover"
|
||||
: "",
|
||||
conn->websocket_deflate_server_no_context_takeover
|
||||
? "; server_no_context_takeover"
|
||||
: "");
|
||||
};
|
||||
}
|
||||
#endif
|
||||
Vendored
+318
@@ -0,0 +1,318 @@
|
||||
/* response.inl
|
||||
*
|
||||
* Bufferring for HTTP headers for HTTP response.
|
||||
* This function are only intended to be used at the server side.
|
||||
* Optional for HTTP/1.0 and HTTP/1.1, mandatory for HTTP/2.
|
||||
*
|
||||
* This file is part of the CivetWeb project.
|
||||
*/
|
||||
|
||||
#if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2)
|
||||
#error "HTTP2 currently works only if NO_RESPONSE_BUFFERING is not set"
|
||||
#endif
|
||||
|
||||
|
||||
/* Internal function to free header list */
|
||||
static void
|
||||
free_buffered_response_header_list(struct mg_connection *conn)
|
||||
{
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
while (conn->response_info.num_headers > 0) {
|
||||
conn->response_info.num_headers--;
|
||||
mg_free((void *)conn->response_info
|
||||
.http_headers[conn->response_info.num_headers]
|
||||
.name);
|
||||
conn->response_info.http_headers[conn->response_info.num_headers].name =
|
||||
0;
|
||||
mg_free((void *)conn->response_info
|
||||
.http_headers[conn->response_info.num_headers]
|
||||
.value);
|
||||
conn->response_info.http_headers[conn->response_info.num_headers]
|
||||
.value = 0;
|
||||
}
|
||||
#else
|
||||
(void)conn; /* Nothing to do */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Send first line of HTTP/1.x response */
|
||||
static void
|
||||
send_http1_response_status_line(struct mg_connection *conn)
|
||||
{
|
||||
/* mg_get_response_code_text will never return NULL */
|
||||
const char *txt = mg_get_response_code_text(conn, conn->status_code);
|
||||
mg_printf(conn,
|
||||
"HTTP/%s %i %s\r\n",
|
||||
conn->request_info.http_version,
|
||||
conn->status_code,
|
||||
txt);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize a new HTTP response
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* status: HTTP status code (e.g., 200 for "OK").
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
*/
|
||||
int
|
||||
mg_response_header_start(struct mg_connection *conn, int status)
|
||||
{
|
||||
if ((conn == NULL) || (status < 100) || (status > 999)) {
|
||||
/* Parameter error */
|
||||
return -1;
|
||||
}
|
||||
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|
||||
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
|
||||
/* Only allowed in server context */
|
||||
return -2;
|
||||
}
|
||||
if (conn->request_state != 0) {
|
||||
/* only allowed if nothing was sent up to now */
|
||||
return -3;
|
||||
}
|
||||
conn->status_code = status;
|
||||
conn->request_state = 1;
|
||||
|
||||
/* Buffered response is stored, unbuffered response will be sent directly,
|
||||
* but we can only send HTTP/1.x response here */
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
free_buffered_response_header_list(conn);
|
||||
#else
|
||||
send_http1_response_status_line(conn);
|
||||
conn->request_state = 1; /* Reset from 10 to 1 */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Add a new HTTP response header line
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* header: Header name.
|
||||
* value: Header value.
|
||||
* value_len: Length of header value, excluding the terminating zero.
|
||||
* Use -1 for "strlen(value)".
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
* -4: too many headers
|
||||
* -5: out of memory
|
||||
*/
|
||||
int
|
||||
mg_response_header_add(struct mg_connection *conn,
|
||||
const char *header,
|
||||
const char *value,
|
||||
int value_len)
|
||||
{
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
int hidx;
|
||||
#endif
|
||||
|
||||
if ((conn == NULL) || (header == NULL) || (value == NULL)) {
|
||||
/* Parameter error */
|
||||
return -1;
|
||||
}
|
||||
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|
||||
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
|
||||
/* Only allowed in server context */
|
||||
return -2;
|
||||
}
|
||||
if (conn->request_state != 1) {
|
||||
/* only allowed if mg_response_header_start has been called before */
|
||||
return -3;
|
||||
}
|
||||
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
hidx = conn->response_info.num_headers;
|
||||
if (hidx >= MG_MAX_HEADERS) {
|
||||
/* Too many headers */
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* Alloc new element */
|
||||
conn->response_info.http_headers[hidx].name =
|
||||
mg_strdup_ctx(header, conn->phys_ctx);
|
||||
if (value_len >= 0) {
|
||||
char *hbuf = mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
|
||||
if (hbuf) {
|
||||
memcpy(hbuf, value, (unsigned)value_len);
|
||||
hbuf[value_len] = 0;
|
||||
}
|
||||
conn->response_info.http_headers[hidx].value = hbuf;
|
||||
} else {
|
||||
conn->response_info.http_headers[hidx].value =
|
||||
mg_strdup_ctx(value, conn->phys_ctx);
|
||||
}
|
||||
|
||||
if ((conn->response_info.http_headers[hidx].name == 0)
|
||||
|| (conn->response_info.http_headers[hidx].value == 0)) {
|
||||
/* Out of memory */
|
||||
mg_free((void *)conn->response_info.http_headers[hidx].name);
|
||||
conn->response_info.http_headers[hidx].name = 0;
|
||||
mg_free((void *)conn->response_info.http_headers[hidx].value);
|
||||
conn->response_info.http_headers[hidx].value = 0;
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* OK, header stored */
|
||||
conn->response_info.num_headers++;
|
||||
|
||||
#else
|
||||
if (value_len >= 0) {
|
||||
mg_printf(conn, "%s: %.*s\r\n", header, (int)value_len, value);
|
||||
} else {
|
||||
mg_printf(conn, "%s: %s\r\n", header, value);
|
||||
}
|
||||
conn->request_state = 1; /* Reset from 10 to 1 */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* forward */
|
||||
static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]);
|
||||
|
||||
|
||||
/* Add a complete header string (key + value).
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* http1_headers: Header line(s) in the form "name: value".
|
||||
* Return:
|
||||
* >=0: no error, number of header lines added
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
* -4: too many headers
|
||||
* -5: out of memory
|
||||
*/
|
||||
int
|
||||
mg_response_header_add_lines(struct mg_connection *conn,
|
||||
const char *http1_headers)
|
||||
{
|
||||
struct mg_header add_hdr[MG_MAX_HEADERS];
|
||||
int num_hdr, i, ret;
|
||||
char *workbuffer, *parse;
|
||||
|
||||
/* We need to work on a copy of the work buffer, sice parse_http_headers
|
||||
* will modify */
|
||||
workbuffer = mg_strdup_ctx(http1_headers, conn->phys_ctx);
|
||||
if (!workbuffer) {
|
||||
/* Out of memory */
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* Call existing method to split header buffer */
|
||||
parse = workbuffer;
|
||||
num_hdr = parse_http_headers(&parse, add_hdr);
|
||||
ret = num_hdr;
|
||||
|
||||
for (i = 0; i < num_hdr; i++) {
|
||||
int lret =
|
||||
mg_response_header_add(conn, add_hdr[i].name, add_hdr[i].value, -1);
|
||||
if ((ret > 0) && (lret < 0)) {
|
||||
/* Store error return value */
|
||||
ret = lret;
|
||||
}
|
||||
}
|
||||
|
||||
/* mg_response_header_add created a copy, so we can free the original */
|
||||
mg_free(workbuffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if defined USE_HTTP2
|
||||
static int http2_send_response_headers(struct mg_connection *conn);
|
||||
#endif
|
||||
|
||||
|
||||
/* Send http response
|
||||
* Parameters:
|
||||
* conn: Current connection handle.
|
||||
* Return:
|
||||
* 0: ok
|
||||
* -1: parameter error
|
||||
* -2: invalid connection type
|
||||
* -3: invalid connection status
|
||||
*/
|
||||
int
|
||||
mg_response_header_send(struct mg_connection *conn)
|
||||
{
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
int i;
|
||||
int has_date = 0;
|
||||
int has_connection = 0;
|
||||
#endif
|
||||
|
||||
if (conn == NULL) {
|
||||
/* Parameter error */
|
||||
return -1;
|
||||
}
|
||||
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|
||||
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
|
||||
/* Only allowed in server context */
|
||||
return -2;
|
||||
}
|
||||
if (conn->request_state != 1) {
|
||||
/* only allowed if mg_response_header_start has been called before */
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* State: 2 */
|
||||
conn->request_state = 2;
|
||||
|
||||
#if !defined(NO_RESPONSE_BUFFERING)
|
||||
if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
|
||||
#if defined USE_HTTP2
|
||||
int ret = http2_send_response_headers(conn);
|
||||
return ret ? 0 : 0; /* todo */
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send */
|
||||
send_http1_response_status_line(conn);
|
||||
for (i = 0; i < conn->response_info.num_headers; i++) {
|
||||
mg_printf(conn,
|
||||
"%s: %s\r\n",
|
||||
conn->response_info.http_headers[i].name,
|
||||
conn->response_info.http_headers[i].value);
|
||||
|
||||
/* Check for some special headers */
|
||||
if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) {
|
||||
has_date = 1;
|
||||
}
|
||||
if (!mg_strcasecmp("Connection",
|
||||
conn->response_info.http_headers[i].name)) {
|
||||
has_connection = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_date) {
|
||||
time_t curtime = time(NULL);
|
||||
char date[64];
|
||||
gmt_time_string(date, sizeof(date), &curtime);
|
||||
mg_printf(conn, "Date: %s\r\n", date);
|
||||
}
|
||||
if (!has_connection) {
|
||||
mg_printf(conn, "Connection: %s\r\n", suggest_connection_header(conn));
|
||||
}
|
||||
#endif
|
||||
|
||||
mg_write(conn, "\r\n", 2);
|
||||
conn->request_state = 3;
|
||||
|
||||
/* ok */
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user