|
@@ -1257,7 +1257,7 @@ mg_current_thread_id(void)
|
|
|
|
|
|
|
|
|
static uint64_t
|
|
|
-mg_get_current_time_ns()
|
|
|
+mg_get_current_time_ns(void)
|
|
|
{
|
|
|
struct timespec tsnow;
|
|
|
clock_gettime(CLOCK_REALTIME, &tsnow);
|
|
@@ -2688,6 +2688,9 @@ mg_vsnprintf(const struct mg_connection *conn,
|
|
|
int n, ok;
|
|
|
|
|
|
if (buflen == 0) {
|
|
|
+ if (truncated) {
|
|
|
+ *truncated = 1;
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -6350,7 +6353,6 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */
|
|
|
|
|
|
if (truncated) {
|
|
|
mg_free(tmp_str);
|
|
|
- tmp_str = NULL;
|
|
|
goto interpret_cleanup;
|
|
|
}
|
|
|
sep_pos = strlen(tmp_str);
|
|
@@ -6657,6 +6659,9 @@ get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
|
|
|
path_len = strlen(path);
|
|
|
|
|
|
if (ctx == NULL || vec == NULL) {
|
|
|
+ if (vec != NULL) {
|
|
|
+ memset(vec, '\0', sizeof(struct vec));
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -7587,13 +7592,21 @@ mg_url_encode(const char *src, char *dst, size_t dst_len)
|
|
|
return (*src == '\0') ? (int)(pos - dst) : -1;
|
|
|
}
|
|
|
|
|
|
+/* Return 0 on success, non-zero if an error occurs. */
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
print_dir_entry(struct de *de)
|
|
|
{
|
|
|
- char size[64], mod[64], href[PATH_MAX * 3 /* worst case */];
|
|
|
+ size_t hrefsize;
|
|
|
+ char *href;
|
|
|
+ char size[64], mod[64];
|
|
|
struct tm *tm;
|
|
|
|
|
|
+ hrefsize = PATH_MAX * 3; /* worst case */
|
|
|
+ href = mg_malloc(hrefsize);
|
|
|
+ if (href == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
if (de->file.is_directory) {
|
|
|
mg_snprintf(de->conn,
|
|
|
NULL, /* Buffer is big enough */
|
|
@@ -7645,7 +7658,7 @@ print_dir_entry(struct de *de)
|
|
|
mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
|
|
|
mod[sizeof(mod) - 1] = '\0';
|
|
|
}
|
|
|
- mg_url_encode(de->file_name, href, sizeof(href));
|
|
|
+ mg_url_encode(de->file_name, href, hrefsize);
|
|
|
mg_printf(de->conn,
|
|
|
"<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
|
|
|
"<td> %s</td><td> %s</td></tr>\n",
|
|
@@ -7656,6 +7669,8 @@ print_dir_entry(struct de *de)
|
|
|
de->file.is_directory ? "/" : "",
|
|
|
mod,
|
|
|
size);
|
|
|
+ mg_free(href);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -7717,7 +7732,7 @@ static int
|
|
|
scan_directory(struct mg_connection *conn,
|
|
|
const char *dir,
|
|
|
void *data,
|
|
|
- void (*cb)(struct de *, void *))
|
|
|
+ int (*cb)(struct de *, void *))
|
|
|
{
|
|
|
char path[PATH_MAX];
|
|
|
struct dirent *dp;
|
|
@@ -7856,7 +7871,7 @@ realloc2(void *ptr, size_t size)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
dir_scan_callback(struct de *de, void *data)
|
|
|
{
|
|
|
struct dir_scan_data *dsd = (struct dir_scan_data *)data;
|
|
@@ -7876,6 +7891,8 @@ dir_scan_callback(struct de *de, void *data)
|
|
|
dsd->entries[dsd->num_entries].conn = de->conn;
|
|
|
dsd->num_entries++;
|
|
|
}
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -8917,8 +8934,9 @@ addenv(struct cgi_environment *env, const char *fmt, ...)
|
|
|
env->varused++;
|
|
|
}
|
|
|
|
|
|
+/* Return 0 on success, non-zero if an error occurs. */
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
prepare_cgi_environment(struct mg_connection *conn,
|
|
|
const char *prog,
|
|
|
struct cgi_environment *env)
|
|
@@ -8929,16 +8947,28 @@ prepare_cgi_environment(struct mg_connection *conn,
|
|
|
int i, truncated, uri_len;
|
|
|
|
|
|
if (conn == NULL || prog == NULL || env == NULL) {
|
|
|
- return;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
env->conn = conn;
|
|
|
env->buflen = CGI_ENVIRONMENT_SIZE;
|
|
|
env->bufused = 0;
|
|
|
env->buf = (char *)mg_malloc_ctx(env->buflen, conn->ctx);
|
|
|
+ if (env->buf == NULL) {
|
|
|
+ mg_cry(conn, "%s: Not enough memory for environmental buffer",
|
|
|
+ __func__);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
env->varlen = MAX_CGI_ENVIR_VARS;
|
|
|
env->varused = 0;
|
|
|
env->var = (char **)mg_malloc_ctx(env->buflen * sizeof(char *), conn->ctx);
|
|
|
+ if (env->var == NULL) {
|
|
|
+ mg_cry(conn,
|
|
|
+ "%s: Not enough memory for environmental variables",
|
|
|
+ __func__);
|
|
|
+ mg_free(env->buf);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
|
|
|
addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
|
|
@@ -9096,6 +9126,8 @@ prepare_cgi_environment(struct mg_connection *conn,
|
|
|
|
|
|
env->var[env->varused] = NULL;
|
|
|
env->buf[env->bufused] = '\0';
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -9120,7 +9152,12 @@ handle_cgi_request(struct mg_connection *conn, const char *prog)
|
|
|
|
|
|
buf = NULL;
|
|
|
buflen = 16384;
|
|
|
- prepare_cgi_environment(conn, prog, &blk);
|
|
|
+ i = prepare_cgi_environment(conn, prog, &blk);
|
|
|
+ if (i != 0) {
|
|
|
+ blk.buf = NULL;
|
|
|
+ blk.var = NULL;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
|
|
|
/* CGI must be executed in its own directory. 'dir' must point to the
|
|
|
* directory containing executable program, 'p' must point to the
|
|
@@ -9996,16 +10033,15 @@ print_props(struct mg_connection *conn,
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
print_dav_dir_entry(struct de *de, void *data)
|
|
|
{
|
|
|
char href[PATH_MAX];
|
|
|
- char href_encoded[PATH_MAX * 3 /* worst case */];
|
|
|
int truncated;
|
|
|
|
|
|
struct mg_connection *conn = (struct mg_connection *)data;
|
|
|
if (!de || !conn) {
|
|
|
- return;
|
|
|
+ return -1;
|
|
|
}
|
|
|
mg_snprintf(conn,
|
|
|
&truncated,
|
|
@@ -10016,9 +10052,20 @@ print_dav_dir_entry(struct de *de, void *data)
|
|
|
de->file_name);
|
|
|
|
|
|
if (!truncated) {
|
|
|
- mg_url_encode(href, href_encoded, PATH_MAX * 3);
|
|
|
+ size_t href_encoded_size;
|
|
|
+ char *href_encoded;
|
|
|
+
|
|
|
+ href_encoded_size = PATH_MAX * 3; /* worst case */
|
|
|
+ href_encoded = mg_malloc(href_encoded_size);
|
|
|
+ if (href_encoded == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ mg_url_encode(href, href_encoded, href_encoded_size);
|
|
|
print_props(conn, href_encoded, &de->file);
|
|
|
+ mg_free(href_encoded);
|
|
|
}
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -11396,6 +11443,7 @@ handle_request(struct mg_connection *conn)
|
|
|
void *callback_data = NULL;
|
|
|
mg_authorization_handler auth_handler = NULL;
|
|
|
void *auth_callback_data = NULL;
|
|
|
+ int handler_type;
|
|
|
time_t curtime = time(NULL);
|
|
|
char date[64];
|
|
|
|
|
@@ -11536,11 +11584,15 @@ handle_request(struct mg_connection *conn)
|
|
|
* protocol namespace or the websocket ws(s):// protocol namespace.
|
|
|
*/
|
|
|
is_websocket_request = is_websocket_protocol(conn);
|
|
|
-
|
|
|
+#if defined(USE_WEBSOCKET)
|
|
|
+ handler_type = is_websocket_request ? WEBSOCKET_HANDLER
|
|
|
+ : REQUEST_HANDLER;
|
|
|
+#else
|
|
|
+ handler_type = REQUEST_HANDLER;
|
|
|
+#endif /* defined(USE_WEBSOCKET) */
|
|
|
/* 5.2. check if the request will be handled by a callback */
|
|
|
if (get_request_handler(conn,
|
|
|
- is_websocket_request ? WEBSOCKET_HANDLER
|
|
|
- : REQUEST_HANDLER,
|
|
|
+ handler_type,
|
|
|
&callback_handler,
|
|
|
&subprotocols,
|
|
|
&ws_connect_handler,
|
|
@@ -12257,6 +12309,8 @@ set_ports_option(struct mg_context *ctx)
|
|
|
mg_cry(fc(ctx),
|
|
|
"cannot bind: address family not supported (entry %i)",
|
|
|
portsTotal);
|
|
|
+ closesocket(so.sock);
|
|
|
+ so.sock = INVALID_SOCKET;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -13614,7 +13668,9 @@ close_connection(struct mg_connection *conn)
|
|
|
void
|
|
|
mg_close_connection(struct mg_connection *conn)
|
|
|
{
|
|
|
+#if defined(USE_WEBSOCKET)
|
|
|
struct mg_context *client_ctx = NULL;
|
|
|
+#endif /* defined(USE_WEBSOCKET) */
|
|
|
|
|
|
if (conn == NULL) {
|
|
|
return;
|
|
@@ -13641,9 +13697,7 @@ mg_close_connection(struct mg_connection *conn)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-#else
|
|
|
- (void)client_ctx;
|
|
|
-#endif
|
|
|
+#endif /* defined(USE_WEBSOCKET) */
|
|
|
|
|
|
close_connection(conn);
|
|
|
|
|
@@ -13653,15 +13707,21 @@ mg_close_connection(struct mg_connection *conn)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#if defined(USE_WEBSOCKET)
|
|
|
if (client_ctx != NULL) {
|
|
|
/* free context */
|
|
|
mg_free(client_ctx->worker_threadids);
|
|
|
mg_free(client_ctx);
|
|
|
(void)pthread_mutex_destroy(&conn->mutex);
|
|
|
mg_free(conn);
|
|
|
- } else if (conn->ctx->context_type == 0) { // Client
|
|
|
+ } else if (conn->ctx->context_type == 0) { /* Client */
|
|
|
+ mg_free(conn);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ if (conn->ctx->context_type == 0) { /* Client */
|
|
|
mg_free(conn);
|
|
|
}
|
|
|
+#endif /* defined(USE_WEBSOCKET) */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -14943,7 +15003,6 @@ accept_new_connection(const struct socket *listener, struct mg_context *ctx)
|
|
|
sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
|
|
|
mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
|
|
|
closesocket(so.sock);
|
|
|
- so.sock = INVALID_SOCKET;
|
|
|
} else {
|
|
|
/* Put so socket structure into the queue */
|
|
|
DEBUG_TRACE("Accepted socket %d", (int)so.sock);
|
|
@@ -14998,6 +15057,7 @@ accept_new_connection(const struct socket *listener, struct mg_context *ctx)
|
|
|
|
|
|
set_blocking_mode(so.sock, 0);
|
|
|
|
|
|
+ so.in_use = 0;
|
|
|
produce_socket(ctx, &so);
|
|
|
}
|
|
|
}
|