summaryrefslogtreecommitdiff
path: root/template.c
diff options
context:
space:
mode:
Diffstat (limited to 'template.c')
-rw-r--r--template.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/template.c b/template.c
new file mode 100644
index 0000000..f6a55b2
--- /dev/null
+++ b/template.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2023, Vincent Douillet <vincent@vdouillet.fr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "template.h"
+#include "url.h"
+
+/*
+ * Reads the file denoted by path into a newly allocated output buffer. Returns
+ * 0 for success, -1 for error. The size_t is the size of output buffer (only
+ * to be used in case of success).
+ */
+static int
+read_file(char *path, char **output, size_t * read_size)
+{
+ long file_size;
+ FILE *fp;
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ return -1;
+
+ /* get file size */
+ if (fseek(fp, 0L, SEEK_END) != 0)
+ return -1;
+
+ file_size = ftell(fp);
+ if (file_size < 0)
+ return -1;
+
+ /* rewind to file start */
+ if (fseek(fp, 0L, SEEK_SET) != 0)
+ return -1;
+
+ /* create output buffer */
+ *output = malloc(sizeof(char) * (file_size + 1));
+ if (*output == NULL)
+ return -1;
+
+ /* read the file */
+ *read_size = fread(*output, sizeof(char), file_size, fp);
+ if (*read_size == 0 || ferror(fp) != 0) {
+ free(*output);
+ return -1;
+ }
+ /* enforce string termination */
+ (*output)[*read_size] = '\0';
+
+ return 0;
+}
+
+struct page_template *
+page_template_new(char *page)
+{
+ struct page_template *tmpl;
+ char template_path[PATH_MAX];
+ size_t path_size;
+ size_t file_size;
+
+ tmpl = (struct page_template *) calloc(1, sizeof(struct page_template));
+ if (tmpl == NULL)
+ return NULL;
+
+ /* read global header */
+ path_size = snprintf(template_path, sizeof(template_path), "%s/%s",
+ TEMPLATE_DIR, "head.html");
+ if (path_size < 0 || path_size >= sizeof(template_path) ||
+ read_file(template_path, &tmpl->header, &file_size) < 0) {
+ page_template_free(tmpl);
+ return NULL;
+ }
+ /* read global footer */
+ path_size = snprintf(template_path, sizeof(template_path), "%s/%s",
+ TEMPLATE_DIR, "foot.html");
+ if (path_size < 0 || path_size >= sizeof(template_path) ||
+ read_file(template_path, &tmpl->footer, &file_size) < 0) {
+ page_template_free(tmpl);
+ return NULL;
+ }
+ /* read page header */
+ path_size = snprintf(template_path, sizeof(template_path), "%s/%s_%s",
+ TEMPLATE_DIR, page, "head.html");
+ if (path_size < 0 || path_size >= sizeof(template_path) ||
+ read_file(template_path, &tmpl->page_header, &file_size) < 0) {
+ page_template_free(tmpl);
+ return NULL;
+ }
+ /* read page footer */
+ path_size = snprintf(template_path, sizeof(template_path), "%s/%s_%s",
+ TEMPLATE_DIR, page, "foot.html");
+ if (path_size < 0 || path_size >= sizeof(template_path) ||
+ read_file(template_path, &tmpl->page_footer, &file_size) < 0) {
+ page_template_free(tmpl);
+ return NULL;
+ }
+ /* read page item */
+ path_size = snprintf(template_path, sizeof(template_path), "%s/%s_%s",
+ TEMPLATE_DIR, page, "item.html");
+ if (path_size < 0 || path_size >= sizeof(template_path) ||
+ read_file(template_path, &tmpl->page_item, &file_size) < 0) {
+ page_template_free(tmpl);
+ return NULL;
+ }
+ return tmpl;
+}
+
+void
+page_template_free(struct page_template * tmpl)
+{
+ if (tmpl == NULL)
+ return;
+
+ if (tmpl->header != NULL)
+ free(tmpl->header);
+ if (tmpl->footer != NULL)
+ free(tmpl->footer);
+ if (tmpl->page_header != NULL)
+ free(tmpl->page_header);
+ if (tmpl->page_footer != NULL)
+ free(tmpl->page_footer);
+ if (tmpl->page_item != NULL)
+ free(tmpl->page_item);
+
+ free(tmpl);
+}