2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
10 local httpserver = require "net.httpserver";
11 local lfs = require "lfs";
14 local t_concat = table.concat;
15 local stat = lfs.attributes;
17 local http_base = config.get("*", "core", "http_path") or "www_files";
19 local response_400 = { status = "400 Bad Request", body = "<h1>Bad Request</h1>Sorry, we didn't understand your request :(" };
20 local response_403 = { status = "403 Forbidden", body = "<h1>Forbidden</h1>You don't have permission to view the contents of this directory :(" };
21 local response_404 = { status = "404 Not Found", body = "<h1>Page Not Found</h1>Sorry, we couldn't find what you were looking for :(" };
23 -- TODO: Should we read this from /etc/mime.types if it exists? (startup time...?)
29 txt = "text/plain; charset=utf-8";
30 js = "text/javascript";
34 local function preprocess_path(path)
35 if path:sub(1,1) ~= "/" then
39 for component in path:gmatch("([^/]+)/") do
40 if component == ".." then
42 elseif component ~= "." then
52 function serve_file(path)
53 local full_path = http_base..path;
54 if stat(full_path, "mode") == "directory" then
55 if stat(full_path.."/index.html", "mode") == "file" then
56 return serve_file(path.."/index.html");
60 local f, err = open(full_path, "rb");
61 if not f then return response_404; end
62 local data = f:read("*a");
67 local ext = path:match("%.([^.]*)$");
68 local mime = mime_map[ext]; -- Content-Type should be nil when not known
70 headers = { ["Content-Type"] = mime; };
75 local function handle_file_request(method, body, request)
76 local path = preprocess_path(request.url.path);
77 if not path then return response_400; end
78 path = path:gsub("^/[^/]+", ""); -- Strip /files/
79 return serve_file(path);
82 local function handle_default_request(method, body, request)
83 local path = preprocess_path(request.url.path);
84 if not path then return response_400; end
85 return serve_file(path);
88 local function setup()
89 local ports = config.get(module.host, "core", "http_ports") or { 5280 };
90 httpserver.set_default_handler(handle_default_request);
91 httpserver.new_from_config(ports, handle_file_request, { base = "files" });
93 if prosody.start_time then -- already started
96 prosody.events.add_handler("server-started", setup);