From 65e25154a92ea47384bc540c129288ca9dad96cb Mon Sep 17 00:00:00 2001
From: Vegard Storheil Eriksen <zyp@jvnv.net>
Date: Mon, 10 Jan 2011 13:02:25 +0100
Subject: Added HTTP::Static for serving static content.

---
 http_connection.cpp |  1 +
 http_static.cpp     | 33 +++++++++++++++++++++++++++++++++
 http_static.h       | 26 ++++++++++++++++++++++++++
 main.cpp            |  6 ++++++
 4 files changed, 66 insertions(+)
 create mode 100644 http_static.cpp
 create mode 100644 http_static.h

diff --git a/http_connection.cpp b/http_connection.cpp
index f04dc28..041cd05 100644
--- a/http_connection.cpp
+++ b/http_connection.cpp
@@ -10,6 +10,7 @@ namespace response_map_init {
 	const P m[] = {
 		P(200, "OK"),
 		P(400, "Bad Request"),
+		P(403, "Forbidden"),
 		P(404, "Not Found"),
 		P(500, "Internal Server Error"),
 		P(501, "Not Implemented")
diff --git a/http_static.cpp b/http_static.cpp
new file mode 100644
index 0000000..7f56744
--- /dev/null
+++ b/http_static.cpp
@@ -0,0 +1,33 @@
+#include "http_static.h"
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/format.hpp>
+
+HTTP::Static::Static(fs::path directory, std::string index) : directory_(directory), index_(index) {
+	
+}
+
+void HTTP::Static::operator()(Connection::p connection) {
+	fs::path path = directory_;
+	
+	if(connection->path.size()) {
+		for(Connection::PathList::iterator it = connection->path.begin(); it != connection->path.end(); it++) {
+			path /= *it;
+		}
+	} else {
+		path /= index_;
+	}
+	
+	if(fs::is_regular_file(path)) {
+		fs::ifstream is(path, std::ios::in | std::ios::binary);
+		is.seekg(0, std::ios::end);
+		connection->add_header("content-length", boost::str(boost::format("%d") % is.tellg()));
+		is.seekg(0, std::ios::beg);
+		
+		connection->send_data(is);
+	} else if(fs::exists(path)) {
+		connection->send_error(403);
+	} else {
+		connection->send_error(404);
+	}
+}
diff --git a/http_static.h b/http_static.h
new file mode 100644
index 0000000..f8d2bec
--- /dev/null
+++ b/http_static.h
@@ -0,0 +1,26 @@
+#ifndef HTTP_STATIC_H
+#define HTTP_STATIC_H
+
+#include "http_connection.h"
+
+#include <boost/filesystem.hpp>
+
+namespace fs = boost::filesystem;
+
+namespace HTTP {
+	//! HTTP Handler serving static files from a directory.
+	class Static {
+		private:
+			fs::path directory_;
+			std::string index_;
+		
+		public:
+			//! Construct Static-handler.
+			Static(fs::path directory, std::string index = "index.html");
+			
+			//! Handle request.
+			void operator()(Connection::p connection);
+	};
+};
+
+#endif
diff --git a/main.cpp b/main.cpp
index 3c22d24..ec5c0fe 100644
--- a/main.cpp
+++ b/main.cpp
@@ -5,6 +5,8 @@
 #include "httpd.h"
 #include "telnetd.h"
 
+#include "http_static.h"
+
 #include <iostream>
 #include <vector>
 
@@ -34,6 +36,10 @@ int main(int argc, char **argv) {
 		
 		httpd.add_handler("files", &foo_handler);
 		
+		HTTP::Static static_files("static");
+		httpd.add_handler("files", static_files);
+		httpd.add_handler("", static_files);
+		
 		telnet::Server telnetd(io_service, tcp::endpoint(tcp::v6(), config::vm["audist.telnetd_port"].as<int>()));
 		
 		std::size_t num_threads = config::vm["audist.threads"].as<std::size_t>();
-- 
cgit v1.2.3