aboutsummaryrefslogtreecommitdiff
path: root/mime.c
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-01-18 18:18:57 +0000
committerOmar Polo <op@omarpolo.com>2021-01-18 18:18:57 +0000
commit0fbe79b33c1d16b0611851e2019558ce8888a02e (patch)
treedf6bac6c8325f8d62862949129010683186bd784 /mime.c
parent132cae8c6f2c5866ff84058ac9461ca95d63ed8b (diff)
improve mime handling
we still have an hardcoded list, but this implements the API needed to modify the mappings.
Diffstat (limited to 'mime.c')
-rw-r--r--mime.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/mime.c b/mime.c
new file mode 100644
index 0000000..cb2f28a
--- /dev/null
+++ b/mime.c
@@ -0,0 +1,116 @@
+/*
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}