From c1809aa935b55b9301199cf05fbe288cdc679cd2 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 14 Sep 2024 09:59:15 +0000 Subject: [PATCH] can show index git-svn-id: file:///raid/svn-personal/tewi/trunk@20 8739d7e6-ffea-ec47-b151-bdff447c6205 --- Common/cm_string.h | 2 + Common/string.c | 47 ++++++++++++ Module/mod_example.c | 2 + Server/config.c | 4 ++ Server/http.c | 29 ++++++++ Server/main.c | 2 +- Server/server.c | 168 +++++++++++++++++++++++++++++-------------- Server/ssl.c | 1 + Server/tw_http.h | 5 ++ Server/tw_module.h | 10 ++- example.conf | 2 +- 11 files changed, 214 insertions(+), 58 deletions(-) diff --git a/Common/cm_string.h b/Common/cm_string.h index 476e297..9adf0a1 100644 --- a/Common/cm_string.h +++ b/Common/cm_string.h @@ -5,6 +5,8 @@ #include +int cm_hex(const char* str, int len); +char* cm_html_escape(const char* str); char* cm_strcat(const char* a, const char* b); char* cm_strcat3(const char* a, const char* b, const char* c); char* cm_strdup(const char* str); diff --git a/Common/string.c b/Common/string.c index f858d77..c894d3f 100644 --- a/Common/string.c +++ b/Common/string.c @@ -3,6 +3,7 @@ #include #include #include +#include #include char* cm_strcat(const char* a, const char* b) { @@ -112,3 +113,49 @@ bool cm_strcaseequ(const char* a, const char* b) { } return true; } + +int cm_hex(const char* str, int len) { + int n = 0; + int i; + for(i = 0; i < len; i++) { + char c = str[i]; + n *= 16; + if('0' <= c && c <= '9') { + n += c - '0'; + } else if('a' <= c && c <= 'f') { + n += c - 'a' + 10; + } else if('A' <= c && c <= 'F') { + n += c - 'A' + 10; + } + } + return n; +} + +char* cm_html_escape(const char* str) { + int i; + char* result = malloc(1); + result[0] = 0; + char cbuf[2]; + cbuf[1] = 0; + for(i = 0; str[i] != 0; i++) { + cbuf[0] = str[i]; + if(str[i] == '&') { + char* tmp = result; + result = cm_strcat(tmp, "&"); + free(tmp); + } else if(str[i] == '<') { + char* tmp = result; + result = cm_strcat(tmp, "<"); + free(tmp); + } else if(str[i] == '>') { + char* tmp = result; + result = cm_strcat(tmp, ">"); + free(tmp); + } else { + char* tmp = result; + result = cm_strcat(tmp, cbuf); + free(tmp); + } + } + return result; +} diff --git a/Module/mod_example.c b/Module/mod_example.c index a26569f..fb22373 100644 --- a/Module/mod_example.c +++ b/Module/mod_example.c @@ -7,3 +7,5 @@ int mod_init(struct tw_config* config, struct tw_tool* tools) { tools->add_version("Example/0.0"); return 0; } + +int mod_request(struct tw_tool* tools, struct tw_http_request* req, struct tw_http_response* res) { return TW_MODULE_ERROR(403); } diff --git a/Server/config.c b/Server/config.c index 1b21d73..4e1904b 100644 --- a/Server/config.c +++ b/Server/config.c @@ -11,6 +11,10 @@ #include #include +#ifdef __MINGW32__ +#include +#endif + #include #include diff --git a/Server/http.c b/Server/http.c index b630591..5c6b5f9 100644 --- a/Server/http.c +++ b/Server/http.c @@ -22,6 +22,7 @@ void tw_free_request(struct tw_http_request* req) { if(req->method != NULL) free(req->method); if(req->path != NULL) free(req->path); + if(req->query != NULL) free(req->query); if(req->headers != NULL) { int i; for(i = 0; req->headers[i] != NULL; i++) free(req->headers[i]); @@ -43,6 +44,7 @@ int tw_http_parse(SSL* ssl, int sock, struct tw_http_request* req) { req->method = NULL; req->path = NULL; + req->query = NULL; req->headers = NULL; req->body = NULL; req->version = NULL; @@ -245,5 +247,32 @@ getout: tw_free_request(req); return 1; } + char* result = malloc(1); + result[0] = 0; + int i; + for(i = 0; req->path[i] != 0; i++) { + if(req->path[i] == '?') { + req->path[i] = 0; + req->query = cm_strdup(req->path + i + 1); + break; + } + } + for(i = 0; req->path[i] != 0; i++) { + if(req->path[i] == '%') { + if(req->path[i + 1] == 0) continue; + cbuf[0] = cm_hex(req->path + i + 1, 2); + char* tmp = result; + result = cm_strcat(tmp, cbuf); + free(tmp); + i += 2; + } else { + cbuf[0] = req->path[i]; + char* tmp = result; + result = cm_strcat(tmp, cbuf); + free(tmp); + } + } + free(req->path); + req->path = result; return 0; } diff --git a/Server/main.c b/Server/main.c index c55a03a..5e5f663 100644 --- a/Server/main.c +++ b/Server/main.c @@ -55,7 +55,7 @@ int main(int argc, char** argv) { return 1; } sprintf(tw_server, "Tewi/%s (%s)%s", tw_get_version(), tw_get_platform(), config.extension == NULL ? "" : config.extension); - cm_log("Daemon", "Ready"); + cm_log("Daemon", "Ready, server: %s", tw_server); #ifndef __MINGW32__ signal(SIGCHLD, SIG_IGN); #endif diff --git a/Server/server.c b/Server/server.c index 199fe05..229c42b 100644 --- a/Server/server.c +++ b/Server/server.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -135,59 +136,14 @@ size_t tw_write(SSL* ssl, int s, void* data, size_t len) { } } -#define ERROR_400 \ +#define ERROR_HTML \ "\n" \ "\n" \ " \n" \ - " 400 Bad Request" \ + " %s\n" \ " \n" \ " \n" \ - "

Bad Request

\n" \ - "
\n" \ - " ", \ - address, \ - "\n" \ - " \n" \ - "\n" - -#define ERROR_401 \ - "\n" \ - "\n" \ - " \n" \ - " 401 Unauthorized" \ - " \n" \ - " \n" \ - "

Unauthorized

\n" \ - "
\n" \ - " ", \ - address, \ - "\n" \ - " \n" \ - "\n" - -#define ERROR_403 \ - "\n" \ - "\n" \ - " \n" \ - " 403 Forbidden" \ - " \n" \ - " \n" \ - "

Forbidden

\n" \ - "
\n" \ - " ", \ - address, \ - "\n" \ - " \n" \ - "\n" - -#define ERROR_404 \ - "\n" \ - "\n" \ - " \n" \ - " 404 Not Found" \ - " \n" \ - " \n" \ - "

Not Found

\n" \ + "

%s

\n" \ "
\n" \ " ", \ address, \ @@ -221,8 +177,16 @@ void tw_process_page(SSL* ssl, int sock, const char* status, const char* type, c } const char* tw_http_status(int code) { - if(code == 400) { + if(code == 200) { + return "200 OK"; + } else if(code == 400) { return "400 Bad Request"; + } else if(code == 401) { + return "401 Unauthorized"; + } else if(code == 403) { + return "403 Forbidden"; + } else if(code == 404) { + return "404 Not Found"; } else { return "400 Bad Request"; } @@ -231,11 +195,22 @@ const char* tw_http_status(int code) { char* tw_http_default_error(int code, char* name, int port) { char address[1024]; sprintf(address, "
%s Server at %s Port %d
", tw_server, name, port); - if(code == 400) { - return cm_strcat3(ERROR_400); - } else { - return cm_strcat3(ERROR_400); + + char* st = cm_strdup(tw_http_status(code)); + char* st2; + int i; + for(i = 0; st[i] != 0; i++) { + if(st[i] == ' ') { + st2 = cm_strdup(st + i + 1); + break; + } } + char* buffer = malloc(4096); + char* str = cm_strcat3(ERROR_HTML); + sprintf(buffer, str, st, st2); + free(str); + free(st); + return buffer; } void tw_http_error(SSL* ssl, int sock, int error, char* name, int port) { @@ -244,6 +219,47 @@ void tw_http_error(SSL* ssl, int sock, int error, char* name, int port) { free(str); } +void addstring(char** str, const char* add, ...) { + int i; + char cbuf[2]; + cbuf[1] = 0; + va_list va; + va_start(va, add); + for(i = 0; add[i] != 0; i++) { + cbuf[0] = add[i]; + if(add[i] == '%') { + i++; + if(add[i] == 's') { + char* tmp = *str; + *str = cm_strcat(tmp, va_arg(va, const char*)); + free(tmp); + } else if(add[i] == 'h') { + char* h = cm_html_escape(va_arg(va, const char*)); + char* tmp = *str; + *str = cm_strcat(tmp, h); + free(tmp); + free(h); + } else if(add[i] == 'd') { + int n = va_arg(va, int); + char* h = malloc(512); + sprintf(h, "%d", n); + char* tmp = *str; + *str = cm_strcat(tmp, h); + free(tmp); + free(h); + } else if(add[i] == '%') { + char* tmp = *str; + *str = cm_strcat(tmp, "%"); + free(tmp); + } + } else { + char* tmp = *str; + *str = cm_strcat(tmp, cbuf); + free(tmp); + } + } +} + #ifdef __MINGW32__ struct pass_entry { int sock; @@ -272,8 +288,54 @@ void tw_server_pass(int sock, bool ssl, int port) { sslworks = true; } struct tw_http_request req; + struct tw_http_response res; + struct tw_tool tools; + res._processed = false; + tw_init_tools(&tools); int ret = tw_http_parse(s, sock, &req); if(ret == 0) { + int i; + for(i = 0; i < config.module_count; i++) { + tw_mod_request_t mod_req = (tw_mod_request_t)tw_module_symbol(config.modules[i], "mod_request"); + if(mod_req != NULL) { + int ret = mod_req(&tools, &req, &res); + int co = ret & 0xff; + if(co == _TW_MODULE_PASS) continue; + if(co == _TW_MODULE_STOP) { + res._processed = true; + break; + } + if(co == _TW_MODULE_ERROR) { + tw_http_error(s, sock, (ret & 0xffff00) >> 8, name, port); + break; + } + } + } + if(!res._processed) { + char* str = malloc(1); + str[0] = 0; + addstring(&str, "\n"); + addstring(&str, "\n"); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, " Index of %h\n", req.path); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, "

Index of %h

\n", req.path); + addstring(&str, "
\n"); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, " \n"); + addstring(&str, "
Filename
\n"); + addstring(&str, "
\n"); + addstring(&str, "
%s Server at %s Port %d
\n", tw_server, name, port); + addstring(&str, " \n"); + addstring(&str, "\n"); + tw_process_page(s, sock, tw_http_status(200), "text/html", str, strlen(str)); + free(str); + } } else { tw_http_error(s, sock, 400, name, port); } diff --git a/Server/ssl.c b/Server/ssl.c index 5f4abcf..1892c94 100644 --- a/Server/ssl.c +++ b/Server/ssl.c @@ -28,6 +28,7 @@ int tw_ssl_cert_cb(SSL* ssl, void* arg) { } else if(config.root.sslkey != NULL && config.root.sslcert != NULL) { SSL_use_PrivateKey_file(ssl, config.root.sslkey, SSL_FILETYPE_PEM); SSL_use_certificate_file(ssl, config.root.sslcert, SSL_FILETYPE_PEM); + return 1; } else { return 0; } diff --git a/Server/tw_http.h b/Server/tw_http.h index 79c0377..6aa1f2b 100644 --- a/Server/tw_http.h +++ b/Server/tw_http.h @@ -3,9 +3,12 @@ #ifndef __TW_HTTP_H__ #define __TW_HTTP_H__ +#include + struct tw_http_request { char* method; char* path; + char* query; char* version; char** headers; char* body; @@ -13,6 +16,8 @@ struct tw_http_request { struct tw_http_response { char** headers; + int status; + bool _processed; /* Internal parameter */ }; #ifdef SOURCE diff --git a/Server/tw_module.h b/Server/tw_module.h index 8379703..df02072 100644 --- a/Server/tw_module.h +++ b/Server/tw_module.h @@ -12,11 +12,15 @@ struct tw_tool { }; enum TW_MODULE_RETURN { - TW_MODULE_PASS = 0, /* Pass to the next module. */ - TW_MODULE_STOP, /* Do not pass to the next module. */ - TW_MODULE_ERROR /* Error, and do not pass to the next module. */ + _TW_MODULE_PASS = 0, /* Pass to the next module. */ + _TW_MODULE_STOP, /* Do not pass to the next module. */ + _TW_MODULE_ERROR /* Error, and do not pass to the next module. */ }; +#define TW_MODULE_PASS _TW_MODULE_PASS +#define TW_MODULE_STOP _TW_MODULE_STOP +#define TW_MODULE_ERROR(x) (_TW_MODULE_ERROR | ((x) << 8)) + typedef int (*tw_mod_init_t)(struct tw_config* config, struct tw_tool* tools); typedef int (*tw_mod_request_t)(struct tw_tool* tools, struct tw_http_request* req, struct tw_http_response* res); diff --git a/example.conf b/example.conf index 7f9b2cc..1159bfc 100644 --- a/example.conf +++ b/example.conf @@ -1,7 +1,7 @@ # $Id$ # This is an example config -LoadModule /home/nishi/SVN/tewi/trunk/Module/mod_example.so +#LoadModule /home/nishi/SVN/tewi/trunk/Module/mod_example.so Listen 8000 8001 8002 8003 8004 ListenSSL 8443 8444 8445 8446 8447 -- 2.43.0