commit 0fbe79b33c1d16b0611851e2019558ce8888a02e from: Omar Polo date: Mon Jan 18 18:18:57 2021 UTC improve mime handling we still have an hardcoded list, but this implements the API needed to modify the mappings. commit - 132cae8c6f2c5866ff84058ac9461ca95d63ed8b commit + 0fbe79b33c1d16b0611851e2019558ce8888a02e blob - 10a141fc7c4652916ed4bbf9b46a753283a39bcd blob + cf88eec449912846c38c3bf47c817277937f4c4b --- Makefile +++ Makefile @@ -19,7 +19,9 @@ lex.yy.c: lex.l y.tab.c y.tab.c: parse.y ${YACC} -b y -d parse.y -OBJS = gmid.o iri.o utf8.o lex.yy.o y.tab.o ex.o server.o sandbox.o +SRCS = gmid.c iri.c utf8.c ex.c server.c sandbox.c mime.c +OBJS = ${SRCS:.c=.o} lex.yy.o y.tab.o + gmid: ${OBJS} ${CC} ${OBJS} -o gmid ${LDFLAGS} @@ -29,8 +31,8 @@ static: ${OBJS} -o gmid strip gmid -TAGS: gmid.c iri.c utf8.c ex.c server.c sandbox.c - -etags gmid.c iri.c utf8.c ex.c server.c sandbox.c || true +TAGS: ${SRCS} + -etags ${SRCS} || true clean: rm -f *.o lex.yy.c y.tab.c y.tab.h y.output gmid iri_test blob - 0645dbb9ae6b1b14309ffc0ce2ac483f9596ca76 blob + 95981c51cac77d80586ed0a6310b3780a5228695 --- gmid.c +++ gmid.c @@ -32,28 +32,6 @@ int exfd; struct conf conf; -struct etm { /* file extension to mime */ - const char *mime; - const char *ext; -} filetypes[] = { - {"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/xml", "xml"}, - - {NULL, NULL} -}; - void fatal(const char *fmt, ...) { @@ -140,38 +118,6 @@ filesize(int fd) if (lseek(fd, 0, SEEK_SET) == -1) return -1; return len; -} - -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(const char *path) -{ - const char *ext, *def = "application/octet-stream"; - struct etm *t; - - if ((ext = path_ext(path)) == NULL) - return def; - - for (t = filetypes; t->mime != NULL; ++t) - if (!strcmp(ext, t->ext)) - return t->mime; - - return def; } char * @@ -303,6 +249,8 @@ listener_main() int sock4, sock6; struct tls *ctx = NULL; struct tls_config *tlsconf; + + load_default_mime(); if ((tlsconf = tls_config_new()) == NULL) fatal("tls_config_new"); @@ -362,6 +310,8 @@ main(int argc, char **argv) conf.ipv6 = 0; conf.protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3; + init_mime(); + while ((ch = getopt(argc, argv, "6C:c:d:fhK:np:x:")) != -1) { switch (ch) { case '6': blob - 39bf27ee95a1d47e668c03d704cf299fdb5974a9 blob + 66563671a9a356f1a003553b406e077fad6a243b --- gmid.h +++ gmid.h @@ -132,8 +132,6 @@ void logs(int, struct client*, const char*, ...); void sig_handler(int); int starts_with(const char*, const char*); ssize_t filesize(int); -const char *path_ext(const char*); -const char *mime(const char*); char *absolutify_path(const char*); void yyerror(const char*); int parse_portno(const char*); @@ -149,6 +147,12 @@ extern int yylineno; extern int yyparse(void); extern int yylex(void); +/* mime.c */ +void init_mime(void); +void add_mime(const char*, const char*); +void load_default_mime(void); +const char *mime(const char*); + /* server.c */ int check_path(struct client*, const char*, int*); int open_file(char*, char*, struct pollfd*, struct client*); blob - /dev/null blob + cb2f28a0aca3a68bf5bb577ec0a74f86917effbb (mode 644) --- /dev/null +++ mime.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Omar Polo + * + * 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 +#include +#include + +#include "gmid.h" + +struct etm { /* extension to mime */ + const char *mime; + const char *ext; +}; + +struct mimes { + struct etm *t; + size_t len; + size_t cap; +}; + +struct mimes mimes; + +void +init_mime(void) +{ + mimes.len = 0; + mimes.cap = 2; + + if ((mimes.t = calloc(mimes.cap, sizeof(struct etm))) == NULL) + fatal("calloc: %s", strerror(errno)); +} + +/* register mime for the given extension */ +void +add_mime(const char *mime, const char *ext) +{ + if (mimes.len == mimes.cap) { + mimes.cap *= 1.5; + mimes.t = realloc(mimes.t, mimes.cap * sizeof(struct etm)); + if (mimes.t == NULL) + fatal("realloc: %s", strerror(errno)); + } + + mimes.t[mimes.len].mime = mime; + mimes.t[mimes.len].ext = ext; + mimes.len++; +} + +/* load a default set of common mime-extension associations */ +void +load_default_mime() +{ + struct etm *i, 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/xml", "xml"}, + {NULL, NULL} + }; + + for (i = m; i->mime != NULL; ++i) + add_mime(i->mime, i->ext); +} + +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(const char *path) +{ + const char *ext, *def = "application/octet-stream"; + struct etm *t; + + if ((ext = path_ext(path)) == NULL) + return def; + + for (t = mimes.t; t->mime != NULL; ++t) + if (!strcmp(ext, t->ext)) + return t->mime; + + return def; +}