Compare commits

...

2 Commits

Author SHA1 Message Date
ngn
4e08375748
Merge branch 'main' of https://git.ngn.tf/ngn/website
Some checks failed
Build the docker image for the doc server / build (push) Failing after 15s
2025-05-22 20:12:41 +03:00
ngn
912bf616b6
update doc server to ctorm 1.8.1
Signed-off-by: ngn <ngn@ngn.tf>
2025-05-22 20:12:05 +03:00
29 changed files with 178 additions and 122 deletions

View File

@ -81,7 +81,7 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 120
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4

35
doc/.clang-tidy Normal file
View File

@ -0,0 +1,35 @@
---
# "gnu-zero-variadic-macro-arguments" ignored because we are using GNU99
# standart
# "clang-diagnostic-language-extension-token" is ignored because we need the
# asm() extension token
# "DeprecatedOrUnsafeBufferHandling" ignored because C11 "_s" functions are not
# secure either
Checks: >-
clang-diagnostic-*,
-clang-diagnostic-gnu-zero-variadic-macro-arguments,
-clang-diagnostic-language-extension-token,
clang-analyzer-*,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
portability-*,
performance-*,
WarningsAsErrors: '*'
HeaderFileExtensions:
- ''
- h
- hh
- hpp
- hxx
ImplementationFileExtensions:
- c
- cc
- cpp
- cxx
HeaderFilterRegex: '.*'
ExcludeHeaderFilterRegex: ''
FormatStyle: file
SystemHeaders: false
...

View File

@ -1,4 +1,4 @@
FROM ghcr.io/ngn13/ctorm:1.7
FROM ghcr.io/ngn13/ctorm:1.8.1
WORKDIR /doc

View File

@ -26,10 +26,13 @@ $(DISTDIR)/%.o: src/%.c
format:
clang-format -i -style=file $(CSRCS) $(HSRCS)
lint:
clang-tidy --warnings-as-errors --config= $(CSRCS) $(HSRCS)
clean:
rm -rf $(DISTDIR)
run:
./doc.elf
.PHONY: format clean run
.PHONY: format lint clean run

View File

@ -1,4 +0,0 @@
{
"title": "privacy",
"desc": "Learn how I respect your privacy"
}

View File

@ -1,4 +0,0 @@
{
"title": "gizlilik",
"desc": "Gizliliğinize nasıl önem verdiğimi öğrenin"
}

View File

@ -3,13 +3,13 @@
#include <stdbool.h>
#include <dirent.h>
#include "util.h"
#include "file.h"
typedef struct {
DIR *dir;
util_file_t *file;
char name[NAME_MAX + 1];
char *lang;
DIR *dir;
file_t *file;
char name[NAME_MAX + 1];
char *lang;
} docs_t;
bool docs_init(docs_t *docs, char *dir);

10
doc/inc/file.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
typedef struct {
char *content;
int64_t size;
} file_t;
file_t *file_load(int dirfd, char *path);
void file_free(file_t *file);

View File

@ -4,16 +4,8 @@
#include <stdint.h>
#include <ctype.h>
typedef struct {
char *content;
uint64_t size;
} util_file_t;
#define util_toupper(str) \
for (char *c = str; *c != 0; c++) \
#define util_toupper(str) \
for (char *c = str; *c != 0; c++) \
*c = toupper(*c)
uint64_t util_endswith(char *str, char *suf);
void util_send(ctorm_res_t *res, uint16_t code, cJSON *json);
util_file_t *util_file_load(int dirfd, char *path);
void util_file_free(util_file_t *file);
bool util_parse_doc_name(char *name, char **lang, const char *ext);
uint64_t util_endswith(char *str, char *suf);
void util_send(ctorm_res_t *res, uint16_t code, cJSON *json);

View File

@ -0,0 +1,4 @@
{
"title": "privacy",
"desc": "Privacy policy"
}

View File

@ -0,0 +1,4 @@
{
"title": "gizlilik",
"desc": "Gizlilik ilkesi"
}

View File

@ -11,22 +11,25 @@
option_t options[] = {
// name value requied
{"host", "0.0.0.0:7003", true }, // host the server should listen on
{"docs_dir", "./docs", true }, // documentation directory
{"", NULL, false},
{"host", "0.0.0.0:7003", true }, // host the server should listen on
{"dir", "./pages", true }, // documentation pages directory
{"", NULL, false},
};
bool config_load(config_t *conf) {
bzero(conf, sizeof(*conf));
memset(conf, 0, sizeof(*conf));
char name_env[OPT_NAME_MAX + 10], name_copy[OPT_NAME_MAX], *value = NULL;
conf->options = options;
for (option_t *opt = conf->options; opt->value != NULL; opt++, conf->count++) {
strcpy(name_copy, opt->name);
for (option_t *opt = conf->options; opt->value != NULL;
opt++, conf->count++) {
// convert option name to environment variable name
strncpy(name_copy, opt->name, OPT_NAME_MAX);
util_toupper(name_copy);
snprintf(name_env, sizeof(name_env), "WEBSITE_%s", name_copy);
// attempt to load the value from the environment
if ((value = getenv(name_env)) != NULL)
opt->value = value;
@ -36,7 +39,9 @@ bool config_load(config_t *conf) {
if (!opt->required || NULL != opt->value)
continue;
ctorm_fail("please specify a value for the required config option: %s (%s)", opt->name, name_env);
ctorm_fail("please specify a value for the required config option: %s (%s)",
opt->name,
name_env);
errno = EFAULT;
return false;
}

View File

@ -1,6 +1,6 @@
#include <linux/limits.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
@ -9,7 +9,7 @@
#define DOCS_LANG_CODE_LEN 2
bool __docs_parse_name(docs_t *docs, char *ext) {
bool _docs_parse_name(docs_t *docs, char *ext) {
// check the extension
uint64_t ext_pos = util_endswith(docs->name, ext);
@ -22,7 +22,8 @@ bool __docs_parse_name(docs_t *docs, char *ext) {
// example.en\0json\0
// |
// `--- find this
for (docs->lang = docs->name; *docs->lang != 0 && *docs->lang != '.'; docs->lang++)
for (docs->lang = docs->name; *docs->lang != 0 && *docs->lang != '.';
docs->lang++)
continue;
if (*docs->lang != '.')
@ -39,11 +40,11 @@ bool __docs_parse_name(docs_t *docs, char *ext) {
return strlen(docs->lang) == DOCS_LANG_CODE_LEN && *docs->name != 0;
}
void __docs_clean(docs_t *docs) {
void _docs_clean(docs_t *docs) {
if (NULL == docs->file)
return;
util_file_free(docs->file);
file_free(docs->file);
docs->file = NULL;
}
@ -53,7 +54,7 @@ bool docs_init(docs_t *docs, char *dir) {
return false;
}
bzero(docs, sizeof(*docs));
memset(docs, 0, sizeof(*docs));
return NULL != (docs->dir = opendir(dir));
}
@ -64,15 +65,15 @@ char *docs_next(docs_t *docs, char *name, bool content) {
}
struct dirent *ent = NULL;
__docs_clean(docs);
_docs_clean(docs);
while (NULL != (ent = readdir(docs->dir))) {
if (*ent->d_name == '.')
continue;
strcpy(docs->name, ent->d_name);
strncpy(docs->name, ent->d_name, NAME_MAX);
if (!__docs_parse_name(docs, content ? ".md" : ".json"))
if (!_docs_parse_name(docs, content ? ".md" : ".json"))
continue;
if (NULL == name || strncmp(docs->name, name, NAME_MAX) == 0)
@ -84,7 +85,7 @@ char *docs_next(docs_t *docs, char *name, bool content) {
return NULL;
}
if (NULL == (docs->file = util_file_load(dirfd(docs->dir), ent->d_name)))
if (NULL == (docs->file = file_load(dirfd(docs->dir), ent->d_name)))
return NULL;
return docs->file->content;
@ -99,8 +100,8 @@ void docs_free(docs_t *docs) {
if (NULL == docs)
return;
__docs_clean(docs);
_docs_clean(docs);
closedir(docs->dir);
bzero(docs, sizeof(*docs));
memset(docs, 0, sizeof(*docs));
}

56
doc/src/file.c Normal file
View File

@ -0,0 +1,56 @@
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include "file.h"
file_t *file_load(int dirfd, char *path) {
if (NULL == path) {
errno = EINVAL;
return NULL;
}
file_t *file = NULL;
int fd = -1;
// open the taarget file
if ((fd = openat(dirfd, path, O_RDONLY)) < 0)
goto end; // errno set by open
// allocate a new file structure
if (NULL == (file = calloc(1, sizeof(file_t))))
goto end; // errno set by malloc
// calculate the file size
if ((file->size = lseek(fd, 0, SEEK_END)) < 0)
goto end;
// memory map the file
if (NULL ==
(file->content = mmap(0, file->size, PROT_READ, MAP_PRIVATE, fd, 0)))
goto end; // errno set by mmap
end:
if (fd != -1)
close(fd);
if (NULL != file && NULL == file->content) {
free(file);
return NULL;
}
return file;
}
void file_free(file_t *file) {
if (NULL == file)
return;
munmap(file->content, file->size);
free(file);
}

View File

@ -1,3 +1,4 @@
#include <ctorm/app.h>
#include <ctorm/ctorm.h>
#include <stdlib.h>
@ -19,25 +20,28 @@ int main() {
return EXIT_FAILURE;
}
// initialize the app config
ctorm_config_new(&app_config);
app_config.disable_logging = true;
app = ctorm_app_new(&app_config);
// create a new app
app = ctorm_app_new(&app_config);
// middlewares
MIDDLEWARE_ALL(app, "/*", route_cors);
MIDDLEWARE_ALL(app, "/*/*", route_cors);
ALL(app, "/*", route_cors);
ALL(app, "/*/*", route_cors);
// routes
GET(app, "/list", route_list);
GET(app, "/get/:name", route_get);
ctorm_app_all(app, route_notfound);
ctorm_app_default(app, route_notfound);
ctorm_app_local(app, "config", &conf);
ctorm_info("starting the web server on %s", host);
if (!ctorm_app_run(app, host))
ctorm_fail("failed to start the app: %s", ctorm_geterror());
ctorm_fail("failed to start the app: %s", ctorm_error());
ctorm_app_free(app);
return EXIT_SUCCESS;

View File

@ -3,7 +3,8 @@
void route_cors(ctorm_req_t *req, ctorm_res_t *res) {
RES_SET("Access-Control-Allow-Origin", "*");
RES_SET("Access-Control-Allow-Headers",
"Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, "
"Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, "
"Authorization, accept, origin, Cache-Control, "
"X-Requested-With");
RES_SET("Access-Control-Allow-Methods", "PUT, DELETE, GET");
}

View File

@ -1,31 +1,30 @@
#include <cjson/cJSON.h>
#include <dirent.h>
#include <linux/limits.h>
#include <cjson/cJSON.h>
#include <ctorm/ctorm.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include "routes.h"
#include "config.h"
#include "util.h"
#include "docs.h"
void route_get(ctorm_req_t *req, ctorm_res_t *res) {
config_t *conf = REQ_LOCAL("config");
char *doc_name = REQ_PARAM("name");
char *docs_dir = config_get(conf, "docs_dir"), *doc_data = NULL;
config_t *conf = REQ_LOCAL("config");
char *name = REQ_PARAM("name");
char *dir = config_get(conf, "dir"), *doc_data = NULL;
cJSON *json = NULL, *doc_json = NULL;
docs_t docs;
if (NULL == doc_name) {
if (NULL == name) {
ctorm_fail("documentation name not specified (how did that even happend)");
util_send(res, 500, NULL);
goto end;
}
if (!docs_init(&docs, docs_dir)) {
ctorm_fail("docs_init failed: %s", ctorm_geterror());
if (!docs_init(&docs, dir)) {
ctorm_fail("docs_init failed: %s", ctorm_error());
util_send(res, 500, NULL);
goto end;
}
@ -36,7 +35,7 @@ void route_get(ctorm_req_t *req, ctorm_res_t *res) {
goto end;
}
while (NULL != (doc_data = docs_next(&docs, doc_name, false))) {
while (NULL != (doc_data = docs_next(&docs, name, false))) {
if (NULL == (doc_json = cJSON_Parse(doc_data))) {
ctorm_fail("failed to parse JSON: %s (%s)", docs.name, docs.lang);
continue;
@ -53,7 +52,7 @@ void route_get(ctorm_req_t *req, ctorm_res_t *res) {
docs_reset(&docs);
while (NULL != (doc_data = docs_next(&docs, doc_name, true))) {
while (NULL != (doc_data = docs_next(&docs, name, true))) {
if (NULL == (doc_json = cJSON_GetObjectItem(json, docs.lang)))
continue;

View File

@ -3,21 +3,21 @@
#include <ctorm/ctorm.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include "routes.h"
#include "config.h"
#include "util.h"
#include "docs.h"
void route_list(ctorm_req_t *req, ctorm_res_t *res) {
config_t *conf = REQ_LOCAL("config");
char *docs_dir = config_get(conf, "docs_dir"), *doc_data = NULL;
config_t *conf = REQ_LOCAL("config");
char *dir = config_get(conf, "dir"), *doc_data = NULL;
cJSON *array = NULL, *json = NULL, *doc_json = NULL;
docs_t docs;
if (!docs_init(&docs, docs_dir)) {
ctorm_fail("docs_init failed: %s", ctorm_geterror());
if (!docs_init(&docs, dir)) {
ctorm_fail("docs_init failed: %s", ctorm_error());
util_send(res, 500, NULL);
goto end;
}
@ -31,7 +31,8 @@ void route_list(ctorm_req_t *req, ctorm_res_t *res) {
while (NULL != (doc_data = docs_next(&docs, NULL, false))) {
if (NULL == (array = cJSON_GetObjectItem(json, docs.lang)) &&
NULL == (array = cJSON_AddArrayToObject(json, docs.lang))) {
ctorm_fail("failed to create an array object for the language %s", docs.lang);
ctorm_fail(
"failed to create an array object for the language %s", docs.lang);
continue;
}

View File

@ -1,17 +1,8 @@
#include <linux/limits.h>
#include <ctorm/ctorm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdint.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <errno.h>
#include "util.h"
@ -57,45 +48,3 @@ void util_send(ctorm_res_t *res, uint16_t code, cJSON *json) {
RES_JSON(json);
}
util_file_t *util_file_load(int dirfd, char *path) {
if (NULL == path) {
errno = EINVAL;
return NULL;
}
util_file_t *file = NULL;
struct stat buf;
int fd = -1;
if (NULL == (file = malloc(sizeof(util_file_t))))
goto end; // errno set by malloc
if ((fd = openat(dirfd, path, O_RDONLY)) < 0)
goto end; // errno set by open
if (fstat(fd, &buf) < 0)
goto end; // errno set by fstat
if (NULL == (file->content = mmap(0, (file->size = buf.st_size), PROT_READ, MAP_PRIVATE, fd, 0)))
goto end; // errno set by mmap
end:
if (fd != -1)
close(fd);
if (NULL == file->content) {
free(file);
return NULL;
}
return file;
}
void util_file_free(util_file_t *file) {
if (NULL == file)
return;
munmap(file->content, file->size);
free(file);
}