diff --git a/.gitignore b/.gitignore index 08d8ba5..0a16d2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -bin/ -obj/ tmp/ +build/ .vscode/ \ No newline at end of file diff --git a/Makefile b/Makefile index 5ff6e30..04f37c3 100644 --- a/Makefile +++ b/Makefile @@ -1,32 +1,29 @@ -CPPFLAGS := -Iinclude -MMD -MP -CFLAGS := -Wall -LDFLAGS := -Llib -LDLIBS := -lm +TARGET_EXEC ?= server -SRC_DIR := src -OBJ_DIR := obj -BIN_DIR := bin +BUILD_DIR ?= ./build +SRC_DIRS ?= ./src -EXE := $(BIN_DIR)/server +SRCS := $(shell find $(SRC_DIRS) -name *.c) +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +DEPS := $(OBJS:.o=.d) -SRC := $(wildcard $(SRC_DIR)/*.c) +INC_DIRS := $(shell find $(SRC_DIRS) -type d) +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) -OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) +CPPFLAGS ?= $(INC_FLAGS) -MMD -MP -all: $(EXE) +$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) + $(CC) $(OBJS) -o $@ $(LDFLAGS) -$(EXE): $(OBJ) | $(BIN_DIR) - $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ - -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) +$(BUILD_DIR)/%.c.o: %.c + $(MKDIR_P) $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ -$(BIN_DIR) $(OBJ_DIR): - mkdir -p $@ +.PHONY: clean -clean: - @$(RM) -rv $(BIN_DIR) $(OBJ_DIR) +clean: + $(RM) -r $(BUILD_DIR) --include $(OBJ:.o=.d) +-include $(DEPS) -.PHONY: all, clean \ No newline at end of file +MKDIR_P ?= mkdir -p diff --git a/include/db_op/blogpost.h b/include/db_op/blogpost.h new file mode 100644 index 0000000..16a4ba1 --- /dev/null +++ b/include/db_op/blogpost.h @@ -0,0 +1,11 @@ +#include +#include + +typedef struct +{ + char *header; + char *content; + char **tags; + char *author; + unsigned int key; +} blogpost_t; \ No newline at end of file diff --git a/include/db_op/db.h b/include/db_op/db.h new file mode 100644 index 0000000..7a31292 --- /dev/null +++ b/include/db_op/db.h @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include +#include + +#include "./blogpost.h" + +#define LINE_SIZE 512 + +int open_db(char *file_name, char *type, FILE **file, char ***head, int *head_length); +int open_table(char *file_name, FILE **file); +int read_head(FILE *file, char ***head); +int get_entry(FILE *file, void **rec, int type, int n, int (*process_line)(char *, void **, int)); +int append_table(FILE *file, void *rec, int type, char *(*process_line)(void *, int)); +int remove_entry(FILE *file, int n); diff --git a/include/file.h b/include/file_op/file.h similarity index 59% rename from include/file.h rename to include/file_op/file.h index 178358a..066c88f 100644 --- a/include/file.h +++ b/include/file_op/file.h @@ -1,3 +1,10 @@ +#include +#include +#include +#include +#include +#include + struct file_s { char *path; diff --git a/include/mime.h b/include/file_op/mime.h similarity index 63% rename from include/mime.h rename to include/file_op/mime.h index aec5cf4..c7dd251 100644 --- a/include/mime.h +++ b/include/file_op/mime.h @@ -1 +1,3 @@ +#include + char *get_mime_type(char *file_path); \ No newline at end of file diff --git a/include/netw.h b/include/netw.h deleted file mode 100644 index 8896080..0000000 --- a/include/netw.h +++ /dev/null @@ -1,2 +0,0 @@ -int get_listener_socket(char *port); -void *get_in_addr(struct sockaddr *sa); \ No newline at end of file diff --git a/include/netw_op/netw.h b/include/netw_op/netw.h new file mode 100644 index 0000000..70645a9 --- /dev/null +++ b/include/netw_op/netw.h @@ -0,0 +1,8 @@ +#include +#include +#include +#include +#include + +int get_listener_socket(char *port); +void *get_in_addr(struct sockaddr *sa); \ No newline at end of file diff --git a/include/request.h b/include/netw_op/request.h similarity index 64% rename from include/request.h rename to include/netw_op/request.h index 9c7edbb..4f07f0e 100644 --- a/include/request.h +++ b/include/netw_op/request.h @@ -1,3 +1,13 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + struct header_s { char * str; size_t size; diff --git a/include/utils_op/arr.h b/include/utils_op/arr.h new file mode 100644 index 0000000..1f27af0 --- /dev/null +++ b/include/utils_op/arr.h @@ -0,0 +1,5 @@ +#include +#include + +void insert_to_arr(char ***arr, size_t length, char *value); +void free_arr(char **arr, int length); \ No newline at end of file diff --git a/include/utils_op/llist.h b/include/utils_op/llist.h new file mode 100644 index 0000000..e69de29 diff --git a/include/utils.h b/include/utils_op/utils.h similarity index 63% rename from include/utils.h rename to include/utils_op/utils.h index 04566f5..d89f556 100644 --- a/include/utils.h +++ b/include/utils_op/utils.h @@ -1,3 +1,8 @@ +#include +#include +#include +#include + void err_msg(char *msg); char *add_to_front(char **str1, char *str2); char *get_status_message(int status_code); diff --git a/src/db_op/blogpost.c b/src/db_op/blogpost.c new file mode 100644 index 0000000..009ecb2 --- /dev/null +++ b/src/db_op/blogpost.c @@ -0,0 +1 @@ +#include "../../include/db_op/blogpost.h" diff --git a/src/db_op/db.c b/src/db_op/db.c new file mode 100644 index 0000000..ec24d14 --- /dev/null +++ b/src/db_op/db.c @@ -0,0 +1,233 @@ +#include "../../include/db_op/db.h" +#include "../../include/utils_op/utils.h" +#include "../../include/utils_op/arr.h" + +/** + * @brief Opens a table of specified type. If no such table, creates one and returns 1 + * + * @param file_name + * @param type + * @param file + * @param head + * @param head_length + * @return int + */ +int open_db(char *file_name, char *type, FILE **file, char ***head, int *head_length) +{ + FILE *root_file; + if ((root_file = fopen(file_name, "a+")) == NULL) + { + err_msg("can't open database file"); + return -1; + } + + char *buff = NULL; + size_t size = LINE_SIZE; + + while (getline(&buff, &size, root_file) >= 0) + { + if (strcmp(type, strtok(buff, " ")) == 0) + { + int ret = open_table(strtok(NULL, "\n"), file); + + *head_length = read_head(*file, head); + + fclose(root_file); + + return ret; + } + } + + struct stat st = {0}; + if (stat("./db", &st) == -1) + { + mkdir("./db", 0700); + } + + int table_file_name_size = snprintf(NULL, 0, "./db/%s.csv", type) + 1; + char *table_file_name = malloc(table_file_name_size); + snprintf(table_file_name, table_file_name_size, "./db/%s.csv", type); + + fseek(root_file, 0, SEEK_SET); + fprintf(root_file, "%s %s\n", type, table_file_name); + + fclose(root_file); + + int ret = open_table(table_file_name, file); + + free(table_file_name); + + return 1; +} + +/** + * @brief Open table file + * + * @param file_name + * @param file + * @return int -1 if couldn't open file + */ +int open_table(char *file_name, FILE **file) +{ + if ((*file = fopen(file_name, "a+")) == NULL) + { + err_msg("can't open table file"); + return -1; + } + + return 0; +} + +/** + * @brief Read table head + * + * @param file + * @param head + * @return int + */ +int read_head(FILE *file, char ***head) +{ + fseek(file, 0, SEEK_SET); + + int length = 0; + *head = malloc(length * sizeof(char *)); + + char buff[LINE_SIZE]; + fscanf(file, "%[^\n]", buff); + + char *tok; + int i = 0; + for (tok = strtok(buff, ";"); tok && *tok; tok = strtok(NULL, ";")) + { + insert_to_arr(head, length++, tok); + } + + return length; +} + +/** + * @brief Get the entry on line n + * + * @param file + * @param rec + * @param type + * @param n + * @param process_line + * @return int + */ +int get_entry(FILE *file, void **rec, int type, int n, int (*process_line)(char *, void **, int)) +{ + char *buff = NULL; + int i = 0; + size_t size = LINE_SIZE; + + fseek(file, 0, SEEK_SET); + + while (getline(&buff, &size, file) >= 0) + { + if (i == n) + { + int res = (*process_line)(buff, rec, type); + return res; + } + else + i++; + } + + return -1; +} + +/** + * @brief Insert entry to the end of table + * + * @param file + * @param rec + * @param type + * @param process_line + * @return int + */ +int append_table(FILE *file, void *rec, int type, char *(*process_line)(void *, int)) +{ + fseek(file, 0, SEEK_END); + char *buff = (*process_line)(rec, type); + + if (fprintf(file, "%s", buff) < 0) + return -1; + + free(buff); + return 0; +} + +/** + * @brief Remove entry located at line n + * + * @param file + * @param n + * @return int + */ +int remove_entry(FILE *file, int n) +{ + if (n == 0) + { + err_msg("you shouldn't remove table head. Aborting"); + return -1; + } + + int tmp_file_name_length = snprintf(NULL, 0, "./db/tmp%d.csv", n) + 1; + char *tmp_file_name = malloc(tmp_file_name_length); + snprintf(tmp_file_name, tmp_file_name_length, "./db/tmp%d.csv", n); + + FILE *tmp_file = fopen(tmp_file_name, "w"); + + char *buff = NULL; + size_t size = LINE_SIZE; + + int i = 0; + + fseek(file, 0, SEEK_SET); + + while (getline(&buff, &size, file) >= 0) + { + if (i != n) + { + fprintf(tmp_file, "%s", buff); + } + i++; + } + + fclose(tmp_file); + free(buff); + + int fd = fileno(file); + char file_path[1024]; + + int path_length = snprintf(NULL, 0, "/proc/self/fd/%d", fd) + 1; + char *path = malloc(path_length); + snprintf(path, path_length, "/proc/self/fd/%d", fd); + + memset(file_path, 0, sizeof(file_path)); + ssize_t l = readlink(path, file_path, sizeof(file_path) - 1); + free(path); + + if (l < 0) + { + err_msg("couldn't get table path"); + return -1; + } + file_path[l] = '\0'; + + if (remove(file_path) != 0) + { + err_msg("couldn't remove original file"); + return -1; + } + + if (rename(tmp_file_name, file_path) != 0) + { + err_msg("couldn't rename tmp file"); + return -1; + } + free(tmp_file_name); + + return i; +} \ No newline at end of file diff --git a/src/file.c b/src/file_op/file.c similarity index 72% rename from src/file.c rename to src/file_op/file.c index 032eab9..61812c8 100644 --- a/src/file.c +++ b/src/file_op/file.c @@ -1,12 +1,5 @@ -#include -#include -#include -#include -#include -#include - -#include "../include/file.h" -#include "../include/utils.h" +#include "../../include/file_op/file.h" +#include "../../include/utils_op/utils.h" /** * @brief Generate file path from request path provided @@ -16,22 +9,22 @@ */ char *gen_file_path(char *req_path) { - char *path = (char *)malloc(sizeof req_path); + char *path = (char *)malloc(strlen(req_path) + 1); strcpy(path, req_path); if (strchr(req_path, '.') == NULL) { if (req_path[strlen(req_path) - 1] != '/') { - path = realloc(path, sizeof path + 1); + path = realloc(path, strlen(path) + 1); path = strcat(path, "/"); } - path = realloc(path, sizeof path + sizeof "index.html"); + path = realloc(path, strlen(path) + strlen("index.html") + 1); path = strcat(path, "index.html"); } char *webroot = "static"; - path = realloc(path, sizeof path + sizeof webroot); + path = realloc(path, strlen(path) + strlen(webroot)); path = add_to_front(&path, webroot); return path; @@ -47,7 +40,7 @@ char *gen_file_path(char *req_path) int send_file(int cli_fd, struct file_s *file) { off_t offset = 0; - if (sendfile(cli_fd, file->fd, &offset, file->size+2) < 0) + if (sendfile(cli_fd, file->fd, &offset, file->size + 2) < 0) { return -1; } diff --git a/src/mime.c b/src/file_op/mime.c similarity index 92% rename from src/mime.c rename to src/file_op/mime.c index e8c5923..5ce87f3 100644 --- a/src/mime.c +++ b/src/file_op/mime.c @@ -1,7 +1,5 @@ -#include - -#include "../include/mime.h" -#include "../include/utils.h" +#include "../../include/file_op/mime.h" +#include "../../include/utils_op/utils.h" #define DEFAULT_mime_TYPE "application/octet-stream" @@ -62,4 +60,4 @@ char *get_mime_type(char *file_path) } return DEFAULT_mime_TYPE; -} \ No newline at end of file +} diff --git a/src/netw.c b/src/netw_op/netw.c similarity index 91% rename from src/netw.c rename to src/netw_op/netw.c index 479e029..00d8d35 100644 --- a/src/netw.c +++ b/src/netw_op/netw.c @@ -1,11 +1,5 @@ -#include -#include -#include -#include -#include - -#include "../include/netw.h" -#include "../include/utils.h" +#include "../../include/netw_op/netw.h" +#include "../../include/utils_op/utils.h" #define BACKLOG 10 @@ -74,6 +68,7 @@ int get_listener_socket(char *port) return sockfd; } + /** * @brief Get address from sockaddr structure * diff --git a/src/request.c b/src/netw_op/request.c similarity index 67% rename from src/request.c rename to src/netw_op/request.c index fda892b..b31039e 100644 --- a/src/request.c +++ b/src/netw_op/request.c @@ -1,17 +1,33 @@ -#include -#include -#include -#include -#include -#include +#include "../../include/netw_op/request.h" +#include "../../include/utils_op/utils.h" +#include "../../include/file_op/file.h" +#include "../../include/file_op/mime.h" -#include -#include +/** + * @brief Send 404 response + * + * @param fd + * @param path + */ +void res_404(int fd, char *path) +{ + FILE *fp = fopen("static/404.html", "r"); + const ssize_t fsize = 512; + char buf[fsize], msg[fsize]; -#include "../include/request.h" -#include "../include/utils.h" -#include "../include/file.h" -#include "../include/mime.h" + fread(buf, fsize, 1, fp); + fclose(fp); + + sprintf(msg, buf, path, path); + + struct header_s *header = gen_header(404, strlen(msg), "text/html"); + send(fd, header->str, header->size - 1, 0); + + send(fd, msg, strlen(msg), 0); + close(fd); + + printf("404 ERROR\n"); +} /** * @brief Get the path object @@ -21,8 +37,7 @@ */ char *get_path(char *request) { - char *tmp = strtok(request, " "); - char *path = strtok(NULL, " "); + char *path = strtok(request, " "); return path; } @@ -67,6 +82,7 @@ int send_response(int fd, char *req_path) char *file_path = gen_file_path(req_path); struct file_s *file = get_file_info(file_path); + if (file == NULL) { char *msg = "Server error"; @@ -79,15 +95,20 @@ int send_response(int fd, char *req_path) return 0; } + if (file->fd < 0) { - char *msg = "\n404, Not Found. Return to home? Home"; + // char *msg = "\n404, Not Found. Return to home? Home"; - struct header_s *header = gen_header(404, strlen(msg), "text/html"); - send(fd, header->str, header->size - 1, 0); + // struct header_s *header = gen_header(404, strlen(msg), "text/html"); + // send(fd, header->str, header->size - 1, 0); - send(fd, msg, strlen(msg), 0); - close(fd); + // send(fd, msg, strlen(msg), 0); + // close(fd); + + // printf("404 ERROR\n"); + + res_404(fd, req_path); return 0; } @@ -96,8 +117,6 @@ int send_response(int fd, char *req_path) struct header_s *header = gen_header(200, file->size, mime_type); - printf("\n---\n%s\n%ld\n---\n", header->str, header->size); - int rv = send(fd, header->str, header->size - 1, 0); if (rv < 0) @@ -141,6 +160,15 @@ void handle_get_request(int fd, char *request) char *path = get_path(request); printf("Client accessed path: %s\n", path); + if (strncmp(path, "/blog/", strlen("/blog/")) == 0) + { + char *id = (char *)malloc(strlen(path) - strlen("/blog/") + 1); + memmove(id, path + strlen("/blog/"), strlen(path) - strlen("/blog/") + 1); + + printf("Blog post id = %s\n", id); + } + + if (send_response(fd, path) < 0) { err_msg("couldn't send response"); diff --git a/src/server.c b/src/server.c index c144f42..8a0c475 100644 --- a/src/server.c +++ b/src/server.c @@ -8,9 +8,9 @@ #include #include -#include "../include/netw.h" -#include "../include/utils.h" -#include "../include/request.h" +#include "../include/netw_op/netw.h" +#include "../include/utils_op/utils.h" +#include "../include/netw_op/request.h" /** * @brief Handle client connection @@ -19,7 +19,7 @@ */ void handle_connection(int fd) { - const size_t request_buffer_size = 512; + const size_t request_buffer_size = 1024; char request[request_buffer_size]; char *prt; @@ -31,7 +31,7 @@ void handle_connection(int fd) return; } - // printf("Request:\n%s---\n", request); + // printf("\nRequest:\n%s---\n", request); prt = strstr(request, " HTTP/"); if (prt == NULL) @@ -42,10 +42,12 @@ void handle_connection(int fd) { if (strncmp(request, "GET ", 4) == 0) { + memmove(request, request + 4, strlen(request) - 3); handle_get_request(fd, request); } else if (strncmp(request, "POST ", 5) == 0) { + memmove(request, request + 5, strlen(request) - 4); handle_post_request(fd, request); } else @@ -97,7 +99,10 @@ int main(int argc, char *argv[]) int pid = fork(); if (pid < 0) + { err_msg("fork failed"); + close(client_fd); + } else if (pid == 0) { close(listenfd); diff --git a/src/utils_op/arr.c b/src/utils_op/arr.c new file mode 100644 index 0000000..0a63a7f --- /dev/null +++ b/src/utils_op/arr.c @@ -0,0 +1,31 @@ +#include "../../include/utils_op/arr.h" +#include + +/** + * @brief Insert string to the end of array of strings + * + * @param arr + * @param length + * @param value + */ +void insert_to_arr(char ***arr, size_t length, char *value) +{ + *arr = realloc(*arr, (length + 1) * sizeof(char *)); + + (*arr)[length] = malloc(strlen(value) * sizeof(char)); + strcpy((*arr)[length], value); +} + +/** + * @brief Free memory allocated for array of strings + * + * @param arr + * @param length + */ +void free_arr(char **arr, int length) +{ + for (int i = 0; i < length; i++) + free(arr[i]); + + free(arr); +} \ No newline at end of file diff --git a/src/utils_op/llist.c b/src/utils_op/llist.c new file mode 100644 index 0000000..65ebb7d --- /dev/null +++ b/src/utils_op/llist.c @@ -0,0 +1,126 @@ +#include +#include + +#define NUMBER 5 + +typedef struct llist_s +{ + char *value; + struct llist_s *next; +} llist_t; + +/** + * @brief Find item by number + * + * @param list + * @param n + * @return llist_t* + */ +llist_t *find_item(llist_t *list, int n) +{ + for (int i = 0; i < n; i++) + list = list->next; + return list; +} + +/** + * @brief Fill llist with array + * + * @param list + * @param arr + * @param n + */ +void fill_with_arr(llist_t **list, char **arr, size_t n) +{ + llist_t *current = *list; + for (int i = 0; i < n; i++) + { + current->value = arr[i]; + current = current->next; + } +} + +/** + * @brief Print hole list + * + * @param list + */ +void print_llist(llist_t *list) +{ + llist_t *current = list; + int i = 0; + + while (current != NULL) + { + printf("%d - %s\n", i + 1, current->value); + current = current->next; + i++; + } + + printf("\n"); +} + +/** + * @brief Add value to the specified pos of llist + * + * @param head + * @param pos + * @param value + * @return llist_t* + */ +llist_t *add_to_list(llist_t **head, int pos, char *value) +{ + if (pos == 1) + { + llist_t *new = malloc(sizeof(llist_t)); + new->value = value; + new->next = *head; + + *head = new; + return new; + } + + llist_t *current = *head; + + for (int i = 0; i < pos - 2; i++) + current = current->next; + + llist_t *next = current->next; + + current->next = malloc(sizeof(llist_t)); + current->next->value = value; + current->next->next = next; + + return current->next; +} + +// int main() +// { +// llist_t *head = malloc(sizeof(llist_t)); + +// head->value = "first"; + +// head->next = malloc(sizeof(llist_t)); +// head->next->value = "second"; + +// head->next->next = malloc(sizeof(llist_t)); +// head->next->next->value = "third"; + +// head->next->next->next = malloc(sizeof(llist_t)); +// head->next->next->next->value = "forth"; + +// head->next->next->next->next = malloc(sizeof(llist_t)); +// head->next->next->next->next->value = "fifth"; + +// head->next->next->next->next->next = malloc(sizeof(llist_t)); +// head->next->next->next->next->next->value = "sixth"; +// head->next->next->next->next->next->next = NULL; + +// print_llist(head); + +// add_to_list(&head, 9, "Hola"); + +// print_llist(head); + +// return 0; +// } \ No newline at end of file diff --git a/src/utils.c b/src/utils_op/utils.c similarity index 89% rename from src/utils.c rename to src/utils_op/utils.c index c73921a..574e1e0 100644 --- a/src/utils.c +++ b/src/utils_op/utils.c @@ -1,9 +1,4 @@ -#include -#include -#include -#include - -#include "../include/utils.h" +#include "../../include/utils_op/utils.h" /** * @brief Prints error @@ -29,7 +24,7 @@ char *add_to_front(char **str1, char *str2) strcpy(*str1, str2); strcat(*str1, tmp); - free(tmp); + // free(tmp); return *str1; } diff --git a/static/404.html b/static/404.html index 234e744..4ddcb3b 100644 --- a/static/404.html +++ b/static/404.html @@ -7,7 +7,8 @@

Not Found

-

The requested URL was not found on this server.

+

The requested URL: %s was not found on this server.

+

Return home

\ No newline at end of file diff --git a/static/about/index.html b/static/about/index.html index 33001dc..b7591d9 100644 --- a/static/about/index.html +++ b/static/about/index.html @@ -5,10 +5,13 @@ About + - Back +
+ +

Me

the pig diff --git a/static/gallery/index.html b/static/gallery/index.html new file mode 100644 index 0000000..3f15417 --- /dev/null +++ b/static/gallery/index.html @@ -0,0 +1,15 @@ + + + + + + Gallery + + + +
+ +
+ %s + + \ No newline at end of file diff --git a/static/index.html b/static/index.html index e969b51..e81235d 100644 --- a/static/index.html +++ b/static/index.html @@ -1,12 +1,35 @@ + Test + + + -

Testing paragraf

- About me +
+ +
+
+

Home

+ +

Blog

+
    + %s +
+

Tech articles

+
    + %s +
+
+ \ No newline at end of file diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..3825639 Binary files /dev/null and b/static/logo.png differ diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..8d64ebb --- /dev/null +++ b/static/style.css @@ -0,0 +1,48 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + + font-family: "alte_haas_grotesk_bold", "Helvetica Neue", Helvetica, Arial; +} + +::selection { + background-color: #000000; + color: #ffffff; +} + +html { + min-height: 100vh; +} + +body { + background-color: #ffffff; + border-top: solid 5px #000000; + padding: 45px; +} + +header { + height: 65px; + margin-bottom: 20px; +} + +header img { + height: 100%; +} + +main h1 { + margin: 20px 0; +} + +main li { + list-style-type: none; +} + +li a { + color: #000000; + font-family: monospace; +} + +li:hover a { + text-decoration: none; +}