mobley

C Git HTTP server
Log | Files | Refs | Submodules | README | git clone https://git.ne02ptzero.me/git/mobley

commit a62a8c6375815f5a791cdf3c36850ae685c122a1
parent 5c19003462247a6c8df2c0ed28d0d87eed9ce057
Author: Louis Solofrizzo <lsolofrizzo@online.net>
Date:   Mon, 17 Dec 2018 15:18:52 +0100

Add repository list parsing and printing

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>

Diffstat:
M.gitignore | 1+
MCMakeLists.txt | 8++++++++
Mconfig.c | 129++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mconfig.yaml | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mhtml.c | 2++
Mhtml.h | 1+
Mindex.c | 26+++++++++++++++++++++++++-
Mmain.c | 2++
Mmobley.h | 8++++++++
Arepository.h | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mstyle/main.css | 9+++++++++
Mtemplate.c | 2++
12 files changed, 404 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,2 @@ build/ +compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -2,6 +2,14 @@ cmake_minimum_required(VERSION 3.4) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +IF( EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json" ) + message("-- Copying compile_commands.json...") + EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json + ) +ENDIF() + if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message (FATAL_ERROR "Don't use 'cmake .' Create a build folder first") endif (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) diff --git a/config.c b/config.c @@ -16,6 +16,7 @@ #include <yaml.h> #include <config.h> +#include <repository.h> # define COPY_OR_FAIL(dst, src) do { \ dst = strdup((char *)src); \ @@ -25,6 +26,9 @@ static bool config_read_token(const char *tok, unsigned char *value, mobley_t *ctx) { + static bool is_token = true; + static char *token = NULL; + if (strcmp(tok, "static_dir") == 0) COPY_OR_FAIL(ctx->conf.static_dir, value); else if (strcmp(tok, "logo") == 0) @@ -35,10 +39,21 @@ static bool config_read_token(const char *tok, unsigned char *value, mobley_t *c COPY_OR_FAIL(ctx->conf.title, value); else if (strcmp(tok, "address") == 0) COPY_OR_FAIL(ctx->ip, value); + else if (strcmp(tok, "repo_dir") == 0) + COPY_OR_FAIL(ctx->repos.repo_dir, value); else if (strcmp(tok, "port") == 0) return str_to_int32((char *)value, (int *)&ctx->port, 10); else if (strcmp(tok, "styles") == 0) string_array_node_add(&ctx->conf.styles, (char *)value); + else if (strcmp(tok, "repositories") == 0) + { + if (is_token) + COPY_OR_FAIL(token, value); + else + free(token); + + is_token = (is_token ? false : true); + } else { printf("Unknown token = %s\n", tok); @@ -48,6 +63,96 @@ static bool config_read_token(const char *tok, unsigned char *value, mobley_t *c return true; } +static bool config_read_repositories(yaml_parser_t *parser, yaml_event_t *event, + mobley_t *ctx) +{ + char *token = NULL; + bool is_token = false; + int quit = 1; + repository_t *repo = NULL; + + repo = calloc(1, sizeof(*repo)); + if (repo == NULL) + goto end; + + do { + switch (event->type) + { + case YAML_NO_EVENT: + case YAML_STREAM_START_EVENT: + case YAML_STREAM_END_EVENT: + case YAML_DOCUMENT_START_EVENT: + case YAML_DOCUMENT_END_EVENT: + case YAML_ALIAS_EVENT: + case YAML_SEQUENCE_START_EVENT: + case YAML_SEQUENCE_END_EVENT: + /* Nothing */ + break; + + case YAML_MAPPING_START_EVENT: + quit--; + break; + case YAML_MAPPING_END_EVENT: + list_add_tail(&repo->node, &ctx->repos.repos); + quit++; + + if (quit != 2) + { + repo = calloc(1, sizeof(*repo)); + if (repo == NULL) + goto end; + } + + break ; + + case YAML_SCALAR_EVENT: + if (is_token) + { + token = strdup((const char *)event->data.scalar.value); + if (token == NULL) + goto end; + } + else + { + char *val = (char *)event->data.scalar.value; + + if (token != NULL) + { + if (strcmp(token, "name") == 0) + COPY_OR_FAIL(repo->name, val); + else if (strcmp(token, "description") == 0) + COPY_OR_FAIL(repo->desc, val); + else if (strcmp(token, "owner") == 0) + COPY_OR_FAIL(repo->owner, val); + else if (strcmp(token, "dir") == 0) + repository_set_path(repo, val, ctx->repos.repo_dir); + else + { + printf("Unknown token = %s\n", token); + goto end; + } + } + FREE(token); + } + + is_token = (is_token ? false : true); + break; + } + + yaml_event_delete(event); + + if (!yaml_parser_parse(parser, event)) + goto end; + + } while (quit != 2); + + free(token); + return true; +end: + free(repo); + return false; +} + bool config_read_file(const char *path, mobley_t *ctx) { FILE *fd = fopen(path, "r"); @@ -70,7 +175,7 @@ bool config_read_file(const char *path, mobley_t *ctx) if (!yaml_parser_parse(&parser, &event)) goto end; - switch(event.type) + switch (event.type) { case YAML_NO_EVENT: case YAML_STREAM_START_EVENT: @@ -90,15 +195,23 @@ bool config_read_file(const char *path, mobley_t *ctx) case YAML_SEQUENCE_END_EVENT: is_sequence = false; is_token = true; - free(token); + FREE(token); break; case YAML_SCALAR_EVENT: if (is_token) { - token = strdup((const char *)event.data.scalar.value); - if (token == NULL) - goto end; + if (strcmp((const char *)event.data.scalar.value, "repositories") == 0) + { + if (!config_read_repositories(&parser, &event, ctx)) + goto end; + } + else + { + token = strdup((const char *)event.data.scalar.value); + if (token == NULL) + goto end; + } } else { @@ -109,7 +222,9 @@ bool config_read_file(const char *path, mobley_t *ctx) if (!is_sequence) { if (!is_token) - free(token); + { + FREE(token); + } is_token = (is_token ? false : true); } @@ -120,7 +235,7 @@ bool config_read_file(const char *path, mobley_t *ctx) if (event.type != YAML_STREAM_END_EVENT) yaml_event_delete(&event); - } while(event.type != YAML_STREAM_END_EVENT); + } while (event.type != YAML_STREAM_END_EVENT); ret = true; end: diff --git a/config.yaml b/config.yaml @@ -1,10 +1,157 @@ -address: 127.0.0.1 -port: 4242 - -static_dir: /usr/local/share/mobley/ -logo: logo.png -desc: Software Stuff -title: git:// +address : 127.0.0.1 +port : 4242 +static_dir : /usr/local/share/mobley +logo : logo.png +desc : Software Stuff +title : git:// +repo_dir : /tmp/git styles: - main.css + - test.css + +repositories: + - dir : linux.git + name : linux + description : my linux tree + owner : louis + + - dir : mobley.git + name : mobley + description : HTTP git distributed viewer C server + owner : louis + + - dir : krakern.git + name : krakern + description : C++ POSIX kernel + owner : louis + + - dir : libdev.a.git + name : libdev.a + description : C helper library + owner : louis + + - dir : lt.git + name : lt + description : simple terminal emulator + owner : louis + + - dir : 42_Scale.git + name : 42_scale + description : A small software to create and edit 42 (.yaml) scale files easily + owner : louis + + - dir : Y-asc.git + name : y-asc + description : Yet Another Stupid compiler + owner : louis + + - dir : KFS.git + name : kfs + description : kernel from scratch course + owner : louis + + - dir : network.git + name : network + description : low level network subjects + owner : louis + + - dir : C_Advanced_Tips_n_Tricks.git + name : C advanced tips and tricks + description : 42 conference about some C tricks + owner : louis + + - dir : ne02ptzero.me.git + name : ne2ptzero.me + description : my personnal website + owner : louis + + - dir : home.git + name : home + description : my firefox custom homepage + owner : louis + + - dir : relita.git + name : relita + description : an encrypted, decentralized, peer-to-peer social network + owner : louis + + - dir : neocgit.git + name : neocgit + description : a more 'modern' version of cgit + owner : louis + + - dir : shayla.git + name : shayla + description : a simple yet fast static site builder + owner : louis + + - dir : dotfiles.git + name : dotfiles + description : various configuration files + owner : louis + + - dir : git-appraise-vim.git + name : git-appraise-vim + description : git appraise wrapper for vim + owner : louis + + - dir : Grog-Knight.git + name : grog-knight + description : Some game in C++ + owner : louis + + - dir : IRC-Bot.git + name : irc-bot + description : morphux IRC bot + owner : louis + + - dir : blog.git + name : blog + description : my personnal blog + owner : louis + + - dir : builder.git + name : builder + description : package builder + owner : morphux + + - dir : documentation.git + name : documentation + description : developer documentation + owner : morphux + + - dir : graphic.git + name : graphic + description : graphic assets + owner : morphux + + - dir : install.git + name : install + description : installer + owner : morphux + + - dir : lib.git + name : lib + description : morphux C utility library + owner : morphux + + - dir : libmpm.git + name : libmpm + description : morphux C package management library + owner : morphux + + - dir : mpm.git + name : mpm + description : morphux package manager + owner : morphux + + - dir : mps.git + name : mps + description : morphux package server + owner : morphux + + - dir : protocol.git + name : protocol + description : protocol tests + owner : morphux diff --git a/html.c b/html.c @@ -53,6 +53,8 @@ void _html(server_req_t *r, const mobley_t *ctx, const char *b, const char *d, evbuffer_add_printf(r->req->buffer_out, " content=\"%s\"", a->content); if (a->type != NULL) evbuffer_add_printf(r->req->buffer_out, " type=\"%s\"", a->type); + if (a->id != NULL) + evbuffer_add_printf(r->req->buffer_out, " id=\"%s\"", a->id); if (a->src != NULL) { if (a->is_static) diff --git a/html.h b/html.h @@ -30,6 +30,7 @@ typedef struct { const char *title; const char *lang; const char *charset; + const char *id; bool closing_slash; bool is_static; } html_args_t; diff --git a/index.c b/index.c @@ -15,9 +15,33 @@ #include <index.h> #include <html.h> +#include <repository.h> bool index_route_handler(const mobley_t *ctx, server_req_t *r) { - html("h1", "Salut!"); + repository_t *repo; + + html_open("table") { + + html_open("tr") { + html("th", "Name"); + html("th", "Description"); + html("th", "Owner"); + html("th", "Last commit"); + } html_close("tr"); + + list_for_each_entry(repo, &ctx->repos.repos, node) + { + html_open("tr") { + html_open("td") { + html("a", repo->name, .href = repo->name); + } html_close("td"); + html("td", repo->desc); + html("td", repo->owner); + html("td", repo->path); + } html_close("tr"); + } + + } html_close("table"); return true; } diff --git a/main.c b/main.c @@ -82,6 +82,7 @@ static bool mobley_options(mobley_t *ctx) } INIT_LIST_HEAD(&ctx->conf.styles); + INIT_LIST_HEAD(&ctx->repos.repos); if (!config_read_file(GET_STR_ARG(options, OPT_CONFIG_PATH), ctx)) return false; @@ -100,6 +101,7 @@ static void sig_reload(int signal, short events, void *mobley) mobley_conf_dtr(ctx); INIT_LIST_HEAD(&ctx->conf.styles); + INIT_LIST_HEAD(&ctx->repos.repos); config_read_file(GET_STR_ARG(options, OPT_CONFIG_PATH), ctx); } diff --git a/mobley.h b/mobley.h @@ -22,6 +22,7 @@ # include <evhtp/log.h> # include <server.h> +# include <repository.h> typedef struct { char *ip; @@ -35,6 +36,11 @@ typedef struct { list_head_t styles; } conf; + struct { + char *repo_dir; + list_head_t repos; + } repos; + struct event_base *evbase; struct evhtp *htp; } mobley_t; @@ -46,7 +52,9 @@ static inline void mobley_conf_dtr(mobley_t *ctx) free(ctx->conf.logo); free(ctx->conf.root_desc); free(ctx->conf.title); + free(ctx->repos.repo_dir); string_array_free(&ctx->conf.styles); + repository_list_free(&ctx->repos.repos); } static inline void mobley_dtr(mobley_t *ctx) diff --git a/repository.h b/repository.h @@ -0,0 +1,70 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#ifndef REPOSITORY_H +# define REPOSITORY_H + +# include <list.h> +# include <stdlib.h> +# include <stdio.h> + +typedef struct { + char path[PATH_MAX]; + char *name; + char *desc; + char *owner; + list_head_t node; +} repository_t; + +/*static inline bool repository_init(repository_t *out, const char *name)*/ +//{ + //bool ret = false; + + //out->name = strdup(name); + //if (out->name == NULL) + //goto end; + + //ret = true; +//end: + //return ret; +/*}*/ + +static inline void repoitory_dtr(repository_t *ptr) +{ + if (ptr == NULL) + return ; + + free(ptr->name); +} + +static inline void repository_set_path(repository_t *out, const char *dir, const char *path) +{ + snprintf(out->path, sizeof(out->path), "%s/%s", path, dir); +} + +static inline void repository_list_free(list_head_t *head) +{ + repository_t *node, *tmp; + + list_for_each_entry_safe(node, tmp, head, node) + { + free(node->desc); + free(node->name); + free(node->owner); + free(node); + } +} + +#endif /* REPOSITORY_H */ diff --git a/style/main.css b/style/main.css @@ -79,3 +79,12 @@ a:hover { display: inline-block; padding: 0 0.4em; } + +#content { + padding: 5px; +} + +table { + width: 100%; + text-align: left; +} diff --git a/template.c b/template.c @@ -162,12 +162,14 @@ void template_begin(const mobley_t *ctx, server_req_t *r) template_menu(ctx, r); } html_close("div"); html_nd("hr", .closing_slash = true); + html_open("div", .id = "content"); } } } void template_end(const mobley_t *ctx, server_req_t *r) { + html_close("div"); html_close("body"); html_close("html"); }