Updated project structure and makefile. Started creating frontend. Created csv database interphase

This commit is contained in:
Dmitriy Shishkov 2020-06-30 12:39:50 +05:00
parent 457a52a585
commit db9b46f041
28 changed files with 643 additions and 89 deletions

3
.gitignore vendored
View File

@ -1,4 +1,3 @@
bin/
obj/
tmp/
build/
.vscode/

View File

@ -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
MKDIR_P ?= mkdir -p

11
include/db_op/blogpost.h Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
#include <unistd.h>
typedef struct
{
char *header;
char *content;
char **tags;
char *author;
unsigned int key;
} blogpost_t;

17
include/db_op/db.h Normal file
View File

@ -0,0 +1,17 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#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);

View File

@ -1,3 +1,10 @@
#include <string.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
struct file_s
{
char *path;

View File

@ -1 +1,3 @@
#include <string.h>
char *get_mime_type(char *file_path);

View File

@ -1,2 +0,0 @@
int get_listener_socket(char *port);
void *get_in_addr(struct sockaddr *sa);

8
include/netw_op/netw.h Normal file
View File

@ -0,0 +1,8 @@
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
int get_listener_socket(char *port);
void *get_in_addr(struct sockaddr *sa);

View File

@ -1,3 +1,13 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
struct header_s {
char * str;
size_t size;

5
include/utils_op/arr.h Normal file
View File

@ -0,0 +1,5 @@
#include <string.h>
#include <stdlib.h>
void insert_to_arr(char ***arr, size_t length, char *value);
void free_arr(char **arr, int length);

0
include/utils_op/llist.h Normal file
View File

View File

@ -1,3 +1,8 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void err_msg(char *msg);
char *add_to_front(char **str1, char *str2);
char *get_status_message(int status_code);

1
src/db_op/blogpost.c Normal file
View File

@ -0,0 +1 @@
#include "../../include/db_op/blogpost.h"

233
src/db_op/db.c Normal file
View File

@ -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;
}

View File

@ -1,12 +1,5 @@
#include <string.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#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;
}

View File

@ -1,7 +1,5 @@
#include <string.h>
#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;
}
}

View File

@ -1,11 +1,5 @@
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#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
*

View File

@ -1,17 +1,33 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#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 <sys/types.h>
#include <sys/socket.h>
/**
* @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 = "<html>\n<body>404, Not Found. Return to home? <a href=\"/\">Home</a></body><html/>";
// char *msg = "<html>\n<body>404, Not Found. Return to home? <a href=\"/\">Home</a></body><html/>";
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");

View File

@ -8,9 +8,9 @@
#include <unistd.h>
#include <netdb.h>
#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);

31
src/utils_op/arr.c Normal file
View File

@ -0,0 +1,31 @@
#include "../../include/utils_op/arr.h"
#include <stdio.h>
/**
* @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);
}

126
src/utils_op/llist.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <stdlib.h>
#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;
// }

View File

@ -1,9 +1,4 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#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;
}

View File

@ -7,7 +7,8 @@
<body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>The requested URL: <a href="%s">%s</a> was not found on this server.</p>
<p>Return <a href="/">home</a></p>
</body>
</html>

View File

@ -5,10 +5,13 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<a href="../">Back</a>
<header>
<a href="/" id="logo"><img src="./logo.png" alt="logo" /></a>
</header>
<p>Me</p>
<img src="/about/me.jpg" alt="the pig" style="max-height: 200px;" />
</body>

15
static/gallery/index.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gallery</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<header>
<a href="/" id="logo"><img src="./logo.png" alt="logo" /></a>
</header>
%s
</body>
</html>

View File

@ -1,12 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<p>Testing paragraf</p>
<a href="./about">About me</a>
<header>
<a href="/" id="logo"><img src="./logo.png" alt="logo" /></a>
</header>
<main>
<h1>Home</h1>
<ul>
<li><a href="/about">About me</a></li>
<li><a href="/gallery">Gallery</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/philosophy">Philosophy</a></li>
</ul>
<h1>Blog</h1>
<ul>
%s
</ul>
<h1>Tech articles</h1>
<ul>
%s
</ul>
</main>
</body>
</html>

BIN
static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

48
static/style.css Normal file
View File

@ -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;
}