Better unicode handling on win32

This commit is contained in:
cpq 2021-02-07 22:43:49 +00:00
parent a2f027e798
commit fd8db5c53a
6 changed files with 231 additions and 69 deletions

View File

@ -691,7 +691,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
LOG(LL_DEBUG,
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
if ((fp = mg_fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
return -2;
} else {
@ -729,9 +729,9 @@ static const char *guess_content_type(const char *filename) {
size_t ext_len;
const char *type;
} * t, types[] = {
MIME_ENTRY("html", "text/html"),
MIME_ENTRY("htm", "text/html"),
MIME_ENTRY("shtml", "text/html"),
MIME_ENTRY("html", "text/html; charset=utf-8"),
MIME_ENTRY("htm", "text/html; charset=utf-8"),
MIME_ENTRY("shtml", "text/html; charset=utf-8"),
MIME_ENTRY("css", "text/css"),
MIME_ENTRY("js", "text/javascript"),
MIME_ENTRY("mjs", "text/javascript"),
@ -742,7 +742,7 @@ static const char *guess_content_type(const char *filename) {
MIME_ENTRY("jpeg", "image/jpeg"),
MIME_ENTRY("png", "image/png"),
MIME_ENTRY("svg", "image/svg+xml"),
MIME_ENTRY("txt", "text/plain"),
MIME_ENTRY("txt", "text/plain; charset=utf-8"),
MIME_ENTRY("wav", "audio/wav"),
MIME_ENTRY("mp3", "audio/mpeg"),
MIME_ENTRY("mid", "audio/mid"),
@ -779,18 +779,21 @@ static const char *guess_content_type(const char *filename) {
if (mg_ncasecmp(t->ext, &filename[n - t->ext_len], t->ext_len)) continue;
return t->type;
}
return "text/plain";
return "text/plain; charset=utf-8";
}
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
const char *path, const char *mime, const char *hdrs) {
struct mg_str *inm = mg_http_get_header(hm, "If-None-Match");
mg_stat_t st;
FILE *fp = fopen(path, "rb");
char etag[64];
FILE *fp = mg_fopen(path, "rb");
if (fp == NULL || mg_stat(path, &st) != 0 ||
mg_http_etag(etag, sizeof(etag), &st) != etag) {
LOG(LL_DEBUG,
("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path, fp));
mg_http_reply(c, 404, "", "%s", "Not found\n");
if (fp != NULL) fclose(fp);
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
fclose(fp);
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
@ -950,12 +953,34 @@ struct dirent *readdir(DIR *d) {
}
#endif
static void printdirentry(struct mg_connection *c, struct mg_http_message *hm,
const char *name, mg_stat_t *stp) {
char size[64], mod[64];
static bool mg_is_safe(int c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL;
}
static int mg_url_encode(const char *s, char *buf, size_t len) {
int i, n = 0;
for (i = 0; s[i] != '\0'; i++) {
int c = *((const unsigned char *) (s + i));
if ((size_t) n + 4 >= len) return 0;
if (mg_is_safe(c)) {
buf[n++] = s[i];
} else {
buf[n++] = '%';
mg_hex(&s[i], 1, &buf[n]);
n += 2;
}
}
return n;
}
static void printdirentry(struct mg_connection *c, const char *name,
mg_stat_t *stp) {
char size[64], mod[64], path[MG_PATH_MAX];
int is_dir = S_ISDIR(stp->st_mode);
const char *slash = is_dir ? "/" : "";
const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : "";
// const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : "";
int n = 0;
if (is_dir) {
snprintf(size, sizeof(size), "%s", "[DIR]");
@ -971,11 +996,11 @@ static void printdirentry(struct mg_connection *c, struct mg_http_message *hm,
}
}
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime));
n = mg_url_encode(name, path, sizeof(path));
mg_printf(c,
" <tr><td><a href=\"%.*s%s%s%s\">%s%s</a></td>"
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
"<td>%s</td><td>%s</td></tr>\n",
(int) hm->uri.len, hm->uri.ptr, es, name, slash, name, slash, mod,
size);
n, path, slash, name, slash, mod, size);
}
static void listdir(struct mg_connection *c, struct mg_http_message *hm,
@ -983,20 +1008,52 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10];
struct dirent *dp;
DIR *dirp;
static const char *sort_js_code =
"<script>function srt(tb, sc, so, d) {"
"var tr = Array.prototype.slice.call(tb.rows, 0),"
"tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
"n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
"t1 = a.cells[2].getAttribute('name'), "
"t2 = b.cells[2].getAttribute('name'); "
"return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
"n1 ? parseInt(n2) - parseInt(n1) : "
"c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
static const char *sort_js_code2 =
"for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
"if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
"};"
"window.onload = function() {"
"var tb = document.getElementById('tb');"
"var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
"var sc = m[1], so = m[2]; document.onclick = function(ev) { "
"var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
"sc = c; ev.preventDefault();}};"
"srt(tb, sc, so, true);"
"}"
"</script>";
while (p > dir && *p != '/') *p-- = '\0';
if ((dirp = (opendir(dir))) != NULL) {
size_t off, n;
mg_printf(c, "%s\r\n", "HTTP/1.1 200 OK\r\nContent-Length: \r\n");
mg_printf(c, "%s\r\n",
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Content-Length: \r\n");
off = c->send.len; // Start of body
mg_printf(c,
"<!DOCTYPE html><html><head><title>Index of %.*s</title>"
"<!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>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
"<tr><th>Name</th><th>Modified</th><th>Size</th></tr>"
"<tr><td colspan=\"3\"><hr></td></tr></thead><tbody>\n",
(int) hm->uri.len, hm->uri.ptr, (int) hm->uri.len, hm->uri.ptr);
"<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>"
"<tr><td colspan=\"3\"><hr></td></tr>"
"</thead>"
"<tbody id=\"tb\">\n",
(int) hm->uri.len, hm->uri.ptr, sort_js_code, sort_js_code2,
(int) hm->uri.len, hm->uri.ptr);
while ((dp = readdir(dirp)) != NULL) {
mg_stat_t st;
const char *sep = dp->d_name[0] == MG_DIRSEP ? "/" : "";
@ -1008,7 +1065,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
} else if (mg_stat(path, &st) != 0) {
LOG(LL_ERROR, ("%lu stat(%s): %d", c->id, path, errno));
} else {
printdirentry(c, hm, dp->d_name, &st);
printdirentry(c, dp->d_name, &st);
}
}
closedir(dirp);
@ -1042,6 +1099,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
size_t n1 = strlen(t1), n2;
mg_url_decode(hm->uri.ptr, hm->uri.len, t1 + n1, sizeof(t1) - n1, 0);
LOG(LL_DEBUG, ("SERVE: [%s]", t1 + n1));
t1[sizeof(t1) - 1] = '\0';
n2 = strlen(t1);
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
@ -1057,16 +1115,17 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
// Requested file is located outside root directory, fail
mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len,
hm->uri.ptr);
} else {
FILE *fp = fopen(t2, "r");
FILE *fp = mg_fopen(t2, "r");
#if MG_ENABLE_SSI
if (is_index && fp == NULL) {
char *p = t2 + strlen(t2);
while (p > t2 && p[-1] != '/') p--;
strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2);
t2[sizeof(t2) - 1] = '\0';
fp = fopen(t2, "r");
fp = mg_fopen(t2, "r");
}
#endif
#if MG_ENABLE_HTTP_DEBUG_ENDPOINT
@ -3054,6 +3113,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
#ifndef MG_MAX_SSI_DEPTH
#define MG_MAX_SSI_DEPTH 5
#endif
@ -3061,7 +3121,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
#if MG_ENABLE_SSI
static char *mg_ssi(const char *path, const char *root, int depth) {
struct mg_iobuf b = {NULL, 0, 0};
FILE *fp = fopen(path, "rb");
FILE *fp = mg_fopen(path, "rb");
if (fp != NULL) {
char buf[BUFSIZ], arg[sizeof(buf)];
int ch, intag = 0;
@ -3735,21 +3795,42 @@ struct mg_str mg_url_pass(const char *url) {
#if MG_ENABLE_FS
size_t mg_file_size(const char *path) {
int mg_stat(const char *path, mg_stat_t *st) {
#ifdef _WIN32
wchar_t tmp[MG_PATH_MAX];
MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
return _wstati64(tmp, st);
#else
return stat(path, st);
#endif
}
FILE *mg_fopen(const char *path, const char *mode) {
#ifdef _WIN32
wchar_t b1[MG_PATH_MAX], b2[10];
MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
return _wfopen(b1, b2);
#else
return fopen(path, mode);
#endif
}
int64_t mg_file_size(const char *path) {
#if MG_ARCH == MG_ARCH_FREERTOS
struct FF_STAT st;
return ff_stat(path, &st) == 0 ? st.st_size : 0;
#else
struct stat st;
return stat(path, &st) == 0 ? st.st_size : 0;
mg_stat_t st;
return mg_stat(path, &st) == 0 ? st.st_size : 0;
#endif
}
char *mg_file_read(const char *path) {
FILE *fp;
char *data = NULL;
size_t size = mg_file_size(path);
if ((fp = fopen(path, "rb")) != NULL) {
size_t size = (size_t) mg_file_size(path);
if ((fp = mg_fopen(path, "rb")) != NULL) {
data = (char *) malloc(size + 1);
if (data != NULL) {
if (fread(data, 1, size, fp) != size) {
@ -3769,7 +3850,7 @@ bool mg_file_write(const char *path, const void *buf, size_t len) {
FILE *fp;
char tmp[MG_PATH_MAX];
snprintf(tmp, sizeof(tmp), "%s.%d", path, rand());
fp = fopen(tmp, "wb");
fp = mg_fopen(tmp, "wb");
if (fp != NULL) {
result = fwrite(buf, 1, len, fp) == len;
fclose(fp);
@ -3797,7 +3878,7 @@ bool mg_file_printf(const char *path, const char *fmt, ...) {
}
void mg_random(void *buf, size_t len) {
FILE *fp = fopen("/dev/urandom", "rb");
FILE *fp = mg_fopen("/dev/urandom", "rb");
size_t i, n = 0;
if (fp != NULL) n = fread(buf, 1, len, fp);
if (fp == NULL || n <= 0) {

View File

@ -428,7 +428,7 @@ void mg_timer_poll(unsigned long uptime_ms);
char *mg_file_read(const char *path);
size_t mg_file_size(const char *path);
int64_t mg_file_size(const char *path);
bool mg_file_write(const char *path, const void *buf, size_t len);
bool mg_file_printf(const char *path, const char *fmt, ...);
void mg_random(void *buf, size_t len);
@ -450,11 +450,11 @@ void mg_usleep(unsigned long usecs);
#if MG_ENABLE_FS
#ifdef _WIN32
typedef struct _stati64 mg_stat_t;
#define mg_stat(a, b) _stati64((a), (b))
#else
typedef struct stat mg_stat_t;
#define mg_stat(a, b) stat((a), (b))
#endif
int mg_stat(const char *path, mg_stat_t *);
FILE *mg_fopen(const char *fp, const char *mode);
#endif
#define mg_htons(x) mg_ntohs(x)

View File

@ -271,7 +271,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
LOG(LL_DEBUG,
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
if ((fp = mg_fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
return -2;
} else {
@ -309,9 +309,9 @@ static const char *guess_content_type(const char *filename) {
size_t ext_len;
const char *type;
} * t, types[] = {
MIME_ENTRY("html", "text/html"),
MIME_ENTRY("htm", "text/html"),
MIME_ENTRY("shtml", "text/html"),
MIME_ENTRY("html", "text/html; charset=utf-8"),
MIME_ENTRY("htm", "text/html; charset=utf-8"),
MIME_ENTRY("shtml", "text/html; charset=utf-8"),
MIME_ENTRY("css", "text/css"),
MIME_ENTRY("js", "text/javascript"),
MIME_ENTRY("mjs", "text/javascript"),
@ -322,7 +322,7 @@ static const char *guess_content_type(const char *filename) {
MIME_ENTRY("jpeg", "image/jpeg"),
MIME_ENTRY("png", "image/png"),
MIME_ENTRY("svg", "image/svg+xml"),
MIME_ENTRY("txt", "text/plain"),
MIME_ENTRY("txt", "text/plain; charset=utf-8"),
MIME_ENTRY("wav", "audio/wav"),
MIME_ENTRY("mp3", "audio/mpeg"),
MIME_ENTRY("mid", "audio/mid"),
@ -359,18 +359,21 @@ static const char *guess_content_type(const char *filename) {
if (mg_ncasecmp(t->ext, &filename[n - t->ext_len], t->ext_len)) continue;
return t->type;
}
return "text/plain";
return "text/plain; charset=utf-8";
}
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
const char *path, const char *mime, const char *hdrs) {
struct mg_str *inm = mg_http_get_header(hm, "If-None-Match");
mg_stat_t st;
FILE *fp = fopen(path, "rb");
char etag[64];
FILE *fp = mg_fopen(path, "rb");
if (fp == NULL || mg_stat(path, &st) != 0 ||
mg_http_etag(etag, sizeof(etag), &st) != etag) {
LOG(LL_DEBUG,
("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path, fp));
mg_http_reply(c, 404, "", "%s", "Not found\n");
if (fp != NULL) fclose(fp);
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
fclose(fp);
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
@ -530,12 +533,34 @@ struct dirent *readdir(DIR *d) {
}
#endif
static void printdirentry(struct mg_connection *c, struct mg_http_message *hm,
const char *name, mg_stat_t *stp) {
char size[64], mod[64];
static bool mg_is_safe(int c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL;
}
static int mg_url_encode(const char *s, char *buf, size_t len) {
int i, n = 0;
for (i = 0; s[i] != '\0'; i++) {
int c = *((const unsigned char *) (s + i));
if ((size_t) n + 4 >= len) return 0;
if (mg_is_safe(c)) {
buf[n++] = s[i];
} else {
buf[n++] = '%';
mg_hex(&s[i], 1, &buf[n]);
n += 2;
}
}
return n;
}
static void printdirentry(struct mg_connection *c, const char *name,
mg_stat_t *stp) {
char size[64], mod[64], path[MG_PATH_MAX];
int is_dir = S_ISDIR(stp->st_mode);
const char *slash = is_dir ? "/" : "";
const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : "";
// const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : "";
int n = 0;
if (is_dir) {
snprintf(size, sizeof(size), "%s", "[DIR]");
@ -551,11 +576,11 @@ static void printdirentry(struct mg_connection *c, struct mg_http_message *hm,
}
}
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime));
n = mg_url_encode(name, path, sizeof(path));
mg_printf(c,
" <tr><td><a href=\"%.*s%s%s%s\">%s%s</a></td>"
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
"<td>%s</td><td>%s</td></tr>\n",
(int) hm->uri.len, hm->uri.ptr, es, name, slash, name, slash, mod,
size);
n, path, slash, name, slash, mod, size);
}
static void listdir(struct mg_connection *c, struct mg_http_message *hm,
@ -563,20 +588,52 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10];
struct dirent *dp;
DIR *dirp;
static const char *sort_js_code =
"<script>function srt(tb, sc, so, d) {"
"var tr = Array.prototype.slice.call(tb.rows, 0),"
"tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
"n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
"t1 = a.cells[2].getAttribute('name'), "
"t2 = b.cells[2].getAttribute('name'); "
"return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
"n1 ? parseInt(n2) - parseInt(n1) : "
"c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
static const char *sort_js_code2 =
"for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
"if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
"};"
"window.onload = function() {"
"var tb = document.getElementById('tb');"
"var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
"var sc = m[1], so = m[2]; document.onclick = function(ev) { "
"var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
"sc = c; ev.preventDefault();}};"
"srt(tb, sc, so, true);"
"}"
"</script>";
while (p > dir && *p != '/') *p-- = '\0';
if ((dirp = (opendir(dir))) != NULL) {
size_t off, n;
mg_printf(c, "%s\r\n", "HTTP/1.1 200 OK\r\nContent-Length: \r\n");
mg_printf(c, "%s\r\n",
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Content-Length: \r\n");
off = c->send.len; // Start of body
mg_printf(c,
"<!DOCTYPE html><html><head><title>Index of %.*s</title>"
"<!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>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
"<tr><th>Name</th><th>Modified</th><th>Size</th></tr>"
"<tr><td colspan=\"3\"><hr></td></tr></thead><tbody>\n",
(int) hm->uri.len, hm->uri.ptr, (int) hm->uri.len, hm->uri.ptr);
"<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>"
"<tr><td colspan=\"3\"><hr></td></tr>"
"</thead>"
"<tbody id=\"tb\">\n",
(int) hm->uri.len, hm->uri.ptr, sort_js_code, sort_js_code2,
(int) hm->uri.len, hm->uri.ptr);
while ((dp = readdir(dirp)) != NULL) {
mg_stat_t st;
const char *sep = dp->d_name[0] == MG_DIRSEP ? "/" : "";
@ -588,7 +645,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
} else if (mg_stat(path, &st) != 0) {
LOG(LL_ERROR, ("%lu stat(%s): %d", c->id, path, errno));
} else {
printdirentry(c, hm, dp->d_name, &st);
printdirentry(c, dp->d_name, &st);
}
}
closedir(dirp);
@ -622,6 +679,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
size_t n1 = strlen(t1), n2;
mg_url_decode(hm->uri.ptr, hm->uri.len, t1 + n1, sizeof(t1) - n1, 0);
LOG(LL_DEBUG, ("SERVE: [%s]", t1 + n1));
t1[sizeof(t1) - 1] = '\0';
n2 = strlen(t1);
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
@ -637,16 +695,17 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
// Requested file is located outside root directory, fail
mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len,
hm->uri.ptr);
} else {
FILE *fp = fopen(t2, "r");
FILE *fp = mg_fopen(t2, "r");
#if MG_ENABLE_SSI
if (is_index && fp == NULL) {
char *p = t2 + strlen(t2);
while (p > t2 && p[-1] != '/') p--;
strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2);
t2[sizeof(t2) - 1] = '\0';
fp = fopen(t2, "r");
fp = mg_fopen(t2, "r");
}
#endif
#if MG_ENABLE_HTTP_DEBUG_ENDPOINT

View File

@ -1,5 +1,6 @@
#include "log.h"
#include "ssi.h"
#include "log.h"
#include "util.h"
#ifndef MG_MAX_SSI_DEPTH
#define MG_MAX_SSI_DEPTH 5
@ -8,7 +9,7 @@
#if MG_ENABLE_SSI
static char *mg_ssi(const char *path, const char *root, int depth) {
struct mg_iobuf b = {NULL, 0, 0};
FILE *fp = fopen(path, "rb");
FILE *fp = mg_fopen(path, "rb");
if (fp != NULL) {
char buf[BUFSIZ], arg[sizeof(buf)];
int ch, intag = 0;

View File

@ -2,21 +2,42 @@
#include "util.h"
#if MG_ENABLE_FS
size_t mg_file_size(const char *path) {
int mg_stat(const char *path, mg_stat_t *st) {
#ifdef _WIN32
wchar_t tmp[MG_PATH_MAX];
MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
return _wstati64(tmp, st);
#else
return stat(path, st);
#endif
}
FILE *mg_fopen(const char *path, const char *mode) {
#ifdef _WIN32
wchar_t b1[MG_PATH_MAX], b2[10];
MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
return _wfopen(b1, b2);
#else
return fopen(path, mode);
#endif
}
int64_t mg_file_size(const char *path) {
#if MG_ARCH == MG_ARCH_FREERTOS
struct FF_STAT st;
return ff_stat(path, &st) == 0 ? st.st_size : 0;
#else
struct stat st;
return stat(path, &st) == 0 ? st.st_size : 0;
mg_stat_t st;
return mg_stat(path, &st) == 0 ? st.st_size : 0;
#endif
}
char *mg_file_read(const char *path) {
FILE *fp;
char *data = NULL;
size_t size = mg_file_size(path);
if ((fp = fopen(path, "rb")) != NULL) {
size_t size = (size_t) mg_file_size(path);
if ((fp = mg_fopen(path, "rb")) != NULL) {
data = (char *) malloc(size + 1);
if (data != NULL) {
if (fread(data, 1, size, fp) != size) {
@ -36,7 +57,7 @@ bool mg_file_write(const char *path, const void *buf, size_t len) {
FILE *fp;
char tmp[MG_PATH_MAX];
snprintf(tmp, sizeof(tmp), "%s.%d", path, rand());
fp = fopen(tmp, "wb");
fp = mg_fopen(tmp, "wb");
if (fp != NULL) {
result = fwrite(buf, 1, len, fp) == len;
fclose(fp);
@ -64,7 +85,7 @@ bool mg_file_printf(const char *path, const char *fmt, ...) {
}
void mg_random(void *buf, size_t len) {
FILE *fp = fopen("/dev/urandom", "rb");
FILE *fp = mg_fopen("/dev/urandom", "rb");
size_t i, n = 0;
if (fp != NULL) n = fread(buf, 1, len, fp);
if (fp == NULL || n <= 0) {

View File

@ -4,7 +4,7 @@
#include "str.h"
char *mg_file_read(const char *path);
size_t mg_file_size(const char *path);
int64_t mg_file_size(const char *path);
bool mg_file_write(const char *path, const void *buf, size_t len);
bool mg_file_printf(const char *path, const char *fmt, ...);
void mg_random(void *buf, size_t len);
@ -26,11 +26,11 @@ void mg_usleep(unsigned long usecs);
#if MG_ENABLE_FS
#ifdef _WIN32
typedef struct _stati64 mg_stat_t;
#define mg_stat(a, b) _stati64((a), (b))
#else
typedef struct stat mg_stat_t;
#define mg_stat(a, b) stat((a), (b))
#endif
int mg_stat(const char *path, mg_stat_t *);
FILE *mg_fopen(const char *fp, const char *mode);
#endif
#define mg_htons(x) mg_ntohs(x)