|
@@ -678,7 +678,7 @@ enum {
|
|
#if defined(USE_LUA) && defined(USE_WEBSOCKET)
|
|
#if defined(USE_LUA) && defined(USE_WEBSOCKET)
|
|
LUA_WEBSOCKET_EXTENSIONS,
|
|
LUA_WEBSOCKET_EXTENSIONS,
|
|
#endif
|
|
#endif
|
|
- ACCESS_CONTROL_ALLOW_ORIGIN,
|
|
|
|
|
|
+ ACCESS_CONTROL_ALLOW_ORIGIN, ERROR_PAGES,
|
|
|
|
|
|
NUM_OPTIONS
|
|
NUM_OPTIONS
|
|
};
|
|
};
|
|
@@ -699,9 +699,9 @@ static struct mg_option config_options[] = {
|
|
{"global_auth_file", CONFIG_TYPE_FILE, NULL},
|
|
{"global_auth_file", CONFIG_TYPE_FILE, NULL},
|
|
{"index_files", 12345,
|
|
{"index_files", 12345,
|
|
#ifdef USE_LUA
|
|
#ifdef USE_LUA
|
|
- "index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,index.shtml,index.php"},
|
|
|
|
|
|
+ "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,index.shtml,index.php"},
|
|
#else
|
|
#else
|
|
- "index.html,index.htm,index.cgi,index.shtml,index.php"},
|
|
|
|
|
|
+ "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
|
|
#endif
|
|
#endif
|
|
{"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
|
|
{"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
|
|
{"access_control_list", 12345, NULL},
|
|
{"access_control_list", 12345, NULL},
|
|
@@ -727,6 +727,7 @@ static struct mg_option config_options[] = {
|
|
{"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
|
|
{"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
|
|
#endif
|
|
#endif
|
|
{"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
|
|
{"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
|
|
|
|
+ {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
|
|
|
|
|
|
{NULL, CONFIG_TYPE_UNKNOWN, NULL}
|
|
{NULL, CONFIG_TYPE_UNKNOWN, NULL}
|
|
};
|
|
};
|
|
@@ -1303,6 +1304,7 @@ static const char *suggest_connection_header(const struct mg_connection *conn)
|
|
}
|
|
}
|
|
|
|
|
|
static void handle_file_based_request(struct mg_connection *conn, const char *path, struct file *filep);
|
|
static void handle_file_based_request(struct mg_connection *conn, const char *path, struct file *filep);
|
|
|
|
+static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
|
|
|
|
|
|
static void send_http_error(struct mg_connection *, int, const char *,
|
|
static void send_http_error(struct mg_connection *, int, const char *,
|
|
PRINTF_FORMAT_STRING(const char *fmt), ...)
|
|
PRINTF_FORMAT_STRING(const char *fmt), ...)
|
|
@@ -1314,11 +1316,12 @@ static void send_http_error(struct mg_connection *conn, int status,
|
|
{
|
|
{
|
|
char buf[MG_BUF_LEN];
|
|
char buf[MG_BUF_LEN];
|
|
va_list ap;
|
|
va_list ap;
|
|
- int len = 0;
|
|
|
|
|
|
+ int len = 0, i, page_handler_found, scope;
|
|
char date[64];
|
|
char date[64];
|
|
time_t curtime = time(NULL);
|
|
time_t curtime = time(NULL);
|
|
- const char * error_handler = NULL;
|
|
|
|
|
|
+ const char *error_handler = NULL;
|
|
struct file error_page_file = STRUCT_FILE_INITIALIZER;
|
|
struct file error_page_file = STRUCT_FILE_INITIALIZER;
|
|
|
|
+ const char *error_page_file_ext, *tstr;
|
|
|
|
|
|
conn->status_code = status;
|
|
conn->status_code = status;
|
|
if (conn->in_error_handler ||
|
|
if (conn->in_error_handler ||
|
|
@@ -1326,10 +1329,39 @@ static void send_http_error(struct mg_connection *conn, int status,
|
|
conn->ctx->callbacks.http_error(conn, status)) {
|
|
conn->ctx->callbacks.http_error(conn, status)) {
|
|
|
|
|
|
if (!conn->in_error_handler) {
|
|
if (!conn->in_error_handler) {
|
|
- /* TODO: allow user defined error page */
|
|
|
|
- if ((error_handler!=NULL) && mg_stat(conn, error_handler, &error_page_file)) {
|
|
|
|
|
|
+ /* Send user defined error pages, if defined */
|
|
|
|
+ error_handler = conn->ctx->config[ERROR_PAGES];
|
|
|
|
+ error_page_file_ext = conn->ctx->config[INDEX_FILES];
|
|
|
|
+ page_handler_found = 0;
|
|
|
|
+ if (error_handler != NULL) {
|
|
|
|
+ for (scope=1; (scope<=3) && !page_handler_found; scope++) {
|
|
|
|
+ switch (scope) {
|
|
|
|
+ case 1:
|
|
|
|
+ len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%03u.", error_handler, status);
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%01uxx.", error_handler, status/100);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror.", error_handler);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ tstr = strchr(error_page_file_ext, '.');
|
|
|
|
+ while (tstr) {
|
|
|
|
+ for (i=1; i<32 && tstr[i]!=0 && tstr[i]!=','; i++) buf[len+i-1]=tstr[i];
|
|
|
|
+ buf[len+i-1]=0;
|
|
|
|
+ if (mg_stat(conn, buf, &error_page_file)) {
|
|
|
|
+ page_handler_found = 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ tstr = strchr(tstr+i, '.');
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (page_handler_found) {
|
|
conn->in_error_handler = 1;
|
|
conn->in_error_handler = 1;
|
|
- handle_file_based_request(conn, error_handler, &error_page_file);
|
|
|
|
|
|
+ handle_file_based_request(conn, buf, &error_page_file);
|
|
conn->in_error_handler = 0;
|
|
conn->in_error_handler = 0;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1621,8 +1653,7 @@ static int path_cannot_disclose_cgi(const char *path)
|
|
return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
|
|
return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-static int mg_stat(struct mg_connection *conn, const char *path,
|
|
|
|
- struct file *filep)
|
|
|
|
|
|
+static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
|
|
{
|
|
{
|
|
wchar_t wbuf[PATH_MAX];
|
|
wchar_t wbuf[PATH_MAX];
|
|
WIN32_FILE_ATTRIBUTE_DATA info;
|
|
WIN32_FILE_ATTRIBUTE_DATA info;
|