]> Git repositories of Nishi - tewi.git/commitdiff
can show index
authorNishi <nishi@nishi.boats>
Sat, 14 Sep 2024 09:59:15 +0000 (09:59 +0000)
committerNishi <nishi@nishi.boats>
Sat, 14 Sep 2024 09:59:15 +0000 (09:59 +0000)
git-svn-id: file:///raid/svn-personal/tewi/trunk@20 8739d7e6-ffea-ec47-b151-bdff447c6205

Common/cm_string.h
Common/string.c
Module/mod_example.c
Server/config.c
Server/http.c
Server/main.c
Server/server.c
Server/ssl.c
Server/tw_http.h
Server/tw_module.h
example.conf

index 476e297c2c4e17b336b2ef7e49dcfabd6476a517..9adf0a14f75021120751f574f9720aa708027fa9 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <stdbool.h>
 
+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);
index f858d7704076a034ab08d56c8710862e73d169a6..c894d3ffebe64504aebc64289eb002a28f4e19a1 100644 (file)
@@ -3,6 +3,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <ctype.h>
 
 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, "&amp;");
+                       free(tmp);
+               } else if(str[i] == '<') {
+                       char* tmp = result;
+                       result = cm_strcat(tmp, "&lt;");
+                       free(tmp);
+               } else if(str[i] == '>') {
+                       char* tmp = result;
+                       result = cm_strcat(tmp, "&gt;");
+                       free(tmp);
+               } else {
+                       char* tmp = result;
+                       result = cm_strcat(tmp, cbuf);
+                       free(tmp);
+               }
+       }
+       return result;
+}
index a26569f5a4dc488c55ae8d9877c42565a374ff6d..fb223736b576ee932d2a070bce038ee9295e9e54 100644 (file)
@@ -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); }
index 1b21d737eaa9b6a4e145611915f0cbb8f260a776..4e1904beeedbd304323d40b27423619b274f1fb3 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#ifdef __MINGW32__
+#include <winsock2.h>
+#endif
+
 #include <cm_string.h>
 #include <cm_log.h>
 
index b63059109ca6a8f05b1e0fd07504c5351c5b7a5c..5c6b5f9fa8ea9ef1b1e3211361c03cbd18f3a5f5 100644 (file)
@@ -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;
 }
index c55a03adcbb78e2f488b0c2f108688706bb86963..5e5f663cf172c581b037f36f3c684a5d41e7d98a 100644 (file)
@@ -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
index 199fe052c41c1edded116d24ab7b32a805d45f83..229c42b338113ea8a975e68f9eaafa9302f033df 100644 (file)
@@ -13,6 +13,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdbool.h>
+#include <stdarg.h>
 
 #include <cm_string.h>
 #include <cm_log.h>
@@ -135,59 +136,14 @@ size_t tw_write(SSL* ssl, int s, void* data, size_t len) {
        }
 }
 
-#define ERROR_400 \
+#define ERROR_HTML \
        "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" \
        "<html>\n" \
        "       <head>\n" \
-       "               <title>400 Bad Request</title>" \
+       "               <title>%s</title>\n" \
        "       </head>\n" \
        "       <body>\n" \
-       "               <h1>Bad Request</h1>\n" \
-       "               <hr>\n" \
-       "               ", \
-           address, \
-           "\n" \
-           "   </body>\n" \
-           "</html>\n"
-
-#define ERROR_401 \
-       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" \
-       "<html>\n" \
-       "       <head>\n" \
-       "               <title>401 Unauthorized</title>" \
-       "       </head>\n" \
-       "       <body>\n" \
-       "               <h1>Unauthorized</h1>\n" \
-       "               <hr>\n" \
-       "               ", \
-           address, \
-           "\n" \
-           "   </body>\n" \
-           "</html>\n"
-
-#define ERROR_403 \
-       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" \
-       "<html>\n" \
-       "       <head>\n" \
-       "               <title>403 Forbidden</title>" \
-       "       </head>\n" \
-       "       <body>\n" \
-       "               <h1>Forbidden</h1>\n" \
-       "               <hr>\n" \
-       "               ", \
-           address, \
-           "\n" \
-           "   </body>\n" \
-           "</html>\n"
-
-#define ERROR_404 \
-       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" \
-       "<html>\n" \
-       "       <head>\n" \
-       "               <title>404 Not Found</title>" \
-       "       </head>\n" \
-       "       <body>\n" \
-       "               <h1>Not Found</h1>\n" \
+       "               <h1>%s</h1>\n" \
        "               <hr>\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, "<address>%s Server at %s Port %d</address>", 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, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
+                       addstring(&str, "<html>\n");
+                       addstring(&str, "       <head>\n");
+                       addstring(&str, "               <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
+                       addstring(&str, "               <title>Index of %h</title>\n", req.path);
+                       addstring(&str, "       </head>\n");
+                       addstring(&str, "       <body>\n");
+                       addstring(&str, "               <h1>Index of %h</h1>\n", req.path);
+                       addstring(&str, "               <hr>\n");
+                       addstring(&str, "               <table border=\"0\">\n");
+                       addstring(&str, "                       <tr>\n");
+                       addstring(&str, "                               <th></th>\n");
+                       addstring(&str, "                               <th>Filename</th>\n");
+                       addstring(&str, "                       </tr>\n");
+                       addstring(&str, "               </table>\n");
+                       addstring(&str, "               <hr>\n");
+                       addstring(&str, "               <address>%s Server at %s Port %d</address>\n", tw_server, name, port);
+                       addstring(&str, "       </body>\n");
+                       addstring(&str, "</html>\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);
        }
index 5f4abcf9fcdd7b891eb4ac0295057edd9c7b61ef..1892c940a5541c8c1bd26a6920e87ecd77cf1276 100644 (file)
@@ -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;
        }
index 79c03779fffb1231a247f2f3fe867e6461175eba..6aa1f2b49cbd5ad612c57db06d9beef62ce8927e 100644 (file)
@@ -3,9 +3,12 @@
 #ifndef __TW_HTTP_H__
 #define __TW_HTTP_H__
 
+#include <stdbool.h>
+
 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
index 8379703bdcb9fb89b01653c14c60b4998bc4ad1f..df02072915c1ccf2365b95acf59aa3cdba4e692a 100644 (file)
@@ -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);
 
index 7f9b2ccf3234f72c78db781ff2f55b736e45f4c0..1159bfce3746d36d05fd82a81f7a922d2d16e734 100644 (file)
@@ -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