Changeset 21 in Main for trunk/Server


Ignore:
Timestamp:
Sep 14, 2024, 9:39:39 PM (2 months ago)
Author:
Nishi
Message:

can send file now

Location:
trunk/Server
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Server/config.c

    r20 r21  
    3131}
    3232
     33bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost){
     34        int i;
     35        bool found = false;
     36        bool pathstart = false;
     37        bool perm = false;
     38again:
     39        for(i = 0; i < vhost->dir_count; i++){
     40                struct tw_dir_entry* e = &vhost->dirs[i];
     41                pathstart = false;
     42                if(strlen(path) >= strlen(e->dir)){
     43                        pathstart = true;
     44                        int j;
     45                        for(j = 0; path[j] != 0 && e->dir[j] != 0; j++){
     46                                if(path[j] != e->dir[j]){
     47                                        pathstart = false;
     48                                        break;
     49                                }
     50                        }
     51                }
     52                char* noslash = cm_strdup(e->dir);
     53                noslash[strlen(noslash) - 1] = 0;
     54                if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart){
     55                        found = true;
     56                        if(strcmp(e->name, "all") == 0){
     57                                perm = e->type == TW_DIR_ALLOW;
     58                        }
     59                }
     60                free(noslash);
     61        }
     62        if(!found && vhost != &config.root){
     63                vhost = &config.root;
     64                goto again;
     65        }
     66        return perm;
     67}
     68
    3369void tw_config_init(void) {
    3470        int i;
     
    4480        config.root.sslcert = NULL;
    4581        config.root.root = NULL;
     82        config.root.mime_count = 0;
     83        config.root.dir_count = 0;
    4684        config.vhost_count = 0;
    4785        config.module_count = 0;
     
    63101                struct tw_config_entry* current = &config.root;
    64102                char* vhost = NULL;
     103                char* dir = NULL;
    65104                while(stop == 0) {
    66105                        int c = fread(cbuf, 1, 1, f);
     
    78117                                                        }
    79118                                                }
     119                                        } else if(cm_strcaseequ(r[0], "BeginDirectory")) {
     120                                                if(dir != NULL) {
     121                                                        cm_log("Config", "Already in directory section at line %d", ln);
     122                                                        stop = 1;
     123                                                } else {
     124                                                        if(r[1] == NULL) {
     125                                                                cm_log("Config", "Missing directory at line %d", ln);
     126                                                                stop = 1;
     127                                                        } else {
     128                                                                dir = cm_strcat(r[1], r[1][strlen(r[1]) - 1] == '/' ? "" : "/");
     129                                                        }
     130                                                }
     131                                        } else if(cm_strcaseequ(r[0], "EndDirectory")) {
     132                                                if(dir == NULL) {
     133                                                        cm_log("Config", "Not in directory section at line %d", ln);
     134                                                        stop = 1;
     135                                                } else {
     136                                                        free(dir);
     137                                                        dir = NULL;
     138                                                }
     139                                        } else if(cm_strcaseequ(r[0], "Allow")) {
     140                                                if(dir == NULL) {
     141                                                        cm_log("Config", "Not in directory section at line %d", ln);
     142                                                        stop = 1;
     143                                                } else {
     144                                                        if(r[1] == NULL) {
     145                                                                cm_log("Config", "Missing argument at line %d", ln);
     146                                                                stop = 1;
     147                                                        } else {
     148                                                                struct tw_dir_entry* e = &current->dirs[current->dir_count++];
     149                                                                e->name = cm_strdup(r[1]);
     150                                                                e->dir = cm_strdup(dir);
     151                                                                e->type = TW_DIR_ALLOW;
     152                                                        }
     153                                                }
     154                                        } else if(cm_strcaseequ(r[0], "Deny")) {
     155                                                if(dir == NULL) {
     156                                                        cm_log("Config", "Not in directory section at line %d", ln);
     157                                                        stop = 1;
     158                                                } else {
     159                                                        if(r[1] == NULL) {
     160                                                                cm_log("Config", "Missing argument at line %d", ln);
     161                                                                stop = 1;
     162                                                        } else {
     163                                                                struct tw_dir_entry* e = &current->dirs[current->dir_count++];
     164                                                                e->name = cm_strdup(r[1]);
     165                                                                e->dir = cm_strdup(dir);
     166                                                                e->type = TW_DIR_DENY;
     167                                                        }
     168                                                }
    80169                                        } else if(cm_strcaseequ(r[0], "BeginVirtualHost")) {
    81170                                                if(vhost != NULL) {
     
    89178                                                                vhost = cm_strdup(r[1]);
    90179                                                                current = &config.vhosts[config.vhost_count++];
     180                                                                current->dir_count = 0;
     181                                                                current->mime_count = 0;
    91182                                                                int i;
    92183                                                                current->name = cm_strdup(vhost);
     
    142233                                                } else {
    143234                                                        if(current->root != NULL) free(current->root);
    144                                                         current->root = cm_strdup(r[1]);
     235                                                        current->root = cm_strdup(strcmp(r[1], "/") == 0 ? "" : r[1]);
    145236                                                }
    146237                                        } else if(cm_strcaseequ(r[0], "ServerRoot")) {
     
    151242                                                        if(config.server_root != NULL) free(config.server_root);
    152243                                                        config.server_root = cm_strdup(r[1]);
     244                                                }
     245                                        } else if(cm_strcaseequ(r[0], "MIMEType")) {
     246                                                if(r[1] == NULL) {
     247                                                        cm_log("Config", "Missing extension at line %d", ln);
     248                                                        stop = 1;
     249                                                }else if(r[2] == NULL) {
     250                                                        cm_log("Config", "Missing MIME at line %d", ln);
     251                                                        stop = 1;
     252                                                } else {
     253                                                        struct tw_mime_entry* e = &current->mimes[current->mime_count++];
     254                                                        e->ext = cm_strdup(r[1]);
     255                                                        e->mime = cm_strdup(r[2]);
    153256                                                }
    154257                                        } else if(cm_strcaseequ(r[0], "LoadModule")) {
  • trunk/Server/server.c

    r20 r21  
    1515#include <stdbool.h>
    1616#include <stdarg.h>
     17#include <sys/stat.h>
    1718
    1819#include <cm_string.h>
    1920#include <cm_log.h>
     21#include <cm_dir.h>
    2022
    2123#ifdef __MINGW32__
    2224#include <winsock2.h>
    2325#include <process.h>
    24 #define NO_IPV6
    2526#else
    2627#include <sys/select.h>
     
    3738int sockcount = 0;
    3839
    39 #ifdef NO_IPV6
    40 #define SOCKADDR struct sockaddr_in
    41 #else
    42 #define SOCKADDR struct sockaddr_in6
    43 #endif
    4440SOCKADDR addresses[MAX_PORTS];
    4541int sockets[MAX_PORTS];
     
    152148            "</html>\n"
    153149
    154 void tw_process_page(SSL* ssl, int sock, const char* status, const char* type, const unsigned char* doc, size_t size) {
     150void tw_process_page(SSL* ssl, int sock, const char* status, const char* type, FILE* f, const unsigned char* doc, size_t size) {
    155151        char construct[512];
    156152        sprintf(construct, "%llu", (unsigned long long)size);
     
    170166        size_t incr = 0;
    171167        while(1) {
    172                 tw_write(ssl, sock, (unsigned char*)doc + incr, size < 128 ? size : 128);
     168                if(f != NULL){
     169                        char buffer[128];
     170                        fread(buffer, size < 128 ? size : 128, 1, f);
     171                        tw_write(ssl, sock, buffer, size < 128 ? size : 128);
     172                }else{
     173                        tw_write(ssl, sock, (unsigned char*)doc + incr, size < 128 ? size : 128);
     174                }
    173175                incr += 128;
    174176                if(size <= 128) break;
     
    216218void tw_http_error(SSL* ssl, int sock, int error, char* name, int port) {
    217219        char* str = tw_http_default_error(error, name, port);
    218         tw_process_page(ssl, sock, tw_http_status(error), "text/html", str, strlen(str));
     220        tw_process_page(ssl, sock, tw_http_status(error), "text/html", NULL, str, strlen(str));
    219221        free(str);
    220222}
     
    240242                                free(tmp);
    241243                                free(h);
     244                        } else if(add[i] == 'l') {
     245                                char* h = cm_url_escape(va_arg(va, const char*));
     246                                char* tmp = *str;
     247                                *str = cm_strcat(tmp, h);
     248                                free(tmp);
     249                                free(h);
    242250                        } else if(add[i] == 'd') {
    243251                                int n = va_arg(va, int);
     
    266274        int port;
    267275        bool ssl;
     276        SOCKADDR addr;
    268277};
    269278
     
    272281        bool ssl = ((struct pass_entry*)ptr)->ssl;
    273282        int port = ((struct pass_entry*)ptr)->port;
     283        SOCKADDR addr = ((struct pass_entry*)ptr)->addr;
    274284        free(ptr);
    275285#else
    276 void tw_server_pass(int sock, bool ssl, int port) {
     286void tw_server_pass(int sock, bool ssl, int port, SOCKADDR addr) {
    277287#endif
    278288        char* name = config.hostname;
     
    295305        int ret = tw_http_parse(s, sock, &req);
    296306        if(ret == 0) {
     307                char* vhost = cm_strdup(config.hostname);
    297308                int i;
     309                for(i = 0; req.headers[i] != NULL; i += 2){
     310                        if(cm_strcaseequ(req.headers[i], "Host")){
     311                                free(vhost);
     312                                vhost = req.headers[i + 1];
     313                                break;
     314                        }
     315                }
     316                cm_log("Server", "Host is %s", vhost);
     317                int port = s == NULL ? 80 : 443;
     318                char* host = cm_strdup(vhost);
     319                for(i = 0; vhost[i] != 0; i++){
     320                        if(vhost[i] == ':'){
     321                                host[i] = 0;
     322                                port = atoi(host + i + 1);
     323                                break;
     324                        }
     325                }
     326                cm_log("Server", "Hostname is `%s', port is `%d'", host, port);
     327                struct tw_config_entry* vhost_entry = tw_vhost_match(host, port);
    298328                for(i = 0; i < config.module_count; i++) {
    299329                        tw_mod_request_t mod_req = (tw_mod_request_t)tw_module_symbol(config.modules[i], "mod_request");
     
    313343                }
    314344                if(!res._processed) {
    315                         char* str = malloc(1);
    316                         str[0] = 0;
    317                         addstring(&str, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
    318                         addstring(&str, "<html>\n");
    319                         addstring(&str, "       <head>\n");
    320                         addstring(&str, "               <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
    321                         addstring(&str, "               <title>Index of %h</title>\n", req.path);
    322                         addstring(&str, "       </head>\n");
    323                         addstring(&str, "       <body>\n");
    324                         addstring(&str, "               <h1>Index of %h</h1>\n", req.path);
    325                         addstring(&str, "               <hr>\n");
    326                         addstring(&str, "               <table border=\"0\">\n");
    327                         addstring(&str, "                       <tr>\n");
    328                         addstring(&str, "                               <th></th>\n");
    329                         addstring(&str, "                               <th>Filename</th>\n");
    330                         addstring(&str, "                       </tr>\n");
    331                         addstring(&str, "               </table>\n");
    332                         addstring(&str, "               <hr>\n");
    333                         addstring(&str, "               <address>%s Server at %s Port %d</address>\n", tw_server, name, port);
    334                         addstring(&str, "       </body>\n");
    335                         addstring(&str, "</html>\n");
    336                         tw_process_page(s, sock, tw_http_status(200), "text/html", str, strlen(str));
    337                         free(str);
    338                 }
     345                        cm_log("Server", "Document root is %s", vhost_entry->root == NULL ? "not set" : vhost_entry->root);
     346                        char* path = cm_strcat(vhost_entry->root == NULL ? "" : vhost_entry->root, req.path);
     347                        cm_log("Server", "Filesystem path is %s", path);
     348                        struct stat st;
     349                        if(stat(path, &st) == 0){
     350                                if(!tw_permission_allowed(path, addr, req, vhost_entry)){
     351                                        tw_http_error(s, sock, 403, name, port);
     352                                }else if(S_ISDIR(st.st_mode)){
     353                                        char* str = malloc(1);
     354                                        str[0] = 0;
     355                                        char** items = cm_scandir(path);
     356                                        addstring(&str, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
     357                                        addstring(&str, "<html>\n");
     358                                        addstring(&str, "       <head>\n");
     359                                        addstring(&str, "               <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
     360                                        addstring(&str, "               <title>Index of %h</title>\n", req.path);
     361                                        addstring(&str, "       </head>\n");
     362                                        addstring(&str, "       <body>\n");
     363                                        addstring(&str, "               <h1>Index of %h</h1>\n", req.path);
     364                                        addstring(&str, "               <hr>\n");
     365                                        addstring(&str, "               <table border=\"0\">\n");
     366                                        addstring(&str, "                       <tr>\n");
     367                                        addstring(&str, "                               <th></th>\n");
     368                                        addstring(&str, "                               <th>Filename</th>\n");
     369                                        addstring(&str, "                       </tr>\n");
     370                                        if(items != NULL){
     371                                                for(i = 0; items[i] != NULL; i++){
     372                                                        addstring(&str, "<tr>\n");
     373                                                        addstring(&str, "       <td></td>\n");
     374                                                        addstring(&str, "       <td><a href=\"%l\">%h</a></td>\n", items[i], items[i]);
     375                                                        addstring(&str, "</tr>\n");
     376                                                }
     377                                        }
     378                                        addstring(&str, "               </table>\n");
     379                                        addstring(&str, "               <hr>\n");
     380                                        addstring(&str, "               <address>%s Server at %s Port %d</address>\n", tw_server, name, port);
     381                                        addstring(&str, "       </body>\n");
     382                                        addstring(&str, "</html>\n");
     383                                        tw_process_page(s, sock, tw_http_status(200), "text/html", NULL, str, strlen(str));
     384                                        free(str);
     385                                }else{
     386                                        char* mime = "application/octet-stream";
     387                                        bool set = false;
     388                                        char* ext = NULL;
     389                                        for(i = strlen(req.path) - 1; i >= 0; i--){
     390                                                if(req.path[i] == '.'){
     391                                                        ext = cm_strdup(req.path + i);
     392                                                        break;
     393                                                }
     394                                        }
     395                                        for(i = 0; i < vhost_entry->mime_count; i++){
     396                                                if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(vhost_entry->mimes[i].ext, ext) == 0)){
     397                                                        mime = vhost_entry->mimes[i].mime;
     398                                                        set = true;
     399                                                }
     400                                        }
     401                                        if(!set){
     402                                                for(i = 0; i < config.root.mime_count; i++){
     403                                                        if(strcmp(config.root.mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(config.root.mimes[i].ext, ext) == 0)){
     404                                                                mime = config.root.mimes[i].mime;
     405                                                                set = true;
     406                                                        }
     407                                                }
     408                                        }
     409                                        if(ext != NULL) free(ext);
     410                                        FILE* f = fopen(path, "rb");
     411                                        tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size);
     412                                        fclose(f);
     413                                }
     414                        }else{
     415                                tw_http_error(s, sock, 404, name, port);
     416                        }
     417                        free(path);
     418                }
     419                free(vhost);
     420                free(host);
    339421        } else {
    340422                tw_http_error(s, sock, 400, name, port);
     
    379461                                        e->ssl = config.ports[i] & (1ULL << 32);
    380462                                        e->port = config.ports[i];
     463                                        e->addr = claddr;
    381464                                        thread = (HANDLE)_beginthreadex(NULL, 0, tw_server_pass, e, 0, NULL);
    382465#else
    383466                                        pid_t pid = fork();
    384467                                        if(pid == 0) {
    385                                                 tw_server_pass(sock, config.ports[i] & (1ULL << 32), config.ports[i]);
     468                                                tw_server_pass(sock, config.ports[i] & (1ULL << 32), config.ports[i], claddr);
    386469                                                _exit(0);
    387470                                        } else {
  • trunk/Server/tw_config.h

    r19 r21  
    44#define __TW_CONFIG_H__
    55
     6#include "tw_http.h"
     7
    68#include <stdint.h>
     9#include <stdbool.h>
    710
    8 #define MAX_PORTS 1024
    9 #define MAX_VHOSTS 1024
    10 #define MAX_MODULES 1024
     11#ifdef __MINGW32__
     12#include <winsock2.h>
     13#define NO_IPV6
     14#else
     15#include <netinet/in.h>
     16#endif
     17
     18#ifdef NO_IPV6
     19#define SOCKADDR struct sockaddr_in
     20#else
     21#define SOCKADDR struct sockaddr_in6
     22#endif
     23
     24#define MAX_PORTS       1024
     25#define MAX_VHOSTS      1024
     26#define MAX_MODULES     1024
     27#define MAX_DIRS        1024
     28#define MAX_MIME        1024
     29
     30enum TW_DIR_TYPE {
     31        TW_DIR_ALLOW = 0,
     32        TW_DIR_DENY
     33};
     34
     35struct tw_dir_entry {
     36        char* name;
     37        char* dir;
     38        int type;
     39};
     40
     41struct tw_mime_entry {
     42        char* ext;
     43        char* mime;
     44};
    1145
    1246struct tw_config_entry {
     
    1650        char* sslcert;
    1751        char* root;
     52        struct tw_dir_entry dirs[MAX_DIRS];
     53        int dir_count;
     54        struct tw_mime_entry mimes[MAX_DIRS];
     55        int mime_count;
    1856};
    1957
     
    3371int tw_config_read(const char* path);
    3472struct tw_config_entry* tw_vhost_match(const char* name, int port);
     73bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost);
    3574
    3675#endif
Note: See TracChangeset for help on using the changeset viewer.