summaryrefslogtreecommitdiffstats
path: root/src/blogc-runserver
diff options
context:
space:
mode:
Diffstat (limited to 'src/blogc-runserver')
-rw-r--r--src/blogc-runserver/httpd-utils.c105
-rw-r--r--src/blogc-runserver/httpd-utils.h19
-rw-r--r--src/blogc-runserver/httpd.c413
-rw-r--r--src/blogc-runserver/httpd.h15
-rw-r--r--src/blogc-runserver/main.c153
-rw-r--r--src/blogc-runserver/mime.c164
-rw-r--r--src/blogc-runserver/mime.h15
7 files changed, 0 insertions, 884 deletions
diff --git a/src/blogc-runserver/httpd-utils.c b/src/blogc-runserver/httpd-utils.c
deleted file mode 100644
index 9d374ae..0000000
--- a/src/blogc-runserver/httpd-utils.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include "../common/utils.h"
-#include "httpd-utils.h"
-
-
-char*
-br_readline(int socket)
-{
- bc_string_t *rv = bc_string_new();
- char buffer[READLINE_BUFFER_SIZE];
- ssize_t len;
- bool end = false;
-
- while ((len = read(socket, buffer, READLINE_BUFFER_SIZE)) > 0) {
- if (!end) {
- for (ssize_t i = 0; i < len; i++) {
- if (buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\0') {
- // we finished "recording", but still need to exhaust
- // request data.
- end = true;
- break;
- }
- bc_string_append_c(rv, buffer[i]);
- }
- }
- if (len < READLINE_BUFFER_SIZE) {
- break;
- }
- }
-
- return bc_string_free(rv, false);
-}
-
-
-int
-br_hextoi(const char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return -1;
-}
-
-
-char*
-br_urldecode(const char *str)
-{
- bc_string_t *rv = bc_string_new();
-
- for (size_t i = 0; i < strlen(str); i++) {
- switch (str[i]) {
- case '%':
- if (i + 2 < strlen(str)) {
- int p1 = br_hextoi(str[i + 1]) * 16;
- int p2 = br_hextoi(str[i + 2]);
- if (p1 >= 0 && p2 >= 0) {
- bc_string_append_c(rv, p1 + p2);
- i += 2;
- continue;
- }
- }
- bc_string_append_c(rv, '%');
- break;
- case '+':
- bc_string_append_c(rv, ' ');
- break;
- default:
- bc_string_append_c(rv, str[i]);
- }
- }
-
- return bc_string_free(rv, false);
-}
-
-
-const char*
-br_get_extension(const char *filename)
-{
- const char *ext = NULL;
- size_t i;
- for (i = strlen(filename); i > 0; i--) {
- if (filename[i] == '.') {
- ext = filename + i + 1;
- break;
- }
- if ((filename[i] == '/') || (filename[i] == '\\'))
- return NULL;
- }
- if (i == 0)
- return NULL;
- return ext;
-}
diff --git a/src/blogc-runserver/httpd-utils.h b/src/blogc-runserver/httpd-utils.h
deleted file mode 100644
index 06ad6e1..0000000
--- a/src/blogc-runserver/httpd-utils.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _HTTPD_UTILS_H
-#define _HTTPD_UTILS_H
-
-#define READLINE_BUFFER_SIZE 2048
-
-char* br_readline(int socket);
-int br_hextoi(const char c);
-char* br_urldecode(const char *str);
-const char* br_get_extension(const char *filename);
-
-#endif /* _HTTPD_UTILS_H */
diff --git a/src/blogc-runserver/httpd.c b/src/blogc-runserver/httpd.c
deleted file mode 100644
index fe98288..0000000
--- a/src/blogc-runserver/httpd.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <pthread.h>
-#include "../common/error.h"
-#include "../common/file.h"
-#include "../common/utils.h"
-#include "mime.h"
-#include "httpd-utils.h"
-
-#define LISTEN_BACKLOG 100
-
-typedef struct {
- pthread_t thread;
- bool initialized;
-} thread_data_t;
-
-typedef struct {
- size_t thread_id;
- int socket;
- char *ip;
- const char *docroot;
-} request_data_t;
-
-
-static void
-error(int socket, int status_code, const char *error)
-{
- char *str = bc_strdup_printf(
- "HTTP/1.0 %d %s\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: %zu\r\n"
- "Connection: close\r\n"
- "\r\n"
- "<h1>%s</h1>\n", status_code, error, strlen(error) + 10, error);
- size_t str_len = strlen(str);
- if (str_len != write(socket, str, str_len)) {
- fprintf(stderr, "warning: Failed to write full response header!\n");
- }
- free(str);
-}
-
-
-static void*
-handle_request(void *arg)
-{
- request_data_t *req = arg;
- size_t thread_id = req->thread_id;
- int client_socket = req->socket;
- char *ip = req->ip;
- const char *docroot = req->docroot;
- free(arg);
-
- char *conn_line = br_readline(client_socket);
- if (conn_line == NULL || conn_line[0] == '\0')
- goto point0;
-
- unsigned short status_code = 200;
-
- char **pieces = bc_str_split(conn_line, ' ', 3);
- if (bc_strv_length(pieces) != 3) {
- status_code = 400;
- error(client_socket, 400, "Bad Request");
- goto point1;
- }
-
- if (strcmp(pieces[0], "GET") != 0) {
- status_code = 405;
- error(client_socket, 405, "Method Not Allowed");
- goto point1;
- }
-
- char **pieces2 = bc_str_split(pieces[1], '?', 2);
- char *path = br_urldecode(pieces2[0]);
- bc_strv_free(pieces2);
-
- if (path == NULL) {
- status_code = 400;
- error(client_socket, 400, "Bad Request");
- goto point2;
- }
-
- char *abs_path = bc_strdup_printf("%s/%s", docroot, path);
- char *real_path = realpath(abs_path, NULL);
- free(abs_path);
-
- if (real_path == NULL) {
- if (errno == ENOENT) {
- status_code = 404;
- error(client_socket, 404, "Not Found");
- }
- else {
- status_code = 500;
- error(client_socket, 500, "Internal Server Error");
- }
- goto point2;
- }
-
- char *real_root = realpath(docroot, NULL);
- if (real_root == NULL) {
- status_code = 500;
- error(client_socket, 500, "Internal Server Error");
- goto point3;
- }
-
- if (0 != strncmp(real_root, real_path, strlen(real_root))) {
- status_code = 404;
- error(client_socket, 404, "Not Found");
- goto point4;
- }
-
- struct stat st;
- if (0 > stat(real_path, &st)) {
- status_code = 404;
- error(client_socket, 404, "Not Found");
- goto point4;
- }
-
- bool add_slash = false;
-
- if (S_ISDIR(st.st_mode)) {
- char *found = br_mime_guess_index(real_path);
-
- if (found == NULL) {
- status_code = 403;
- error(client_socket, 403, "Forbidden");
- goto point4;
- }
-
- size_t path_len = strlen(path);
- if (path_len > 0 && path[path_len - 1] != '/')
- add_slash = true;
-
- free(real_path);
- real_path = found;
- }
-
- if (0 != access(real_path, F_OK)) {
- status_code = 500;
- error(client_socket, 500, "Internal Server Error");
- goto point4;
- }
-
- if (add_slash) {
- // production webservers usually returns 301 in such cases, but 302 is
- // better for development/testing.
- char *tmp = bc_strdup_printf(
- "HTTP/1.0 302 Found\r\n"
- "Location: %s/\r\n"
- "Content-Length: 0\r\n"
- "Connection: close\r\n"
- "\r\n", path);
- status_code = 302;
- size_t tmp_len = strlen(tmp);
- if (tmp_len != write(client_socket, tmp, tmp_len)) {
- fprintf(stderr, "warning: Failed to write full response header!\n");
- }
- free(tmp);
- goto point4;
- }
-
- size_t len;
- bc_error_t *err = NULL;
- char* contents = bc_file_get_contents(real_path, false, &len, &err);
- if (err != NULL) {
- status_code = 500;
- error(client_socket, 500, "Internal Server Error");
- bc_error_free(err);
- goto point4;
- }
-
- char *out = bc_strdup_printf(
- "HTTP/1.0 200 OK\r\n"
- "Content-Type: %s\r\n"
- "Content-Length: %zu\r\n"
- "Connection: close\r\n"
- "\r\n", br_mime_guess_content_type(real_path), len);
- size_t out_len = strlen(out);
- if (out_len != write(client_socket, out, out_len)) {
- fprintf(stderr, "warning: Failed to write full response header!\n");
- }
- free(out);
-
- if (len != write(client_socket, contents, len)) {
- fprintf(stderr, "warning: Failed to write full response body!\n");
- }
- free(contents);
-
-point4:
- free(real_root);
-point3:
- free(real_path);
-point2:
- free(path);
-point1:
- fprintf(stderr, "[Thread-%zu] %s - - \"%s\" %d\n", thread_id + 1,
- ip, conn_line, status_code);
- free(conn_line);
- bc_strv_free(pieces);
-point0:
- free(ip);
- close(client_socket);
- return NULL;
-}
-
-
-static char*
-br_httpd_get_ip(int af, const struct sockaddr *addr)
-{
- char host[INET6_ADDRSTRLEN];
- if (af == AF_INET6) {
- struct sockaddr_in6 *a = (struct sockaddr_in6*) addr;
- inet_ntop(af, &(a->sin6_addr), host, INET6_ADDRSTRLEN);
- }
- else {
- struct sockaddr_in *a = (struct sockaddr_in*) addr;
- inet_ntop(af, &(a->sin_addr), host, INET6_ADDRSTRLEN);
- }
- return bc_strdup(host);
-}
-
-
-static uint16_t
-br_httpd_get_port(int af, const struct sockaddr *addr)
-{
- in_port_t port = 0;
- if (af == AF_INET6) {
- struct sockaddr_in6 *a = (struct sockaddr_in6*) addr;
- port = a->sin6_port;
- }
- else {
- struct sockaddr_in *a = (struct sockaddr_in*) addr;
- port = a->sin_port;
- }
- return ntohs(port);
-}
-
-
-int
-br_httpd_run(const char *host, const char *port, const char *docroot,
- size_t max_threads)
-{
- int err;
- struct addrinfo *result;
- struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_STREAM,
- .ai_flags = AI_PASSIVE,
- .ai_protocol = 0,
- .ai_canonname = NULL,
- .ai_addr = NULL,
- .ai_next = NULL,
- };
- if (0 != (err = getaddrinfo(host, port, &hints, &result))) {
- fprintf(stderr, "Failed to get host:port info: %s\n",
- gai_strerror(err));
- return 1;
- }
-
- thread_data_t threads[max_threads];
- for (size_t i = 0; i < max_threads; i++)
- threads[i].initialized = false;
-
- int rv = 0;
-
- struct addrinfo *rp;
- int server_socket = 0;
-
- int ai_family = 0;
- char *final_host = NULL;
- uint16_t final_port = 0;
-
- for (rp = result; rp != NULL; rp = rp->ai_next) {
- final_host = br_httpd_get_ip(rp->ai_family, rp->ai_addr);
- final_port = br_httpd_get_port(rp->ai_family, rp->ai_addr);
- server_socket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (server_socket == -1) {
- if (rp->ai_next == NULL) {
- fprintf(stderr, "Failed to open server socket (%s:%d): %s\n",
- final_host, final_port, strerror(errno));
- rv = 1;
- goto cleanup0;
- }
- continue;
- }
- int value = 1;
- if (0 > setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &value,
- sizeof(int)))
- {
- if (rp->ai_next == NULL) {
- fprintf(stderr, "Failed to set socket option (%s:%d): %s\n",
- final_host, final_port, strerror(errno));
- rv = 1;
- goto cleanup;
- }
- close(server_socket);
- continue;
- }
- if (0 == bind(server_socket, rp->ai_addr, rp->ai_addrlen)) {
- ai_family = rp->ai_family;
- break;
- }
- else {
- if (rp->ai_next == NULL) {
- fprintf(stderr, "Failed to bind to server socket (%s:%d): %s\n",
- final_host, final_port, strerror(errno));
- rv = 1;
- goto cleanup;
- }
- }
- free(final_host);
- close(server_socket);
- }
-
- if (-1 == listen(server_socket, LISTEN_BACKLOG)) {
- fprintf(stderr, "Failed to listen to server socket (%s:%d): %s\n",
- final_host, final_port, strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- fprintf(stderr, " * Running on http://");
- if (ai_family == AF_INET6)
- fprintf(stderr, "[%s]", final_host);
- else
- fprintf(stderr, "%s", final_host);
- if (final_port != 80)
- fprintf(stderr, ":%d", final_port);
- fprintf(stderr, "/ (max threads: %zu)\n"
- "\n"
- "WARNING!!! This is a development server, DO NOT RUN IT IN PRODUCTION!\n"
- "\n", max_threads);
-
- size_t current_thread = 0;
-
- while (1) {
- struct sockaddr_in6 addr6;
- struct sockaddr_in addr;
-
- socklen_t addrlen;
- struct sockaddr *client_addr = NULL;
-
- if (ai_family == AF_INET6) {
- addrlen = sizeof(addr6);
- client_addr = (struct sockaddr*) &addr6;
- }
- else {
- addrlen = sizeof(addr);
- client_addr = (struct sockaddr*) &addr;
- }
-
- int client_socket = accept(server_socket, client_addr, &addrlen);
- if (client_socket == -1) {
- fprintf(stderr, "Failed to accept connection: %s\n", strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- request_data_t *arg = malloc(sizeof(request_data_t));
- arg->thread_id = current_thread;
- arg->socket = client_socket;
- arg->ip = br_httpd_get_ip(ai_family, client_addr);
- arg->docroot = docroot;
-
- if (threads[current_thread].initialized) {
- if (pthread_join(threads[current_thread].thread, NULL) != 0) {
- fprintf(stderr, "Failed to join thread\n");
- free(arg->ip);
- free(arg);
- rv = 1;
- goto cleanup;
- }
- }
-
- if (pthread_create(&(threads[current_thread].thread), NULL,
- handle_request, arg) != 0)
- {
- fprintf(stderr, "Failed to create thread\n");
- rv = 1;
- goto cleanup;
- }
-
- threads[current_thread++].initialized = true;
-
- if (current_thread >= max_threads)
- current_thread = 0;
- }
-
-cleanup:
- close(server_socket);
-
-cleanup0:
- free(final_host);
- freeaddrinfo(result);
- return rv;
-}
diff --git a/src/blogc-runserver/httpd.h b/src/blogc-runserver/httpd.h
deleted file mode 100644
index b71a8d9..0000000
--- a/src/blogc-runserver/httpd.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _HTTPD_H
-#define _HTTPD_H
-
-int br_httpd_run(const char *host, const char *port, const char *docroot,
- size_t max_threads);
-
-#endif /* _HTTPD_H */
diff --git a/src/blogc-runserver/main.c b/src/blogc-runserver/main.c
deleted file mode 100644
index 1c5be29..0000000
--- a/src/blogc-runserver/main.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "../common/utils.h"
-#include "httpd.h"
-
-
-static void
-print_help(const char *default_host, const char *default_port)
-{
- printf(
- "usage:\n"
- " blogc-runserver [-h] [-v] [-t HOST] [-p PORT] [-m THREADS] DOCROOT\n"
- " - A simple HTTP server to test blogc websites.\n"
- "\n"
- "positional arguments:\n"
- " DOCROOT document root directory\n"
- "\n"
- "optional arguments:\n"
- " -h show this help message and exit\n"
- " -v show version and exit\n"
- " -t HOST set server listen address (default: %s)\n"
- " -p PORT set server listen port (default: %s)\n"
- " -m THREADS set maximum number of threads to spawn (default: 20)\n",
- default_host, default_port);
-}
-
-
-static void
-print_usage(void)
-{
- printf("usage: blogc-runserver [-h] [-v] [-t HOST] [-p PORT] [-m THREADS] DOCROOT\n");
-}
-
-
-int
-main(int argc, char **argv)
-{
- struct sigaction new_action;
- new_action.sa_handler = SIG_IGN;
- sigemptyset(&new_action.sa_mask);
- new_action.sa_flags = 0;
- sigaction(SIGPIPE, &new_action, NULL);
-
- int rv = 0;
- char *host = NULL;
- char *port = NULL;
- char *docroot = NULL;
- size_t max_threads = 20;
- char *ptr;
- char *endptr;
-
- char *tmp_host = getenv("BLOGC_RUNSERVER_DEFAULT_HOST");
- char *default_host = bc_strdup(tmp_host != NULL ? tmp_host : "127.0.0.1");
- char *tmp_port = getenv("BLOGC_RUNSERVER_DEFAULT_PORT");
- char *default_port = bc_strdup(tmp_port != NULL ? tmp_port : "8080");
-
- size_t args = 0;
-
- for (size_t i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch (argv[i][1]) {
- case 'h':
- print_help(default_host, default_port);
- goto cleanup;
- case 'v':
- printf("%s\n", PACKAGE_STRING);
- goto cleanup;
- case 't':
- if (argv[i][2] != '\0')
- host = bc_strdup(argv[i] + 2);
- else
- host = bc_strdup(argv[++i]);
- break;
- case 'p':
- if (argv[i][2] != '\0')
- port = bc_strdup(argv[i] + 2);
- else
- port = bc_strdup(argv[++i]);
- break;
- case 'm':
- if (argv[i][2] != '\0')
- ptr = argv[i] + 2;
- else
- ptr = argv[++i];
- max_threads = strtoul(ptr, &endptr, 10);
- if (*ptr != '\0' && *endptr != '\0')
- fprintf(stderr, "blogc-runserver: warning: invalid value "
- "for -m argument: %s. using %zu instead\n", ptr, max_threads);
- break;
- default:
- print_usage();
- fprintf(stderr, "blogc-runserver: error: invalid "
- "argument: -%c\n", argv[i][1]);
- rv = 1;
- goto cleanup;
- }
- }
- else {
- if (args > 0) {
- print_usage();
- fprintf(stderr, "blogc-runserver: error: only one positional "
- "argument allowed\n");
- rv = 1;
- goto cleanup;
- }
- args++;
- docroot = bc_strdup(argv[i]);
- }
- }
-
- if (docroot == NULL) {
- print_usage();
- fprintf(stderr, "blogc-runserver: error: document root directory "
- "required\n");
- rv = 1;
- goto cleanup;
- }
-
- if (max_threads <= 0 || max_threads > 1000) {
- print_usage();
- fprintf(stderr, "blogc-runserver: error: invalid value for -m. "
- "Must be integer > 0 and <= 1000\n");
- rv = 1;
- goto cleanup;
- }
-
- rv = br_httpd_run(
- host != NULL ? host : default_host,
- port != NULL ? port : default_port,
- docroot, max_threads);
-
-cleanup:
- free(default_host);
- free(default_port);
- free(host);
- free(port);
- free(docroot);
-
- return rv;
-}
diff --git a/src/blogc-runserver/mime.c b/src/blogc-runserver/mime.c
deleted file mode 100644
index 636c496..0000000
--- a/src/blogc-runserver/mime.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "../common/utils.h"
-#include "httpd-utils.h"
-
-
-// mime types with index should be in the begin of the list. first NULL
-// index aborts the lookup, for optimization
-static const struct content_type_map {
- const char *mimetype;
- const char *extension;
- const char *index;
-} content_types[] = {
-
- // with index
- {"text/html", "html", "index.html"},
- {"text/html", "htm", "index.htm"},
- {"text/html", "shtml", "index.shtml"},
- {"text/xml", "xml", "index.xml"},
- {"text/plain", "txt", "index.txt"},
- {"application/xhtml+xml", "xhtml", "index.xhtml"},
-
- // without index
- {"text/css", "css", NULL},
- {"image/gif", "gif", NULL},
- {"image/jpeg", "jpeg", NULL},
- {"image/jpeg", "jpg", NULL},
- {"application/javascript", "js", NULL},
- {"application/atom+xml", "atom", NULL},
- {"application/rss+xml", "rss", NULL},
- {"text/mathml", "mml", NULL},
- {"text/vnd.sun.j2me.app-descriptor", "jad", NULL},
- {"text/vnd.wap.wml", "wml", NULL},
- {"text/x-component", "htc", NULL},
- {"image/png", "png", NULL},
- {"image/tiff", "tif", NULL},
- {"image/tiff", "tiff", NULL},
- {"image/vnd.wap.wbmp", "wbmp", NULL},
- {"image/x-icon", "ico", NULL},
- {"image/x-jng", "jng", NULL},
- {"image/x-ms-bmp", "bmp", NULL},
- {"image/svg+xml", "svg", NULL},
- {"image/svg+xml", "svgz", NULL},
- {"image/webp", "webp", NULL},
- {"application/font-woff", "woff", NULL},
- {"application/java-archive", "jar", NULL},
- {"application/java-archive", "war", NULL},
- {"application/java-archive", "ear", NULL},
- {"application/json", "json", NULL},
- {"application/mac-binhex40", "hqx", NULL},
- {"application/msword", "doc", NULL},
- {"application/pdf", "pdf", NULL},
- {"application/postscript", "ps", NULL},
- {"application/postscript", "eps", NULL},
- {"application/postscript", "ai", NULL},
- {"application/rtf", "rtf", NULL},
- {"application/vnd.apple.mpegurl", "m3u8", NULL},
- {"application/vnd.ms-excel", "xls", NULL},
- {"application/vnd.ms-fontobject", "eot", NULL},
- {"application/vnd.ms-powerpoint", "ppt", NULL},
- {"application/vnd.wap.wmlc", "wmlc", NULL},
- {"application/vnd.google-earth.kml+xml", "kml", NULL},
- {"application/vnd.google-earth.kmz", "kmz", NULL},
- {"application/x-7z-compressed", "7z", NULL},
- {"application/x-cocoa", "cco", NULL},
- {"application/x-java-archive-diff", "jardiff", NULL},
- {"application/x-java-jnlp-file", "jnlp", NULL},
- {"application/x-makeself", "run", NULL},
- {"application/x-perl", "pl", NULL},
- {"application/x-perl", "pm", NULL},
- {"application/x-pilot", "prc", NULL},
- {"application/x-pilot", "pdb", NULL},
- {"application/x-rar-compressed", "rar", NULL},
- {"application/x-redhat-package-manager", "rpm", NULL},
- {"application/x-sea", "sea", NULL},
- {"application/x-shockwave-flash", "swf", NULL},
- {"application/x-stuffit", "sit", NULL},
- {"application/x-tcl", "tcl", NULL},
- {"application/x-tcl", "tk", NULL},
- {"application/x-x509-ca-cert", "der", NULL},
- {"application/x-x509-ca-cert", "pem", NULL},
- {"application/x-x509-ca-cert", "crt", NULL},
- {"application/x-xpinstall", "xpi", NULL},
- {"application/xspf+xml", "xspf", NULL},
- {"application/zip", "zip", NULL},
- {"application/octet-stream", "bin", NULL},
- {"application/octet-stream", "exe", NULL},
- {"application/octet-stream", "dll", NULL},
- {"application/octet-stream", "deb", NULL},
- {"application/octet-stream", "dmg", NULL},
- {"application/octet-stream", "iso", NULL},
- {"application/octet-stream", "img", NULL},
- {"application/octet-stream", "msi", NULL},
- {"application/octet-stream", "msp", NULL},
- {"application/octet-stream", "msm", NULL},
- {"application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx", NULL},
- {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx", NULL},
- {"application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx", NULL},
- {"audio/midi", "mid", NULL},
- {"audio/midi", "midi", NULL},
- {"audio/midi", "kar", NULL},
- {"audio/mpeg", "mp3", NULL},
- {"audio/ogg", "ogg", NULL},
- {"audio/x-m4a", "m4a", NULL},
- {"audio/x-realaudio", "ra", NULL},
- {"video/3gpp", "3gpp", NULL},
- {"video/3gpp", "3gp", NULL},
- {"video/mp2t", "ts", NULL},
- {"video/mp4", "mp4", NULL},
- {"video/mpeg", "mpeg", NULL},
- {"video/mpeg", "mpg", NULL},
- {"video/quicktime", "mov", NULL},
- {"video/webm", "webm", NULL},
- {"video/x-flv", "flv", NULL},
- {"video/x-m4v", "m4v", NULL},
- {"video/x-mng", "mng", NULL},
- {"video/x-ms-asf", "asx", NULL},
- {"video/x-ms-asf", "asf", NULL},
- {"video/x-ms-wmv", "wmv", NULL},
- {"video/x-msvideo", "avi", NULL},
- {NULL, NULL, NULL}
-};
-
-
-const char*
-br_mime_guess_content_type(const char *filename)
-{
- const char *extension = br_get_extension(filename);
- if (extension == NULL)
- goto default_type;
- for (size_t i = 0; content_types[i].extension != NULL; i++) {
- if (0 == strcmp(content_types[i].extension, extension)) {
- return content_types[i].mimetype;
- }
- }
-
-default_type:
- return "application/octet-stream";
-}
-
-
-char*
-br_mime_guess_index(const char *path)
-{
- char *found = NULL;
- for (size_t i = 0; content_types[i].index != NULL; i++) {
- char *f = bc_strdup_printf("%s/%s", path, content_types[i].index);
- if (0 == access(f, F_OK)) {
- found = f;
- break;
- }
- free(f);
- }
- return found;
-}
diff --git a/src/blogc-runserver/mime.h b/src/blogc-runserver/mime.h
deleted file mode 100644
index b9fb013..0000000
--- a/src/blogc-runserver/mime.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MIME_H
-#define _MIME_H
-
-const char* br_mime_guess_content_type(const char *filename);
-char* br_mime_guess_index(const char *path);
-
-#endif /* _MIME_H */