first commit

This commit is contained in:
2024-10-05 20:48:04 +02:00
commit 85b57e9cb8
15 changed files with 277163 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
social
social.exe
*.db
backtrace.txt
logs/*
+2
View File
@@ -0,0 +1,2 @@
all:
gcc serve.c tinytemplate.c sqlite3.c -o social -Wall -Wextra -ggdb
+53
View File
@@ -0,0 +1,53 @@
# Log buffer size in bytes
log_buff_size_b 1048576 # 1MB
# Log file size limit in bytes
log_file_limit_b 16777216 # 16MB
# Log folder limit in megabytes
log_dir_limit_mb 25600 # 25GB
# Log folder
log_dir_path logs
# How often the log buffer is flushed
log_flush_timeout_sec 3
# Capacity of the server. This must be lower than the NOFILE rlimit by 2.
# If the rlimit is 1024, max_connections can only go up to 1024-2=1022
max_connections 1022
# Maximum HTTP request count that can be server through a single TCP connection
keep_alive_max_requests 1000
# Maximum time a TCP connection is allowed to be alive
connection_timeout_sec 60
# Timeout for the closing state (when response is being flushed before the TCP
# connection is closed)
closing_timeout_sec 1
# Request receive timeout
request_timeout_sec 5
access_log yes
# These are debug options
show_io yes
show_requests no
# Address and port the HTTP server will listen on.
# To bind to all available interfaces, leave a blank address blank:
http_addr "127.0.0.1"
http_port 8080
# Address and port the HTTPS server will listen on (if the server
# has been built with HTTPS support). To bind to all interfaces you
# must leave the address blank.
https_addr "127.0.0.1"
https_port 8081
# Certificate and private key files
cert_file "cert.pem"
privkey_file "key.pem"
+30
View File
@@ -0,0 +1,30 @@
<html>
<head>
<title>Log in</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
</tr>
</table>
</nav>
<form method="POST" action="/action/login">
<input type="text" name="name" placeholder="name" />
<input type="password" name="pass" placeholder="pass" />
<input type="submit" value="login" />
</form>
</main>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
<html>
<head>
<title>{{title}}</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
{% if login %}
<td><a href="/users/{{login_username}}">{{login_username}}</a></td>
<td><a href="/action/logout">logout</a></td>
{% else %}
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
{% end %}
</tr>
</table>
</nav>
<article>
<h1>{{title}} (by {{author}})</h1>
<p>{{content}}</p>
</article>
</main>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
<html>
<head>
<title>Posts</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
{% if login %}
<td><a href="/users/{{login_username}}">{{login_username}}</a></td>
<td><a href="/action/logout">logout</a></td>
{% else %}
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
{% end %}
</tr>
</table>
</nav>
{% if login %}
<form action="/action/post" method="POST">
<input type="text" name="title" placeholder="title" />
<textarea name="content" placeholder="content"></textarea>
<input type="submit" value="publish" />
</form>
{% end %}
{% for post in posts %}
<div class="post-preview">
<a href="/posts/{{post.id}}">{{post.title}}</a> by <a href="/users/{{post.author}}">{{post.author}}</a>
</div>
{% end %}
</main>
</body>
</html>
+31
View File
@@ -0,0 +1,31 @@
<html>
<head>
<title>Sign up</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
</tr>
</table>
</nav>
<form method="POST" action="/action/signup">
<input type="text" name="name" placeholder="name" />
<input type="password" name="pass" placeholder="pass" />
<textarea name="bio" placeholder="bio"></textarea>
<input type="submit" value="signup" />
</form>
</main>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
<html>
<head>
<title>{{name}}'s profile</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
{% if login %}
<td><a href="/users/{{login_username}}">{{login_username}}</a></td>
<td><a href="/action/logout">logout</a></td>
{% else %}
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
{% end %}
</tr>
</table>
</nav>
<article>
<h1>{{name}}'s proile</h1>
<p>{{bio}}</p>
</article>
</main>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
<html>
<head>
<title>Users</title>
<link rel="stylesheet" media="screen" href="/static/global.css" />
</head>
<body>
<main>
<nav>
<table>
<tr>
<td><a href="/posts">Posts</a></td>
<td><a href="/users">Users</a></td>
</tr>
</table>
<table>
<tr>
{% if login %}
<td><a href="/users/{{login_username}}">{{login_username}}</a></td>
<td><a href="/action/logout">logout</a></td>
{% else %}
<td><a href="/login">login</a></td>
<td><a href="/signup">signup</a></td>
{% end %}
</tr>
</table>
</nav>
{% for user in users %}
<div class="user-preview">
<a href="/users/{{user.name}}">{{user.name}}</a>
</div>
{% end %}
</main>
</body>
</html>
+5758
View File
File diff suppressed because it is too large Load Diff
+255932
View File
File diff suppressed because it is too large Load Diff
+13374
View File
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
main {
width: 600px;
margin: auto;
}
nav {
overflow: auto;
background: #fab8b8;
border: 1px solid #c16464;
border-radius: 3px;
margin-bottom: 10px;
}
nav table {
float: left;
border-collapse: collapse;
}
nav table:last-child {
float: right;
}
nav table td {
padding: 10px;
}
form {
width: calc(100% - 20px);
padding: 10px;
overflow: auto;
background: #c9ffcd;
border-radius: 3px;
border: 1px solid #76c97d;
}
form input,
form textarea {
width: 100%;
margin-bottom: 10px;
padding: 3px;
border-radius: 3px;
border: 1px solid #76c97d;
}
form input:last-child,
form textarea:last-child {
margin-bottom: 0;
}
form textarea {
height: 150px;
}
form input[type=submit] {
width: 200px;
float: right;
}
.user-preview {
margin-top: 10px;
padding: 10px;
background: #ccd6fb;
border: 1px solid #6478c1;
border-radius: 3px;
}
.post-preview {
margin-top: 10px;
padding: 10px;
background: #ccd6fb;
border: 1px solid #6478c1;
border-radius: 3px;
}
+1666
View File
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
#ifndef TINYTEMPLATE_H
#define TINYTEMPLATE_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifndef TINYTEMPLATE_MAX_SCOPE_DEPTH
#define TINYTEMPLATE_MAX_SCOPE_DEPTH 8
#endif
#ifndef TINYTEMPLATE_MAX_EXPR_DEPTH
#define TINYTEMPLATE_MAX_EXPR_DEPTH 8
#endif
#ifndef TINYTEMPLATE_MAX_ITER_DEPTH
#define TINYTEMPLATE_MAX_ITER_DEPTH 8
#endif
typedef enum {
TINYTEMPLATE_TYPE_INT,
TINYTEMPLATE_TYPE_FLOAT,
TINYTEMPLATE_TYPE_DICT,
TINYTEMPLATE_TYPE_ARRAY,
TINYTEMPLATE_TYPE_STRING,
} tinytemplate_type_t;
typedef struct tinytemplate_value_t tinytemplate_value_t;
typedef bool (*tinytemplate_nextcallback_t)(void*, tinytemplate_value_t*);
typedef bool (*tinytemplate_getter_t)(void*, const char*, size_t, tinytemplate_value_t*);
typedef void (*tinytemplate_callback_t)(void *userp, const char *str, size_t len);
typedef struct {
void *data;
tinytemplate_getter_t get;
} tinytemplate_dict_t;
typedef struct {
void *data;
tinytemplate_nextcallback_t next;
} tinytemplate_array_t;
typedef struct {
const char *str; size_t len;
} tinytemplate_string_t;
typedef union {
int64_t as_int;
double as_float;
tinytemplate_dict_t as_dict;
tinytemplate_array_t as_array;
tinytemplate_string_t as_string;
} tinytemplate_union_t;
struct tinytemplate_value_t {
tinytemplate_type_t type;
tinytemplate_union_t data;
};
typedef struct {
int opcode;
struct {
int64_t as_int;
size_t as_size;
double as_float;
} operands[2];
} tinytemplate_instr_t;
typedef enum {
TINYTEMPLATE_STATUS_DONE,
TINYTEMPLATE_STATUS_ESYMBOL,
TINYTEMPLATE_STATUS_ESCOPE,
TINYTEMPLATE_STATUS_EDEPTH,
TINYTEMPLATE_STATUS_ETYPE,
TINYTEMPLATE_STATUS_EITER,
TINYTEMPLATE_STATUS_EMEMORY,
TINYTEMPLATE_STATUS_ESYNTAX,
TINYTEMPLATE_STATUS_ESEMANT,
} tinytemplate_status_t;
tinytemplate_status_t
tinytemplate_eval(const char *src, const tinytemplate_instr_t *program,
void *userp, tinytemplate_getter_t params,
tinytemplate_callback_t callback,
char *errmsg, size_t errmax);
tinytemplate_status_t
tinytemplate_compile(const char *src, size_t len,
tinytemplate_instr_t *program,
size_t max_instr, size_t *num_instr,
char *errmsg, size_t errmax);
void tinytemplate_set_int(tinytemplate_value_t *dst, int64_t value);
void tinytemplate_set_float(tinytemplate_value_t *dst, float value);
void tinytemplate_set_string(tinytemplate_value_t *dst, const char *str, size_t len);
void tinytemplate_set_array(tinytemplate_value_t *dst, void *data, tinytemplate_nextcallback_t next);
void tinytemplate_set_dict(tinytemplate_value_t *dst, void *data, tinytemplate_getter_t get);
#endif