/* * Copyright 2023, Vincent Douillet * * 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 #include #include #include #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(const 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(const 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 (optional) */ 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)) { page_template_free(tmpl); return NULL; } read_file(template_path, &tmpl->page_footer, &file_size); /* read page item (optional) */ 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)) { page_template_free(tmpl); return NULL; } read_file(template_path, &tmpl->page_item, &file_size); 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); }