mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-27 15:01:03 +08:00
Using mg_snprintf() everywhere
This commit is contained in:
parent
f64c86d23f
commit
54f75889fa
@ -580,14 +580,17 @@ Usage example:
|
||||
mg_send(c, "hi", 2); // Append string "hi" to the output buffer
|
||||
```
|
||||
|
||||
### mg\_printf()
|
||||
### mg\_printf(), mg\_vprintf()
|
||||
|
||||
```c
|
||||
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
```
|
||||
|
||||
Same as `mg_send()`, but formats data using `printf()` semantics. Return
|
||||
number of bytes appended to the output buffer.
|
||||
<span class="badge bg-danger">NOTE: </span> See [mg\_snprintf](#mg_snprintf-mg_vsnprintf)
|
||||
for the list of supported format specifiers
|
||||
|
||||
Parameters:
|
||||
- `c` - a connection pointer
|
||||
@ -601,32 +604,6 @@ Usage example:
|
||||
mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer
|
||||
```
|
||||
|
||||
### mg\_vprintf()
|
||||
|
||||
```c
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
```
|
||||
|
||||
Same as `mg_printf()`, but takes `va_list` argument as a parameter.
|
||||
|
||||
Parameters:
|
||||
- `c` - A connection pointer
|
||||
- `fmt` - A format string in `printf` semantics
|
||||
- `ap` - An arguments list
|
||||
|
||||
Return value: Number of bytes appended to the output buffer.
|
||||
|
||||
Usage example:
|
||||
|
||||
```c
|
||||
void foo(struct mg_connection *c, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mg_vprintf(c, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
```
|
||||
|
||||
### mg\_straddr
|
||||
|
||||
```c
|
||||
@ -2385,10 +2362,11 @@ unsigned long val = mg_unhex(data, sizeof(data) - 1); // val is now 123
|
||||
```
|
||||
|
||||
|
||||
### mg\_asprintf()
|
||||
### mg\_asprintf(), mg\_vasprintf()
|
||||
|
||||
```c
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
```
|
||||
|
||||
Print message specified by printf-like format string `fmt` into a buffer
|
||||
@ -2411,38 +2389,42 @@ char buf[1024], *pbuf = &buf;
|
||||
mg_asprintf(&pbuf, sizeof(buf), "Hello, %s!", "world"); // buf is now "Hello, world!"
|
||||
```
|
||||
|
||||
### mg\_vasprintf()
|
||||
|
||||
### mg\_snprintf(), mg\_vsnprintf()
|
||||
```c
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
|
||||
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);
|
||||
size_t mg_asprintf(char **buf, size_t len, const char *fmt, ...);
|
||||
size_t mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
```
|
||||
|
||||
Same as `mg_asprintf()` but uses `va_list` argument.
|
||||
Print formatted string into a string buffer, just like `snprintf()`
|
||||
standard function does, but in a predictable way that does not depend on
|
||||
the C library or the build environment. The return value can be larger
|
||||
than the buffer length `len`, in which case the overflow bytes are not printed.
|
||||
|
||||
Parameters:
|
||||
- `buf` - Pointer to pointer to output buffer
|
||||
- `size` - Pre-allocated buffer size
|
||||
- `len` - Buffer size
|
||||
- `fmt` - printf-like format string
|
||||
- `ap` - Parameters list
|
||||
|
||||
Supported format specifiers:
|
||||
- `hhd`, `hd`, `d`, `ld`, `lld` - for `char`, `short`, `int`, `long`, `int64_t`
|
||||
- `hhu`, `hu`, `u`, `lu`, `llu` - same but for unsigned variants
|
||||
- `hhx`, `hx`, `x`, `lx`, `llx` - same, unsigned and hex output
|
||||
- `s` - `for char *`
|
||||
- `p` - for any pointer, prints `0x.....` hex value
|
||||
- `%X.Y` - optional width and precision modifiers
|
||||
- `%.*` - optional precision modifier specified as `int` argument
|
||||
|
||||
Return value: Number of bytes printed
|
||||
|
||||
Usage example:
|
||||
|
||||
```c
|
||||
void foo(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
char buf[1024], *pbuf = buf;
|
||||
mg_vasprintf(&pbuf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
foo("Hello, %s!", "world"); // Print "Hello, world!
|
||||
|
||||
mg_snprintf(buf, sizeof(buf), "%lld", (int64_t) 123); // 123
|
||||
mg_snprintf(buf, sizeof(buf), "%.2s", "abcdef"); // ab
|
||||
mg_snprintf(buf, sizeof(buf), "%.*s", 2, "abcdef"); // ab
|
||||
mg_snprintf(buf, sizeof(buf), "%05x", 123); // 00123
|
||||
```
|
||||
|
||||
### mg\_to64()
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "mongoose.h"
|
||||
|
||||
static const char *s_debug_level = "2";
|
||||
static const char *s_root_dir = NULL;
|
||||
static const char *s_root_dir = ".";
|
||||
static const char *s_listening_address = "http://0.0.0.0:8000";
|
||||
static const char *s_enable_hexdump = "no";
|
||||
static const char *s_ssi_pattern = "#.html";
|
||||
|
124
mongoose.c
124
mongoose.c
@ -472,7 +472,7 @@ bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf,
|
||||
bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
|
||||
char tmp[256], *buf = tmp;
|
||||
bool result;
|
||||
int len;
|
||||
size_t len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
|
||||
@ -1246,8 +1246,8 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
||||
va_list ap) {
|
||||
char mem[256], *buf = mem;
|
||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_printf(c, "%X\r\n", len);
|
||||
size_t len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_printf(c, "%lx\r\n", (unsigned long) len);
|
||||
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
mg_send(c, "\r\n", 2);
|
||||
if (buf != mem) free(buf);
|
||||
@ -1261,7 +1261,7 @@ void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
|
||||
mg_printf(c, "%lX\r\n", (unsigned long) len);
|
||||
mg_printf(c, "%lx\r\n", (unsigned long) len);
|
||||
mg_send(c, buf, len);
|
||||
mg_send(c, "\r\n", 2);
|
||||
}
|
||||
@ -1341,13 +1341,13 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
||||
const char *fmt, ...) {
|
||||
char mem[256], *buf = mem;
|
||||
va_list ap;
|
||||
int len;
|
||||
size_t len;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
va_end(ap);
|
||||
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
|
||||
mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
|
||||
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
mg_send(c, buf, len > 0 ? len : 0);
|
||||
if (buf != mem) free(buf);
|
||||
}
|
||||
|
||||
@ -1481,7 +1481,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
|
||||
} else {
|
||||
int n, status = 200;
|
||||
char range[100] = "", tmp[50];
|
||||
char range[100] = "";
|
||||
int64_t r1 = 0, r2 = 0, cl = (int64_t) size;
|
||||
struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
|
||||
@ -1504,13 +1504,14 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
fs->sk(fd->fd, (size_t) r1);
|
||||
}
|
||||
}
|
||||
mg_snprintf(tmp, sizeof(tmp), "Content-Length: %lld\r\n", cl);
|
||||
LOG(LL_INFO, ("TMP: [%s]", tmp));
|
||||
mg_printf(c,
|
||||
"HTTP/1.1 %d %s\r\nContent-Type: %.*s\r\n"
|
||||
"Etag: %s\r\n%s%s%s\r\n",
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
"Content-Type: %.*s\r\n"
|
||||
"Etag: %s\r\n"
|
||||
"Content-Length: %llu\r\n"
|
||||
"%s%s\r\n",
|
||||
status, mg_http_status_code_str(status), (int) mime.len, mime.ptr,
|
||||
etag, tmp, range, opts->extra_headers ? opts->extra_headers : "");
|
||||
etag, cl, range, opts->extra_headers ? opts->extra_headers : "");
|
||||
if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
|
||||
c->is_draining = 1;
|
||||
mg_fs_close(fd);
|
||||
@ -1547,13 +1548,13 @@ static void printdirentry(const char *name, void *userdata) {
|
||||
if (flags & MG_FS_DIR) {
|
||||
mg_snprintf(sz, sizeof(sz), "%s", "[DIR]");
|
||||
} else {
|
||||
mg_snprintf(sz, sizeof(sz), "%llx", (uint64_t) size);
|
||||
mg_snprintf(sz, sizeof(sz), "%lld", (uint64_t) size);
|
||||
}
|
||||
mg_snprintf(mod, sizeof(mod), "%lx", (unsigned long) t);
|
||||
mg_snprintf(mod, sizeof(mod), "%ld", (unsigned long) t);
|
||||
n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
|
||||
mg_printf(d->c,
|
||||
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
|
||||
"<td name=%lu>%s</td><td name=" MG_INT64_FMT ">%s</td></tr>\n",
|
||||
"<td name=%lu>%s</td><td name=%lld>%s</td></tr>\n",
|
||||
n, path, slash, name, slash, (unsigned long) t, mod,
|
||||
flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
|
||||
}
|
||||
@ -1602,7 +1603,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
|
||||
"<style>th,td {text-align: left; padding-right: 1em; "
|
||||
"font-family: monospace; }</style></head>"
|
||||
"<body><h1>Innex of %.*s</h1><table cellpadding=\"0\"><thead>"
|
||||
"<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
|
||||
"<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
|
||||
"<a href=\"#\" rel=\"1\">Modified</a></th>"
|
||||
"<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
|
||||
@ -1611,6 +1612,9 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
"<tbody id=\"tb\">\n",
|
||||
(int) uri.len, uri.ptr, sort_js_code, sort_js_code2, (int) uri.len,
|
||||
uri.ptr);
|
||||
mg_printf(c, "%s",
|
||||
" <tr><td><a href=\"..\">..</a></td>"
|
||||
"<td name=-1></td><td name=-1>[DIR]</td></tr>\n");
|
||||
|
||||
fs->ls(dir, printdirentry, &d);
|
||||
mg_printf(c,
|
||||
@ -2077,11 +2081,11 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
|
||||
void mg_log(const char *fmt, ...) {
|
||||
char mem[256], *buf = mem;
|
||||
va_list ap;
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
va_end(ap);
|
||||
s_fn(buf, len > 0 ? (size_t) len : 0, s_fn_param);
|
||||
s_fn(buf, len > 0 ? len : 0, s_fn_param);
|
||||
s_fn("\n", 1, s_fn_param);
|
||||
if (buf != mem) free(buf);
|
||||
}
|
||||
@ -2584,16 +2588,16 @@ struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
||||
|
||||
|
||||
|
||||
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
char mem[256], *buf = mem;
|
||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
len = mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
size_t len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
len = mg_send(c, buf, len);
|
||||
if (buf != mem) free(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
int mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
int len = 0;
|
||||
size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
size_t len = 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vprintf(c, fmt, ap);
|
||||
@ -3202,7 +3206,7 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
|
||||
(char) ('0' + c->is_writable),
|
||||
'\0'};
|
||||
LOG(log_level,
|
||||
("%-3lu %s %d:%d %ld err %d (%s)", c->id, flags, (int) c->send.len,
|
||||
("%3lu %s %d:%d %ld err %d (%s)", c->id, flags, (int) c->send.len,
|
||||
(int) c->recv.len, n, MG_SOCK_ERRNO, strerror(errno)));
|
||||
if (n == 0) {
|
||||
// Do nothing
|
||||
@ -3981,7 +3985,8 @@ size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
|
||||
|
||||
static size_t mg_copys(char *buf, size_t len, size_t n, char *p, size_t k) {
|
||||
size_t j = 0;
|
||||
for (j = 0; j < k && j + n < len && p[j]; j++) buf[n + j] = p[j];
|
||||
for (j = 0; j < k && p[j]; j++)
|
||||
if (j + n < len) buf[n + j] = p[j];
|
||||
return j;
|
||||
}
|
||||
|
||||
@ -3989,8 +3994,9 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
size_t i = 0, n = 0;
|
||||
while (fmt[i] != '\0') {
|
||||
if (fmt[i] == '%') {
|
||||
size_t j, k, is_long = 0, w = 0 /* width */, pr = 0 /* precision */;
|
||||
size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = 0 /* prec */;
|
||||
char pad = ' ', c = fmt[++i];
|
||||
if (c == '#') x++, c = fmt[++i];
|
||||
if (c == '0') pad = '0', c = fmt[++i];
|
||||
while (isdigit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
|
||||
if (c == '.') {
|
||||
@ -4002,12 +4008,14 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
while (isdigit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
|
||||
}
|
||||
}
|
||||
while (c == 'h') c = fmt[++i]; // Treat h and hh as int
|
||||
if (c == 'l') {
|
||||
is_long++, c = fmt[++i];
|
||||
if (c == 'l') is_long++, c = fmt[++i];
|
||||
}
|
||||
if (c == 'd' || c == 'u' || c == 'x') {
|
||||
bool s = (c == 'd'), h = (c == 'x');
|
||||
if (c == 'p') x = 1, is_long = 1;
|
||||
if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p') {
|
||||
bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
|
||||
char tmp[30];
|
||||
if (is_long == 2) {
|
||||
int64_t v = va_arg(ap, int64_t);
|
||||
@ -4019,7 +4027,9 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
int v = va_arg(ap, int);
|
||||
k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
|
||||
}
|
||||
for (j = 0; n < len && k < w && j + k < w; j++) buf[n++] = pad;
|
||||
for (j = 0; k < w && j + k < w; j++)
|
||||
mg_copys(buf, len, n, &pad, 1), n++;
|
||||
if (x) mg_copys(buf, len, n, (char *) "0x", 2), n += 2;
|
||||
mg_copys(buf, len, n, tmp, k);
|
||||
n += k;
|
||||
} else if (c == 'c') {
|
||||
@ -4029,8 +4039,14 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
} else if (c == 's') {
|
||||
char *p = va_arg(ap, char *);
|
||||
if (pr == 0) pr = p == NULL ? 0 : strlen(p);
|
||||
for (j = 0; n < len && pr < w && j + pr < w; j++) buf[n++] = pad;
|
||||
for (j = 0; pr < w && j + pr < w; j++)
|
||||
mg_copys(buf, len, n, &pad, 1), n++;
|
||||
n += mg_copys(buf, len, n, p, pr);
|
||||
} else if (c == '%') {
|
||||
if (n < len) buf[n] = '%';
|
||||
n++;
|
||||
} else {
|
||||
abort(); // Unsupported format specifier
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
@ -4109,43 +4125,21 @@ void mg_unhex(const char *buf, size_t len, unsigned char *to) {
|
||||
}
|
||||
}
|
||||
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
size_t mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
va_list ap_copy;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, size, fmt, ap_copy);
|
||||
len = mg_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.
|
||||
// LCOV_EXCL_START
|
||||
*buf = NULL;
|
||||
while (len < 0) {
|
||||
free(*buf);
|
||||
if (size == 0) size = 5;
|
||||
size *= 2;
|
||||
if ((*buf = (char *) calloc(1, size)) == NULL) {
|
||||
len = -1;
|
||||
break;
|
||||
}
|
||||
if (len >= size) {
|
||||
// Allocate a buffer that is large enough
|
||||
if ((*buf = (char *) calloc(1, len + 1)) == NULL) {
|
||||
len = 0;
|
||||
} else {
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, size - 1, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
}
|
||||
// Microsoft version of vsnprintf() is not always null-terminated, so put
|
||||
// the terminator manually
|
||||
if (*buf != NULL) (*buf)[len] = 0;
|
||||
// LCOV_EXCL_STOP
|
||||
} else if (len >= (int) size) {
|
||||
/// Standard-compliant code path. Allocate a buffer that is large enough
|
||||
if ((*buf = (char *) calloc(1, (size_t) len + 1)) == NULL) {
|
||||
len = -1; // LCOV_EXCL_LINE
|
||||
} else { // LCOV_EXCL_LINE
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, (size_t) len + 1, fmt, ap_copy);
|
||||
len = mg_vsnprintf(*buf, len + 1, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
}
|
||||
}
|
||||
@ -4153,8 +4147,8 @@ int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
return len;
|
||||
}
|
||||
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
|
||||
int ret;
|
||||
size_t mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
|
||||
size_t ret;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = mg_vasprintf(buf, size, fmt, ap);
|
||||
@ -5036,7 +5030,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
|
||||
if (c != NULL) {
|
||||
char nonce[16], key[30], mem1[128], mem2[256], *buf1 = mem1, *buf2 = mem2;
|
||||
struct mg_str host = mg_url_host(url);
|
||||
int n1 = 0, n2 = 0;
|
||||
size_t n1 = 0, n2 = 0;
|
||||
if (fmt != NULL) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
@ -5058,7 +5052,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
|
||||
"Sec-WebSocket-Key: %s\r\n"
|
||||
"\r\n",
|
||||
mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
|
||||
mg_send(c, buf2, n2 > 0 ? (size_t) n2 : 0);
|
||||
mg_send(c, buf2, n2 > 0 ? n2 : 0);
|
||||
if (buf1 != mem1) free(buf1);
|
||||
if (buf2 != mem2) free(buf2);
|
||||
c->pfn = mg_ws_cb;
|
||||
|
20
mongoose.h
20
mongoose.h
@ -54,13 +54,11 @@ extern "C" {
|
||||
#endif
|
||||
#endif // !defined(MG_ARCH)
|
||||
|
||||
#if !defined(PRINTF_LIKE)
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||
#if defined(__GNUC__) && defined(__arm__)
|
||||
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||
#else
|
||||
#define PRINTF_LIKE(f, a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MG_ARCH == MG_ARCH_CUSTOM
|
||||
#include <mongoose_custom.h>
|
||||
@ -401,8 +399,6 @@ typedef int socklen_t;
|
||||
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#define MG_INT64_FMT "%I64d"
|
||||
|
||||
#ifndef MG_ENABLE_DIRLIST
|
||||
#define MG_ENABLE_DIRLIST 1
|
||||
#endif
|
||||
@ -505,10 +501,6 @@ typedef int socklen_t;
|
||||
#define MG_DIRSEP '/'
|
||||
#endif
|
||||
|
||||
#ifndef MG_INT64_FMT
|
||||
#define MG_INT64_FMT "%lld"
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_FILE
|
||||
#if defined(FOPEN_MAX)
|
||||
#define MG_ENABLE_FILE 1
|
||||
@ -550,13 +542,13 @@ bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
|
||||
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);
|
||||
size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
|
||||
size_t mg_snprintf(char *, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4);
|
||||
char *mg_hexdump(const void *buf, size_t len);
|
||||
char *mg_hex(const void *buf, size_t len, char *dst);
|
||||
void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||
unsigned long mg_unhexn(const char *s, size_t len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
size_t mg_asprintf(char **, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4);
|
||||
size_t mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
|
||||
@ -865,8 +857,8 @@ struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data);
|
||||
void mg_connect_resolved(struct mg_connection *);
|
||||
bool mg_send(struct mg_connection *, const void *, size_t);
|
||||
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
char *mg_straddr(struct mg_addr *, char *, size_t);
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||||
|
@ -29,13 +29,11 @@
|
||||
#endif
|
||||
#endif // !defined(MG_ARCH)
|
||||
|
||||
#if !defined(PRINTF_LIKE)
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||
#if defined(__GNUC__) && defined(__arm__)
|
||||
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||
#else
|
||||
#define PRINTF_LIKE(f, a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MG_ARCH == MG_ARCH_CUSTOM
|
||||
#include <mongoose_custom.h>
|
||||
|
@ -84,8 +84,6 @@ typedef int socklen_t;
|
||||
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#define MG_INT64_FMT "%I64d"
|
||||
|
||||
#ifndef MG_ENABLE_DIRLIST
|
||||
#define MG_ENABLE_DIRLIST 1
|
||||
#endif
|
||||
|
@ -95,10 +95,6 @@
|
||||
#define MG_DIRSEP '/'
|
||||
#endif
|
||||
|
||||
#ifndef MG_INT64_FMT
|
||||
#define MG_INT64_FMT "%lld"
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_FILE
|
||||
#if defined(FOPEN_MAX)
|
||||
#define MG_ENABLE_FILE 1
|
||||
|
2
src/fs.c
2
src/fs.c
@ -64,7 +64,7 @@ bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf,
|
||||
bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
|
||||
char tmp[256], *buf = tmp;
|
||||
bool result;
|
||||
int len;
|
||||
size_t len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
|
||||
|
34
src/http.c
34
src/http.c
@ -258,8 +258,8 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
||||
va_list ap) {
|
||||
char mem[256], *buf = mem;
|
||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_printf(c, "%X\r\n", len);
|
||||
size_t len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_printf(c, "%lx\r\n", (unsigned long) len);
|
||||
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
mg_send(c, "\r\n", 2);
|
||||
if (buf != mem) free(buf);
|
||||
@ -273,7 +273,7 @@ void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
|
||||
mg_printf(c, "%lX\r\n", (unsigned long) len);
|
||||
mg_printf(c, "%lx\r\n", (unsigned long) len);
|
||||
mg_send(c, buf, len);
|
||||
mg_send(c, "\r\n", 2);
|
||||
}
|
||||
@ -353,13 +353,13 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
||||
const char *fmt, ...) {
|
||||
char mem[256], *buf = mem;
|
||||
va_list ap;
|
||||
int len;
|
||||
size_t len;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
va_end(ap);
|
||||
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
|
||||
mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
|
||||
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
mg_send(c, buf, len > 0 ? len : 0);
|
||||
if (buf != mem) free(buf);
|
||||
}
|
||||
|
||||
@ -493,7 +493,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
|
||||
} else {
|
||||
int n, status = 200;
|
||||
char range[100] = "", tmp[50];
|
||||
char range[100] = "";
|
||||
int64_t r1 = 0, r2 = 0, cl = (int64_t) size;
|
||||
struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
|
||||
|
||||
@ -516,13 +516,14 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
fs->sk(fd->fd, (size_t) r1);
|
||||
}
|
||||
}
|
||||
mg_snprintf(tmp, sizeof(tmp), "Content-Length: %lld\r\n", cl);
|
||||
LOG(LL_INFO, ("TMP: [%s]", tmp));
|
||||
mg_printf(c,
|
||||
"HTTP/1.1 %d %s\r\nContent-Type: %.*s\r\n"
|
||||
"Etag: %s\r\n%s%s%s\r\n",
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
"Content-Type: %.*s\r\n"
|
||||
"Etag: %s\r\n"
|
||||
"Content-Length: %llu\r\n"
|
||||
"%s%s\r\n",
|
||||
status, mg_http_status_code_str(status), (int) mime.len, mime.ptr,
|
||||
etag, tmp, range, opts->extra_headers ? opts->extra_headers : "");
|
||||
etag, cl, range, opts->extra_headers ? opts->extra_headers : "");
|
||||
if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
|
||||
c->is_draining = 1;
|
||||
mg_fs_close(fd);
|
||||
@ -559,13 +560,13 @@ static void printdirentry(const char *name, void *userdata) {
|
||||
if (flags & MG_FS_DIR) {
|
||||
mg_snprintf(sz, sizeof(sz), "%s", "[DIR]");
|
||||
} else {
|
||||
mg_snprintf(sz, sizeof(sz), "%llx", (uint64_t) size);
|
||||
mg_snprintf(sz, sizeof(sz), "%lld", (uint64_t) size);
|
||||
}
|
||||
mg_snprintf(mod, sizeof(mod), "%lx", (unsigned long) t);
|
||||
mg_snprintf(mod, sizeof(mod), "%ld", (unsigned long) t);
|
||||
n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
|
||||
mg_printf(d->c,
|
||||
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
|
||||
"<td name=%lu>%s</td><td name=" MG_INT64_FMT ">%s</td></tr>\n",
|
||||
"<td name=%lu>%s</td><td name=%lld>%s</td></tr>\n",
|
||||
n, path, slash, name, slash, (unsigned long) t, mod,
|
||||
flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
|
||||
}
|
||||
@ -614,7 +615,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
|
||||
"<style>th,td {text-align: left; padding-right: 1em; "
|
||||
"font-family: monospace; }</style></head>"
|
||||
"<body><h1>Innex of %.*s</h1><table cellpadding=\"0\"><thead>"
|
||||
"<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
|
||||
"<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
|
||||
"<a href=\"#\" rel=\"1\">Modified</a></th>"
|
||||
"<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
|
||||
@ -623,6 +624,9 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||
"<tbody id=\"tb\">\n",
|
||||
(int) uri.len, uri.ptr, sort_js_code, sort_js_code2, (int) uri.len,
|
||||
uri.ptr);
|
||||
mg_printf(c, "%s",
|
||||
" <tr><td><a href=\"..\">..</a></td>"
|
||||
"<td name=-1></td><td name=-1>[DIR]</td></tr>\n");
|
||||
|
||||
fs->ls(dir, printdirentry, &d);
|
||||
mg_printf(c,
|
||||
|
@ -50,11 +50,11 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
|
||||
void mg_log(const char *fmt, ...) {
|
||||
char mem[256], *buf = mem;
|
||||
va_list ap;
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
va_end(ap);
|
||||
s_fn(buf, len > 0 ? (size_t) len : 0, s_fn_param);
|
||||
s_fn(buf, len > 0 ? len : 0, s_fn_param);
|
||||
s_fn("\n", 1, s_fn_param);
|
||||
if (buf != mem) free(buf);
|
||||
}
|
||||
|
10
src/net.c
10
src/net.c
@ -2,16 +2,16 @@
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
char mem[256], *buf = mem;
|
||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
len = mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
size_t len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
len = mg_send(c, buf, len);
|
||||
if (buf != mem) free(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
int mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
int len = 0;
|
||||
size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
size_t len = 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vprintf(c, fmt, ap);
|
||||
|
@ -69,8 +69,8 @@ struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data);
|
||||
void mg_connect_resolved(struct mg_connection *);
|
||||
bool mg_send(struct mg_connection *, const void *, size_t);
|
||||
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
char *mg_straddr(struct mg_addr *, char *, size_t);
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||||
|
@ -117,7 +117,7 @@ static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
|
||||
(char) ('0' + c->is_writable),
|
||||
'\0'};
|
||||
LOG(log_level,
|
||||
("%-3lu %s %d:%d %ld err %d (%s)", c->id, flags, (int) c->send.len,
|
||||
("%3lu %s %d:%d %ld err %d (%s)", c->id, flags, (int) c->send.len,
|
||||
(int) c->recv.len, n, MG_SOCK_ERRNO, strerror(errno)));
|
||||
if (n == 0) {
|
||||
// Do nothing
|
||||
|
68
src/str.c
68
src/str.c
@ -170,7 +170,8 @@ size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
|
||||
|
||||
static size_t mg_copys(char *buf, size_t len, size_t n, char *p, size_t k) {
|
||||
size_t j = 0;
|
||||
for (j = 0; j < k && j + n < len && p[j]; j++) buf[n + j] = p[j];
|
||||
for (j = 0; j < k && p[j]; j++)
|
||||
if (j + n < len) buf[n + j] = p[j];
|
||||
return j;
|
||||
}
|
||||
|
||||
@ -178,8 +179,9 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
size_t i = 0, n = 0;
|
||||
while (fmt[i] != '\0') {
|
||||
if (fmt[i] == '%') {
|
||||
size_t j, k, is_long = 0, w = 0 /* width */, pr = 0 /* precision */;
|
||||
size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = 0 /* prec */;
|
||||
char pad = ' ', c = fmt[++i];
|
||||
if (c == '#') x++, c = fmt[++i];
|
||||
if (c == '0') pad = '0', c = fmt[++i];
|
||||
while (isdigit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
|
||||
if (c == '.') {
|
||||
@ -191,12 +193,14 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
while (isdigit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
|
||||
}
|
||||
}
|
||||
while (c == 'h') c = fmt[++i]; // Treat h and hh as int
|
||||
if (c == 'l') {
|
||||
is_long++, c = fmt[++i];
|
||||
if (c == 'l') is_long++, c = fmt[++i];
|
||||
}
|
||||
if (c == 'd' || c == 'u' || c == 'x') {
|
||||
bool s = (c == 'd'), h = (c == 'x');
|
||||
if (c == 'p') x = 1, is_long = 1;
|
||||
if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p') {
|
||||
bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
|
||||
char tmp[30];
|
||||
if (is_long == 2) {
|
||||
int64_t v = va_arg(ap, int64_t);
|
||||
@ -208,7 +212,9 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
int v = va_arg(ap, int);
|
||||
k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
|
||||
}
|
||||
for (j = 0; n < len && k < w && j + k < w; j++) buf[n++] = pad;
|
||||
for (j = 0; k < w && j + k < w; j++)
|
||||
mg_copys(buf, len, n, &pad, 1), n++;
|
||||
if (x) mg_copys(buf, len, n, (char *) "0x", 2), n += 2;
|
||||
mg_copys(buf, len, n, tmp, k);
|
||||
n += k;
|
||||
} else if (c == 'c') {
|
||||
@ -218,8 +224,14 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
|
||||
} else if (c == 's') {
|
||||
char *p = va_arg(ap, char *);
|
||||
if (pr == 0) pr = p == NULL ? 0 : strlen(p);
|
||||
for (j = 0; n < len && pr < w && j + pr < w; j++) buf[n++] = pad;
|
||||
for (j = 0; pr < w && j + pr < w; j++)
|
||||
mg_copys(buf, len, n, &pad, 1), n++;
|
||||
n += mg_copys(buf, len, n, p, pr);
|
||||
} else if (c == '%') {
|
||||
if (n < len) buf[n] = '%';
|
||||
n++;
|
||||
} else {
|
||||
abort(); // Unsupported format specifier
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
@ -298,43 +310,21 @@ void mg_unhex(const char *buf, size_t len, unsigned char *to) {
|
||||
}
|
||||
}
|
||||
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
size_t mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
va_list ap_copy;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, size, fmt, ap_copy);
|
||||
len = mg_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.
|
||||
// LCOV_EXCL_START
|
||||
*buf = NULL;
|
||||
while (len < 0) {
|
||||
free(*buf);
|
||||
if (size == 0) size = 5;
|
||||
size *= 2;
|
||||
if ((*buf = (char *) calloc(1, size)) == NULL) {
|
||||
len = -1;
|
||||
break;
|
||||
}
|
||||
if (len >= size) {
|
||||
// Allocate a buffer that is large enough
|
||||
if ((*buf = (char *) calloc(1, len + 1)) == NULL) {
|
||||
len = 0;
|
||||
} else {
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, size - 1, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
}
|
||||
// Microsoft version of vsnprintf() is not always null-terminated, so put
|
||||
// the terminator manually
|
||||
if (*buf != NULL) (*buf)[len] = 0;
|
||||
// LCOV_EXCL_STOP
|
||||
} else if (len >= (int) size) {
|
||||
/// Standard-compliant code path. Allocate a buffer that is large enough
|
||||
if ((*buf = (char *) calloc(1, (size_t) len + 1)) == NULL) {
|
||||
len = -1; // LCOV_EXCL_LINE
|
||||
} else { // LCOV_EXCL_LINE
|
||||
va_copy(ap_copy, ap);
|
||||
len = vsnprintf(*buf, (size_t) len + 1, fmt, ap_copy);
|
||||
len = mg_vsnprintf(*buf, len + 1, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
}
|
||||
}
|
||||
@ -342,8 +332,8 @@ int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
||||
return len;
|
||||
}
|
||||
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
|
||||
int ret;
|
||||
size_t mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
|
||||
size_t ret;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = mg_vasprintf(buf, size, fmt, ap);
|
||||
|
@ -32,12 +32,12 @@ bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
|
||||
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);
|
||||
size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
|
||||
size_t mg_snprintf(char *, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4);
|
||||
char *mg_hexdump(const void *buf, size_t len);
|
||||
char *mg_hex(const void *buf, size_t len, char *dst);
|
||||
void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||
unsigned long mg_unhexn(const char *s, size_t len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
size_t mg_asprintf(char **, size_t, const char *fmt, ...) PRINTF_LIKE(3, 4);
|
||||
size_t mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
|
4
src/ws.c
4
src/ws.c
@ -216,7 +216,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
|
||||
if (c != NULL) {
|
||||
char nonce[16], key[30], mem1[128], mem2[256], *buf1 = mem1, *buf2 = mem2;
|
||||
struct mg_str host = mg_url_host(url);
|
||||
int n1 = 0, n2 = 0;
|
||||
size_t n1 = 0, n2 = 0;
|
||||
if (fmt != NULL) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
@ -238,7 +238,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
|
||||
"Sec-WebSocket-Key: %s\r\n"
|
||||
"\r\n",
|
||||
mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
|
||||
mg_send(c, buf2, n2 > 0 ? (size_t) n2 : 0);
|
||||
mg_send(c, buf2, n2 > 0 ? n2 : 0);
|
||||
if (buf1 != mem1) free(buf1);
|
||||
if (buf2 != mem2) free(buf2);
|
||||
c->pfn = mg_ws_cb;
|
||||
|
@ -1194,6 +1194,7 @@ static void test_timer(void) {
|
||||
|
||||
static void test_str(void) {
|
||||
char buf[100];
|
||||
size_t n = sizeof(buf);
|
||||
struct mg_str s = mg_strdup(mg_str("a"));
|
||||
ASSERT(mg_strcmp(s, mg_str("a")) == 0);
|
||||
free((void *) s.ptr);
|
||||
@ -1204,37 +1205,47 @@ static void test_str(void) {
|
||||
ASSERT(mg_strstr(mg_str("abc"), mg_str("b")) != NULL);
|
||||
ASSERT(mg_strcmp(mg_str("hi"), mg_strstrip(mg_str(" \thi\r\n"))) == 0);
|
||||
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%d", 0) == 1 && !strcmp(buf, "0"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%d", 1) == 1 && !strcmp(buf, "1"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%d", -1) == 2 && !strcmp(buf, "-1"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%.*s", 1, "ab") == 1 &&
|
||||
!strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%.1s", "ab") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%.99s", "a") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%11s", "a") == 11 &&
|
||||
!strcmp(buf, " a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%s", "a\0b") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%2s", "a") == 2 && !strcmp(buf, " a"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%.*s", 3, "a\0b") == 1 &&
|
||||
!strcmp(buf, "a"));
|
||||
memset(buf, 'x', sizeof(buf));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%d", 7) == 1 && !strcmp(buf, "7"));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ASSERT(mg_snprintf(buf, n, "%d", 0) == 1 && !strcmp(buf, "0"));
|
||||
ASSERT(mg_snprintf(buf, n, "%d", 1) == 1 && !strcmp(buf, "1"));
|
||||
ASSERT(mg_snprintf(buf, n, "%d", -1) == 2 && !strcmp(buf, "-1"));
|
||||
ASSERT(mg_snprintf(buf, n, "%.*s", 1, "ab") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%.1s", "ab") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%.99s", "a") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%11s", "a") == 11 && !strcmp(buf, " a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%s", "a\0b") == 1 && !strcmp(buf, "a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%2s", "a") == 2 && !strcmp(buf, " a"));
|
||||
ASSERT(mg_snprintf(buf, n, "%.*s", 3, "a\0b") == 1 && !strcmp(buf, "a"));
|
||||
memset(buf, 'x', n);
|
||||
ASSERT(mg_snprintf(buf, n, "%d", 7) == 1 && !strcmp(buf, "7"));
|
||||
memset(buf, 0, n);
|
||||
ASSERT(mg_snprintf(buf, 0, "%d", 123) == 3 && buf[0] == '\0');
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%lld", (uint64_t) 0xffffffffff) == 13 &&
|
||||
ASSERT(mg_snprintf(buf, n, "%lld", (uint64_t) 0xffffffffff) == 13 &&
|
||||
!strcmp(buf, "1099511627775"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%llx", (uint64_t) 0xffffffffff) == 10 &&
|
||||
ASSERT(mg_snprintf(buf, n, "%llx", (uint64_t) 0xffffffffff) == 10 &&
|
||||
!strcmp(buf, "ffffffffff"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%lx", (unsigned long) 0x6204d754) ==
|
||||
8 &&
|
||||
ASSERT(mg_snprintf(buf, n, "%lx", (unsigned long) 0x6204d754) == 8 &&
|
||||
!strcmp(buf, "6204d754"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "ab") == 2 && !strcmp(buf, "ab"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%dx", 1) == 2 && !strcmp(buf, "1x"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%sx", "a") == 2 && !strcmp(buf, "ax"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%cx", 32) == 2 && !strcmp(buf, " x"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%x", 15) == 1 && !strcmp(buf, "f"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%2x", 15) == 2 && !strcmp(buf, " f"));
|
||||
ASSERT(mg_snprintf(buf, sizeof(buf), "%02x", 15) == 2 && !strcmp(buf, "0f"));
|
||||
ASSERT(mg_snprintf(buf, n, "ab") == 2 && !strcmp(buf, "ab"));
|
||||
ASSERT(mg_snprintf(buf, n, "%dx", 1) == 2 && !strcmp(buf, "1x"));
|
||||
ASSERT(mg_snprintf(buf, n, "%sx", "a") == 2 && !strcmp(buf, "ax"));
|
||||
ASSERT(mg_snprintf(buf, n, "%cx", 32) == 2 && !strcmp(buf, " x"));
|
||||
ASSERT(mg_snprintf(buf, n, "%x", 15) == 1 && !strcmp(buf, "f"));
|
||||
ASSERT(mg_snprintf(buf, n, "%2x", 15) == 2 && !strcmp(buf, " f"));
|
||||
ASSERT(mg_snprintf(buf, n, "%02x", 15) == 2 && !strcmp(buf, "0f"));
|
||||
ASSERT(mg_snprintf(buf, n, "%p", (void *) (size_t) 7) == 3 &&
|
||||
!strcmp(buf, "0x7"));
|
||||
ASSERT(mg_snprintf(buf, n, "%hx:%hhx", (short) 1, (char) 2) == 3 &&
|
||||
!strcmp(buf, "1:2"));
|
||||
ASSERT(mg_snprintf(buf, n, "%hx:%hhx", (short) 1, (char) 2) == 3 &&
|
||||
!strcmp(buf, "1:2"));
|
||||
ASSERT(mg_snprintf(buf, n, "%%") == 1 && !strcmp(buf, "%"));
|
||||
ASSERT(mg_snprintf(buf, 10, "%s %s", "a", "b") == 3 && !strcmp(buf, "a b"));
|
||||
ASSERT(mg_snprintf(buf, 10, "%s %s", "a", "b") == 3 && !strcmp(buf, "a b"));
|
||||
buf[0] = '\0';
|
||||
ASSERT(mg_snprintf(0, 0, "ab%dc", 123) == 6 && buf[0] == '\0');
|
||||
ASSERT(mg_snprintf(0, 0, "%s ", "a") == 2 && buf[0] == '\0');
|
||||
ASSERT(mg_snprintf(0, 0, "%s %s", "a", "b") == 3 && buf[0] == '\0');
|
||||
ASSERT(mg_snprintf(0, 0, "%2s %s", "a", "b") == 4 && buf[0] == '\0');
|
||||
}
|
||||
|
||||
static void fn1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
@ -1371,9 +1382,9 @@ static void test_util(void) {
|
||||
|
||||
{
|
||||
s = buf;
|
||||
mg_asprintf(&s, sizeof(buf), "%s", "%3d", 123);
|
||||
mg_asprintf(&s, sizeof(buf), "%3d", 123);
|
||||
ASSERT(s == buf);
|
||||
ASSERT(strcmp(buf, "%3d") == 0);
|
||||
ASSERT(strcmp(buf, "123") == 0);
|
||||
mg_asprintf(&s, sizeof(buf), "%.*s", 7, "a%40b.c");
|
||||
ASSERT(s == buf);
|
||||
ASSERT(strcmp(buf, "a%40b.c") == 0);
|
||||
@ -1729,7 +1740,10 @@ static void test_get_header_var(void) {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
mg_log_set("3");
|
||||
const char *debug_level = getenv("V");
|
||||
if (debug_level == NULL) debug_level = "3";
|
||||
mg_log_set(debug_level);
|
||||
|
||||
test_str();
|
||||
test_globmatch();
|
||||
test_get_header_var();
|
||||
|
Loading…
x
Reference in New Issue
Block a user