about summary refs log tree commit diff
path: root/templates
diff options
context:
space:
mode:
authorsternenseemann <sternenseemann@systemli.org>2020-08-07 23:58:50 +0200
committersternenseemann <sternenseemann@systemli.org>2020-08-08 02:16:15 +0200
commite5cd70a596f797ddff973861a5b72d2af1dec1b9 (patch)
tree95f8d2f93e79e8b1a67475897cff5a10f8f4225a /templates
parent351d951158992488df4a679a4a882468b0b21793 (diff)
feat(treewide): major rework
Unfortunately, I got a bit carried away after realizing that the initial
change would be a breaking change anyways, so I am now left with a huge
diff which can't be really split up. Please excuse this.

The changes are as follows:

* Rename blogpost → entry (breaking): make_blogpost → make_entry,
  blog_post → blog_entry etc.
* Rename blogdefs.h → core.h (breaking)
* Split functions from main.c into cgiutil and entry
* entry / make_entry:
  * Use modification time instead of time in filename (breaking)
  * Rename timestamp → time (breaking)
  * Add field title (currently basename, breaking)
  * Add field text and text_size which can be use to store the
    contents of the associated file using mmap (fields default to
    NULL and -1 respectively, breaking)
  * Do PATH_INFO resolving and on disk path building in make_entry
    instead of in blog_index / blog_rss / blog_entry
* entry_get_text: add function to mmap an entry's file into the
  structure
* free_entry: also unmap file if present
* make_index: Add function to build an array of entries reverse sorted
  by time
* blog_index / blog_rss:
  * use make_index instead of scandir and make_blogpost_from_dirent
  * (blog_rss) use entry_get_text to pass the template the text of
    the entry.
* template:
  * template_post_index_entry → template_index_entry (breaking)
  * template_post_single_entry → template_single_entry (breaking)
  * replace template_error_404() with generic template_error(status)
* templates/simple.c:
  * Use xml library instead of printf
  * Use entry.text instead of opening the file in the template
  * include CSS if BLOG_CSS is set in config.h
* document internal and public interfaces using doxygen
* build process:
  * build object files individually
  * build process configuration in config.mk (breaking)
  * support templates in arbitrary locations
  * build default config.h if it's missing
  * add install phase
  * Rename target to sternenblog.cgi (breaking)
Diffstat (limited to 'templates')
-rw-r--r--templates/simple.c203
1 files changed, 159 insertions, 44 deletions
diff --git a/templates/simple.c b/templates/simple.c
index eec43cc..8e1037e 100644
--- a/templates/simple.c
+++ b/templates/simple.c
@@ -1,69 +1,184 @@
+#define _POSIX_C_SOURCE 200809L
 #include <stdio.h>
 #include <stdlib.h>
-#include "../template.h"
-#include "../config.h"
+#include <string.h>
+#include <time.h>
 
-void template_header(void) {
-    printf("<!doctype html>\n"
-           "<html>\n"
-           "<head>\n"
-           "\t<title>%s</title>\n"
-           "\t<meta charset=\"utf-8\"/>\n"
-           "\t<style type=\"text/css\">\n"
-           "\ta:link, a:visited{\n"
-           "\tcolor:blue;\n"
-           "\t}</style>\n"
-           "</head>\n"
-           "<body><h1>%s</h1>\n", BLOG_TITLE, BLOG_TITLE);
-}
+#include <core.h>
+#include <template.h>
+#include <config.h>
+#include <cgiutil.h>
+#include <xml.h>
 
-void template_footer(void) {
-    printf("\t<footer><a href=\"%s/rss.xml\">RSS feed</a></footer>\n"
-            "</body></html>", getenv("SCRIPT_NAME"));
+extern long timezone;
+
+static struct xml_context ctx;
+
+int make_link(char *buf, size_t size, char *abs_path) {
+    // TODO pass to template somehow?
+    char *script_name = getenv("SCRIPT_NAME");
+
+    if(script_name == NULL || buf == NULL || abs_path == NULL) {
+        return -1;
+    }
+
+    size_t script_name_len = strlen(script_name);
+    size_t abs_path_len = strlen(abs_path);
+
+    size_t min_buf_len = script_name_len + abs_path_len + 1;
+
+    if(min_buf_len > size) {
+        return -1;
+    }
+
+    if(script_name_len > 0) {
+        memcpy(buf, script_name, script_name_len);
+    }
+    if(abs_path_len > 0) {
+        memcpy(buf + script_name_len, abs_path, abs_path_len);
+    }
+
+    buf[script_name_len + abs_path_len] = '\0';
+
+    return min_buf_len;
 }
 
-void template_post_single_entry(struct blogpost post) {
-    FILE *fp = fopen(post.path, "r");
-    char c;
+void output_entry_time(struct xml_context *ctx, struct entry entry) {
+    tzset();
+    char *format = timezone == 0 ? "%Y-%m-%d %TZ" : "%Y-%m-%d %T%z";
+
+    char strtime[32];
+    struct tm *local = localtime(&entry.time);
 
-    if(fp == NULL) {
-        template_error_404();
-        exit(EXIT_SUCCESS);
-        /* TODO: does CGI still work correctly if we exit
-         * with EXIT_FAILURE? */
+    if(strftime(strtime, sizeof strtime, format, local) > 0) {
+        xml_open_tag_attrs(ctx, "time", 1, "datetime", strtime);
+        xml_raw(ctx, strtime);
+        xml_close_tag(ctx, "time");
     }
+}
+
+void template_header(void) {
+    new_xml_context(&ctx);
+    ctx.warn = stderr;
+    ctx.closing_slash = 0;
+
+    xml_raw(&ctx, "<!doctype html>");
+    xml_open_tag_attrs(&ctx, "html", 1, "lang", "en");
+
+    xml_open_tag(&ctx, "head");
 
-    printf("<article>\n");
+    xml_empty_tag(&ctx, "meta", 1, "charset", "utf-8");
 
-    while((c = fgetc(fp)) != EOF) {
-        printf("%c", c);
+   #ifdef BLOG_CSS
+    xml_empty_tag(&ctx, "link", 3,
+                  "rel", "stylesheet",
+                  "type", "text/css",
+                  "href", BLOG_CSS);
+   #endif
+
+    xml_open_tag(&ctx, "title");
+    xml_raw(&ctx, BLOG_TITLE);
+    xml_close_tag(&ctx, "title");
+
+    xml_close_tag(&ctx, "head");
+
+    xml_open_tag(&ctx, "body");
+    xml_open_tag(&ctx, "header");
+    xml_open_tag(&ctx, "h1");
+    xml_raw(&ctx, BLOG_TITLE);
+    xml_close_including(&ctx, "header");
+
+    xml_open_tag(&ctx, "main");
+}
+
+void template_footer(void) {
+    xml_close_tag(&ctx, "main");
+
+    xml_open_tag(&ctx, "footer");
+
+    char rss_link[256];
+    if(make_link(rss_link, sizeof rss_link, "/rss.xml") != -1) {
+        xml_open_tag_attrs(&ctx, "a", 1, "href", rss_link);
+        xml_raw(&ctx, "RSS Feed");
+        xml_close_tag(&ctx, "a");
     }
 
-    printf("<p><a href=\"%s\">Back</a></p></article>\n", getenv("SCRIPT_NAME"));
+    xml_close_all(&ctx);
 
-    fclose(fp);
+    del_xml_context(&ctx);
 }
 
-void template_post_index_entry(struct blogpost post) {
-    FILE *fp = fopen(post.path, "r");
-    char c;
+void template_single_entry(struct entry entry) {
+    xml_open_tag(&ctx, "article");
 
-    if(fp == NULL) {
-        fprintf(stderr, "No such file or directory: %s\n", post.path);
-        exit(EXIT_FAILURE);
+    if(entry.text_size > 0) {
+        xml_open_tag_attrs(&ctx, "div", 1, "class", "content");
+        xml_raw(&ctx, entry.text);
+        xml_close_tag(&ctx, "div");
     }
 
-    printf("<article>\n");
+    char *script_name = getenv("SCRIPT_NAME");
+
+    xml_open_tag_attrs(&ctx, "div", 1, "class", "meta");
+    xml_open_tag(&ctx, "ul");
+
+    // time of publishing
+    xml_open_tag(&ctx, "li");
+    output_entry_time(&ctx, entry);
+    xml_close_tag(&ctx, "li");
 
-    while((c = fgetc(fp)) != EOF) {
-        printf("%c", c);
+    // link back to index
+    xml_open_tag(&ctx, "li");
+    xml_open_tag_attrs(&ctx, "a", 1, "href", script_name);
+    xml_raw(&ctx, "Back");
+    xml_close_tag(&ctx, "a");
+    xml_close_tag(&ctx, "li");
+
+    xml_close_including(&ctx, "article");
+}
+
+void template_index_entry(struct entry entry) {
+    // TODO time?
+    xml_open_tag_attrs(&ctx, "article", 1, "id", entry.title);
+    if(entry.text_size > 0) {
+        xml_open_tag_attrs(&ctx, "div", 1, "class", "content index");
+        xml_raw(&ctx, entry.text);
+        xml_close_tag(&ctx, "div");
     }
 
-    printf("<p><a href=\"%s\">Permalink</a></p></article>\n", post.link);
+    xml_open_tag_attrs(&ctx, "div", 1, "class", "meta index");
+    xml_open_tag(&ctx, "p");
+    xml_open_tag_attrs(&ctx, "a", 1, "href", entry.link);
+    xml_raw(&ctx, "Permalink");
 
-    fclose(fp);
+    xml_close_including(&ctx, "article");
 }
 
-void template_error_404(void) {
-    printf("<article><h2>Error 404</h2><p>This page does not exist. I am so sorry</p></article>");
+void template_error(int status) {
+    xml_open_tag_attrs(&ctx, "div", 1, "class", "error-page");
+    xml_open_tag(&ctx, "h2");
+    xml_raw(&ctx, "An error occured while handling your request");
+    xml_close_tag(&ctx, "h2");
+
+    xml_open_tag(&ctx, "p");
+
+    if(status == 500) {
+        xml_raw(&ctx, "Something is wrong with this application and/or its server (error 500).");
+    } else if(status == 404) {
+        xml_raw(&ctx, "What you requested doesn't exist (error 404).");
+    } else {
+       xml_raw(&ctx, "The error encoutered is: ");
+       xml_raw(&ctx, http_status_line(status));
+    }
+
+    xml_close_tag(&ctx, "p");
+
+    char *script_name = getenv("SCRIPT_NAME");
+
+    xml_open_tag(&ctx, "nav");
+    xml_open_tag(&ctx, "p");
+    xml_open_tag_attrs(&ctx, "a", 1, "href", script_name);
+    xml_raw(&ctx, "Back");
+
+    xml_close_including(&ctx, "div");
 }