summaryrefslogtreecommitdiff
path: root/server_file.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2014-07-13 01:15:01 +0200
committerReyk Floeter <reyk@esdenera.com>2014-07-13 01:15:01 +0200
commit6d196c9daa83925cc04f8019c1c0065317f6efdf (patch)
tree484726f0f6df8ff02e9cb1943ee35d8711417dd6 /server_file.c
parent9edde19e282ba13de068a4dc7e717152aaae77b8 (diff)
downloadhttpd-6d196c9daa83925cc04f8019c1c0065317f6efdf.tar.gz
httpd-6d196c9daa83925cc04f8019c1c0065317f6efdf.zip
Simple file serving
Diffstat (limited to 'server_file.c')
-rw-r--r--server_file.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/server_file.c b/server_file.c
new file mode 100644
index 0000000..00774c1
--- /dev/null
+++ b/server_file.c
@@ -0,0 +1,123 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/tree.h>
+#include <sys/hash.h>
+
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <err.h>
+#include <event.h>
+
+#include <openssl/ssl.h>
+
+#include "httpd.h"
+#include "http.h"
+
+int
+server_response(struct client *clt)
+{
+ struct http_descriptor *desc = clt->clt_desc;
+ struct server *srv = clt->clt_server;
+ struct kv *kv;
+ const char *errstr = NULL;
+ int fd = -1;
+ char path[MAXPATHLEN];
+ struct stat st;
+
+ if (desc->http_path == NULL)
+ goto fail;
+
+ /*
+ * XXX hardcode XXX
+ */
+ strlcpy(path, "/htdocs", sizeof(path));
+ if (desc->http_path[0] != '/')
+ strlcat(path, "/", sizeof(path));
+ strlcat(path, desc->http_path, sizeof(path));
+ if (desc->http_path[strlen(desc->http_path) - 1] == '/')
+ strlcat(path, "index.html", sizeof(path));
+
+ if (access(path, R_OK) == -1) {
+ switch (errno) {
+ case EACCES:
+ server_abort_http(clt, 403, path);
+ break;
+ case ENOENT:
+ server_abort_http(clt, 404, path);
+ break;
+ default:
+ server_abort_http(clt, 500, path);
+ break;
+ }
+ return (-1);
+ }
+
+ if ((fd = open(path, O_RDONLY)) == -1 || fstat(fd, &st) == -1)
+ goto fail;
+
+ kv_purge(&desc->http_headers);
+ kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME);
+ kv_add(&desc->http_headers, "Connection", "close");
+ if ((kv = kv_add(&desc->http_headers, "Content-Length", NULL)) != NULL)
+ kv_set(kv, "%ld", st.st_size);
+ kv_setkey(&desc->http_pathquery, "200");
+ kv_set(&desc->http_pathquery, "%s", server_httperror_byid(200));
+
+ if (server_writeresponse_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1 ||
+ server_writeheader_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
+ goto fail;
+
+ clt->clt_fd = fd;
+ clt->clt_file = bufferevent_new(clt->clt_fd, server_read,
+ server_write, server_error, clt);
+ if (clt->clt_file == NULL) {
+ errstr = "failed to allocate file buffer event";
+ goto fail;
+ }
+
+ bufferevent_settimeout(clt->clt_file,
+ srv->srv_conf.timeout.tv_sec, srv->srv_conf.timeout.tv_sec);
+ bufferevent_enable(clt->clt_file, EV_READ|EV_WRITE);
+
+ return (0);
+ fail:
+ if (errstr == NULL)
+ errstr = strerror(errno);
+ server_abort_http(clt, 500, errstr);
+ return (-1);
+}