Re-add asset fetching
This commit is contained in:
@@ -22,6 +22,8 @@ stylesheet=
|
||||
banner=
|
||||
# Time in seconds between status page recaching. (default: 15)
|
||||
recache_delay=15
|
||||
# Path (absolute or relative to working dir) to root of web. Not recommended.
|
||||
root=
|
||||
|
||||
## SERVICE EXAMPLE
|
||||
# Services are always defined in their own section with their name prepended by "service."
|
||||
|
||||
204
src/main.c
204
src/main.c
@@ -21,6 +21,7 @@ uint16_t web_port = 7800;
|
||||
char* web_stylesheet = "";
|
||||
char* web_banner = "";
|
||||
uint32_t web_recache = 30;
|
||||
char* web_root = "";
|
||||
|
||||
uint8_t daemon_enabled = 1;
|
||||
mxml_node_t* cached_index;
|
||||
@@ -63,6 +64,9 @@ static int config_handler(void* user, const char* section, const char* name, con
|
||||
strcpy(web_banner, value);
|
||||
} else if (strcmp(name, "recache_delay") == 0) {
|
||||
web_recache = atoi(value);
|
||||
} else if (strcmp(name, "root") == 0) {
|
||||
web_root = malloc(strlen(value)+1);
|
||||
strcpy(web_root, value);
|
||||
} else {
|
||||
printf("Unknown configuration entry \'%s\' in \'%s\'\n", name, section);
|
||||
}
|
||||
@@ -125,78 +129,7 @@ static void init_signals() {
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
}
|
||||
|
||||
static enum MHD_Result http_response(void *cls, struct MHD_Connection *conn, const char* uri, const char* method, const char* version, const char* upload_Data, size_t* upload_data_size, void** req_cls) {
|
||||
const union MHD_ConnectionInfo *info = MHD_get_connection_info(conn, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
|
||||
const char* client_ip = (char*)malloc(64);
|
||||
uint16_t client_port = 0;
|
||||
if (info != NULL) {
|
||||
const struct sockaddr *addr = info->client_addr;
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
|
||||
if (addr->sa_family == AF_INET) {
|
||||
const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
|
||||
client_ip = inet_ntop(AF_INET, &addr4->sin_addr, ip_str, sizeof(ip_str));
|
||||
client_port = ntohs(addr4->sin_port);
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
||||
client_ip = inet_ntop(AF_INET6, &addr6->sin6_addr, ip_str, sizeof(ip_str));
|
||||
client_port = ntohs(addr6->sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t response_code = 0;
|
||||
char* page;
|
||||
size_t page_size = 0;
|
||||
|
||||
if (strcmp(method, "GET") != 0 || strcmp(uri, "/") != 0)
|
||||
response_code = 400;
|
||||
|
||||
if (response_code != 200) {
|
||||
mxml_node_t* doc = mxmlNewXML("1.0");
|
||||
if (strcmp(uri, "/") == 0 && response_code == 0) {
|
||||
doc = cached_index;
|
||||
response_code = 200;
|
||||
} else {
|
||||
mxml_node_t* html = mxmlNewElement(doc, "html");
|
||||
mxmlElementSetAttr(html, "xmlns", "http://www.w3.org/1999/xhtml");
|
||||
mxmlElementSetAttr(html, "xml:lang", "en");
|
||||
mxmlElementSetAttr(html, "lang", "en");
|
||||
|
||||
mxml_node_t* head = mxmlNewElement(html, "head");
|
||||
mxml_node_t *title = mxmlNewElement(head, "title");
|
||||
mxmlNewText(title, 0, daemon_name);
|
||||
|
||||
mxml_node_t* meta_charset = mxmlNewElement(head, "meta");
|
||||
mxmlElementSetAttr(meta_charset, "http-equiv", "Content-Type");
|
||||
mxmlElementSetAttr(meta_charset, "content", "text/html; charset=utf-8");
|
||||
|
||||
mxml_node_t* meta_viewport = mxmlNewElement(head, "meta");
|
||||
mxmlElementSetAttr(meta_viewport, "name", "viewport");
|
||||
mxmlElementSetAttr(meta_viewport, "content", "width=device-width, initial-scale=1.0");
|
||||
|
||||
mxml_node_t* body = mxmlNewElement(html, "body");
|
||||
|
||||
mxml_node_t* center = mxmlNewElement(body, "center");
|
||||
|
||||
mxml_node_t* error_header = mxmlNewElement(center, "h1");
|
||||
char err_str[5];
|
||||
snprintf(err_str, sizeof(err_str)-1, "%i", response_code);
|
||||
mxmlNewText(error_header, 0, err_str);
|
||||
}
|
||||
page = mxmlSaveAllocString(doc, MXML_NO_CALLBACK);
|
||||
page_size = strlen(page);
|
||||
}
|
||||
|
||||
printf("[%lu] %s %s \"%s\" %s:%u %zu %zu %i\n", time(NULL), method, uri, version, client_ip, client_port, *upload_data_size, page_size, response_code);
|
||||
fflush(stdout);
|
||||
|
||||
struct MHD_Response* response = MHD_create_response_from_buffer_static(page_size, page);
|
||||
enum MHD_Result ret = MHD_queue_response(conn, response_code, response);
|
||||
MHD_destroy_response(response);
|
||||
return ret;
|
||||
};
|
||||
|
||||
mxml_node_t* generate_index() {
|
||||
static mxml_node_t* generate_index() {
|
||||
mxml_node_t* doc = mxmlNewXML("1.0");
|
||||
mxml_node_t* html = mxmlNewElement(doc, "html");
|
||||
mxmlElementSetAttr(html, "xmlns", "http://www.w3.org/1999/xhtml");
|
||||
@@ -215,7 +148,7 @@ mxml_node_t* generate_index() {
|
||||
mxmlElementSetAttr(meta_viewport, "name", "viewport");
|
||||
mxmlElementSetAttr(meta_viewport, "content", "width=device-width, initial-scale=1.0");
|
||||
|
||||
if (web_stylesheet != 0 && strcmp(web_stylesheet, "") != 0) {
|
||||
if (web_stylesheet != 0 && strlen(web_stylesheet) > 0) {
|
||||
mxml_node_t* stylesheet = mxmlNewElement(head, "link");
|
||||
mxmlElementSetAttr(stylesheet, "rel", "stylesheet");
|
||||
mxmlElementSetAttr(stylesheet, "href", web_stylesheet);
|
||||
@@ -355,6 +288,131 @@ mxml_node_t* generate_index() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
static uint16_t get_asset(char** buffer, const char* path, size_t* size) {
|
||||
*size = 0;
|
||||
if (strlen(web_root) + strlen(path) + 2 > PATH_MAX)
|
||||
return 404;
|
||||
|
||||
char full_path[PATH_MAX] = {};
|
||||
snprintf(full_path, sizeof(full_path), "%s%s", web_root, path);
|
||||
|
||||
char resolved_path[PATH_MAX] = {};
|
||||
if (realpath(full_path, resolved_path) == NULL)
|
||||
return 404;
|
||||
|
||||
char resolved_base[PATH_MAX] = {};
|
||||
if (realpath(web_root, resolved_base) == NULL)
|
||||
return 404;
|
||||
|
||||
size_t resolved_base_len = strlen(resolved_base);
|
||||
if (strncmp(resolved_path, resolved_base, resolved_base_len) != 0)
|
||||
return 404;
|
||||
|
||||
if (resolved_path[resolved_base_len] != '\0' && resolved_path[resolved_base_len] != '/')
|
||||
return 404;
|
||||
|
||||
FILE* asset = fopen(resolved_path, "rb");
|
||||
if (!asset) return 404;
|
||||
|
||||
fseek(asset, 0, SEEK_END);
|
||||
*size = ftell(asset);
|
||||
rewind(asset);
|
||||
|
||||
*buffer = (char*)malloc(*size + 1);
|
||||
if (!*buffer) {
|
||||
fclose(asset);
|
||||
*size = 0;
|
||||
return 500;
|
||||
}
|
||||
|
||||
size_t bytes_read = fread(*buffer, 1, *size, asset);
|
||||
fclose(asset);
|
||||
|
||||
if (bytes_read != *size) {
|
||||
free(*buffer);
|
||||
*size = 0;
|
||||
return 500;
|
||||
}
|
||||
|
||||
return 200;
|
||||
};
|
||||
|
||||
static enum MHD_Result http_response(void *cls, struct MHD_Connection *conn, const char* uri, const char* method, const char* version, const char* upload_Data, size_t* upload_data_size, void** req_cls) {
|
||||
const union MHD_ConnectionInfo *info = MHD_get_connection_info(conn, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
|
||||
const char* client_ip = (char*)malloc(64);
|
||||
uint16_t client_port = 0;
|
||||
if (info != NULL) {
|
||||
const struct sockaddr *addr = info->client_addr;
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
|
||||
if (addr->sa_family == AF_INET) {
|
||||
const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
|
||||
client_ip = inet_ntop(AF_INET, &addr4->sin_addr, ip_str, sizeof(ip_str));
|
||||
client_port = ntohs(addr4->sin_port);
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
||||
client_ip = inet_ntop(AF_INET6, &addr6->sin6_addr, ip_str, sizeof(ip_str));
|
||||
client_port = ntohs(addr6->sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t response_code = 0;
|
||||
char* page;
|
||||
size_t page_size = 0;
|
||||
|
||||
if (strcmp(method, "GET") != 0) response_code = 400;
|
||||
else
|
||||
if (strcmp(uri, "/") != 0) {
|
||||
if (web_root != 0 && strlen(web_root) > 0)
|
||||
response_code = get_asset(&page, uri, &page_size);
|
||||
else response_code = 404;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
mxml_node_t* doc = mxmlNewXML("1.0");
|
||||
if (strcmp(uri, "/") == 0 && response_code == 0) {
|
||||
doc = cached_index;
|
||||
response_code = 200;
|
||||
} else {
|
||||
mxml_node_t* html = mxmlNewElement(doc, "html");
|
||||
mxmlElementSetAttr(html, "xmlns", "http://www.w3.org/1999/xhtml");
|
||||
mxmlElementSetAttr(html, "xml:lang", "en");
|
||||
mxmlElementSetAttr(html, "lang", "en");
|
||||
|
||||
mxml_node_t* head = mxmlNewElement(html, "head");
|
||||
mxml_node_t *title = mxmlNewElement(head, "title");
|
||||
mxmlNewText(title, 0, daemon_name);
|
||||
|
||||
mxml_node_t* meta_charset = mxmlNewElement(head, "meta");
|
||||
mxmlElementSetAttr(meta_charset, "http-equiv", "Content-Type");
|
||||
mxmlElementSetAttr(meta_charset, "content", "text/html; charset=utf-8");
|
||||
|
||||
mxml_node_t* meta_viewport = mxmlNewElement(head, "meta");
|
||||
mxmlElementSetAttr(meta_viewport, "name", "viewport");
|
||||
mxmlElementSetAttr(meta_viewport, "content", "width=device-width, initial-scale=1.0");
|
||||
|
||||
mxml_node_t* body = mxmlNewElement(html, "body");
|
||||
|
||||
mxml_node_t* center = mxmlNewElement(body, "center");
|
||||
|
||||
mxml_node_t* error_header = mxmlNewElement(center, "h1");
|
||||
char err_str[5];
|
||||
snprintf(err_str, sizeof(err_str)-1, "%i", response_code);
|
||||
mxmlNewText(error_header, 0, err_str);
|
||||
}
|
||||
page = mxmlSaveAllocString(doc, MXML_NO_CALLBACK);
|
||||
page_size = strlen(page);
|
||||
}
|
||||
|
||||
printf("[%lu] %s %s \"%s\" %s:%u %zu %zu %i\n", time(NULL), method, uri, version, client_ip, client_port, *upload_data_size, page_size, response_code);
|
||||
fflush(stdout);
|
||||
|
||||
struct MHD_Response* response = MHD_create_response_from_buffer_static(page_size, page);
|
||||
enum MHD_Result ret = MHD_queue_response(conn, response_code, response);
|
||||
MHD_destroy_response(response);
|
||||
return ret;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
printf("Starting Stethoscope...\n");
|
||||
fflush(stdout);
|
||||
|
||||
Reference in New Issue
Block a user