Blob
Date:
Fri Apr 8 13:44:49 2022
UTC
Message:
allow add_mime to fail
add_mime nows allocate dinamically copies of the passed strings, so
that we can actually free what we parse from the config file.
This matters a lot especially with lengthy `types' block: strings that
reach the internal mapping are never free'd, so every manual addition
is leaked.
/** Copyright (c) 2021 Omar Polo <op@omarpolo.com>** Permission to use, copy, modify, and distribute this software for any* purpose with or without fee is hereby granted, provided that the above* copyright notice and this permission notice appear in all copies.** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.*/#include "gmid.h"#include <errno.h>#include <stdlib.h>#include <string.h>voidinit_mime(struct mime *mime){mime->len = 0;mime->cap = 16;mime->t = calloc(mime->cap, sizeof(struct etm));if (mime->t == NULL)fatal("calloc: %s", strerror(errno));}/* register mime for the given extension */intadd_mime(struct mime *mime, const char *mt, const char *ext){char *mimetype, *extension;struct etm *t;size_t newcap;if (mime->len == mime->cap) {newcap = mime->cap * 1.5;t = recallocarray(mime->t, mime->cap, newcap,sizeof(struct etm));if (t == NULL)return -1;mime->t = t;mime->cap = newcap;}if ((mimetype = strdup(mt)) == NULL)return -1;if ((extension = strdup(ext)) == NULL) {free(mimetype);return -1;}mime->t[mime->len].mime = mimetype;mime->t[mime->len].ext = extension;mime->len++;return 0;}/* load a default set of common mime-extension associations */intload_default_mime(struct mime *mime){const struct mapping {const char *mime;const char *ext;} m[] = {{"application/pdf", "pdf"},{"image/gif", "gif"},{"image/jpeg", "jpg"},{"image/jpeg", "jpeg"},{"image/png", "png"},{"image/svg+xml", "svg"},{"text/gemini", "gemini"},{"text/gemini", "gmi"},{"text/markdown", "markdown"},{"text/markdown", "md"},{"text/plain", "txt"},{"text/x-patch", "diff"},{"text/x-patch", "patch"},{"text/xml", "xml"},{NULL, NULL}}, *i;for (i = m; i->mime != NULL; ++i) {if (add_mime(mime, i->mime, i->ext) == -1)return -1;}return 0;}static const char *path_ext(const char *path){const char *end;end = path + strlen(path)-1;for (; end != path; --end) {if (*end == '.')return end+1;if (*end == '/')break;}return NULL;}const char *mime(struct vhost *host, const char *path){const char *def, *ext;struct etm *t;def = vhost_default_mime(host, path);if ((ext = path_ext(path)) == NULL)return def;for (t = conf.mime.t; t->mime != NULL; ++t)if (!strcmp(ext, t->ext))return t->mime;return def;}voidfree_mime(struct mime *m){struct etm *t;for (t = m->t; t->mime != NULL; ++t) {free(t->mime);free(t->ext);}free(m->t);}
Omar Polo