diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 121 |
1 files changed, 75 insertions, 46 deletions
@@ -13,7 +13,7 @@ #define PORT "8079" #define RM_LF(str) do { \ - signed long len = strlen(str)-1; \ + signed long len = strlen(str)-1; \ if(len >= 0 && str[len] == '\n') str[len] = '\0'; \ } while(0) @@ -35,58 +35,60 @@ SEND_BUF_ADD("\r\n"); \ } while(0) -#define LOAD_FILE() do { \ - if(is_binary) { \ - fseek(fp, 0, SEEK_END); \ - size_t file_sz = ftell(fp); \ - rewind(fp); \ - \ - fread(&send_buf[*send_buf_sz], sizeof(char), file_sz, fp); \ - *send_buf_sz += file_sz; \ - } else { \ - char line[BUF_CAP]; \ - while(fgets(line, sizeof(line), fp) != NULL) \ - { \ - RM_LF(line); \ - SEND_BUF_ADD_LINE(line); \ - } \ - } \ +#define SEND_BUF_ADD_LINE_LONG(lon) do { \ + char str[COMMON_CAP]; \ + sprintf(str, "%ld", lon); \ + SEND_BUF_ADD_LINE(str); \ } while(0) +#ifdef USE_LIBMAGIC +#include <magic.h> static int get_content_type(char *file_path, char *content_type) { - char cmd[COMMON_CAP + 64]; - sprintf(cmd, "/usr/bin/file -ib %s", file_path); + int ret = 1; + magic_t magic; - FILE *fp = popen(cmd, "r"); - if(!fp) { - err("popen: cmd %s: %s", cmd, strerror(errno)); - return 1; + if((magic = magic_open(MAGIC_MIME)) == NULL) { + err("magic_open: %s", magic_error(magic)); + return ret; } - if(fgets(content_type, COMMON_CAP, fp) == NULL) { - err("get_mime_type: no output from fgets"); - return 1; + if(magic_load(magic, NULL) != 0) { + err("magic_load: %s", magic_error(magic)); + goto close; } - pclose(fp); - RM_LF(content_type); - - char ct_cpy[COMMON_CAP]; - strcpy(ct_cpy, content_type); - strtok(ct_cpy, "="); - - // the only thing after the '=' should be the either binary or something else (text) - char *charset = strtok(NULL, "="); - if(charset == NULL || strcmp(charset, "binary") != 0) { - return 0; + const char *mime = magic_file(magic, file_path); + if(mime == NULL) { + err("magic_file: %s", magic_error(magic)); + goto close; } - return -1; + memcpy(content_type, mime, strlen(mime)); + + ret = 0; +close: + magic_close(magic); + return ret; +} +#else +static int get_content_type(char *file_path, char *content_type) +{ + (void)file_path; + (void)content_type; + return 0; } +#endif static int try_file(char *req_path, FILE **fp, char *content_type) { + for(size_t i = 1; i < strlen(req_path); i++) { + if(req_path[i-1] == '.' && req_path[i] == '.') { + err("try_file: the requested path %s includes ..", req_path); + return 1; + } + } + char file_path[COMMON_CAP]; sprintf(file_path, "%s%s", FILES, (strlen(req_path) == 1) ? "/index.html" : req_path); @@ -96,24 +98,31 @@ static int try_file(char *req_path, FILE **fp, char *content_type) err("fopen: file %s: %s", file_path, strerror(errno)); return 1; } + info("fopen: file %s was opened", file_path); - return get_content_type(file_path, content_type); + if(get_content_type(file_path, content_type) != 0) { + err("get_content_type: failed"); + fclose(*fp); + return 1; + } + + return 0; } static int on_get(char *send_buf, ssize_t *send_buf_sz, char *req_path) { - char content_type[COMMON_CAP]; - int is_binary; // 0 - no; -1 - yes; 1 - error + int ret = 1; + char content_type[COMMON_CAP] = {0}; FILE *fp; - if((is_binary = try_file(req_path, &fp, content_type)) == 1) { + if(try_file(req_path, &fp, content_type) != 0) { if(errno == 2) { // 2 is 'No such file or directory' SEND_BUF_ADD_LINE("404"); - if((is_binary = try_file("/404.html", &fp, content_type)) != 0) return 1; + if(try_file("/404.html", &fp, content_type) != 0) return ret; } else { SEND_BUF_ADD_LINE("500"); - if((is_binary = try_file("/500.html", &fp, content_type)) != 0) return 1; + if(try_file("/500.html", &fp, content_type) != 0) return ret; } } else { SEND_BUF_ADD_LINE("200"); @@ -122,11 +131,31 @@ static int on_get(char *send_buf, ssize_t *send_buf_sz, char *req_path) SEND_BUF_ADD_LINE("Server: potato"); SEND_BUF_ADD("Content-Type: "); SEND_BUF_ADD_LINE(content_type); + + if(fseek(fp, 0, SEEK_END) != 0) { + err("fseek: %s", strerror(errno)); + goto close; + } + + size_t file_sz = ftell(fp); + if(file_sz == 0) { + err("ftell: %s", strerror(errno)); + goto close; + } + + rewind(fp); + + SEND_BUF_ADD("Content-Lenght: "); + SEND_BUF_ADD_LINE_LONG(file_sz); SEND_BUF_ADD("\r\n"); - LOAD_FILE(); + fread(&send_buf[*send_buf_sz], sizeof(char), file_sz, fp); + *send_buf_sz += file_sz; + + ret = 0; +close: fclose(fp); - return 0; + return ret; } static int handle_connection(sock_t *conn) |