c585928306ddeae0069f7526436282f6891096f6
[prosody.git] / plugins / mod_http_files.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9 module:depends("http");
10 local lfs = require "lfs";
11
12 local open = io.open;
13 local stat = lfs.attributes;
14
15 local http_base = module:get_option_string("http_path", "www_files");
16
17 -- TODO: Should we read this from /etc/mime.types if it exists? (startup time...?)
18 local mime_map = {
19         html = "text/html";
20         htm = "text/html";
21         xml = "text/xml";
22         xsl = "text/xml";
23         txt = "text/plain; charset=utf-8";
24         js = "text/javascript";
25         css = "text/css";
26 };
27
28 local function preprocess_path(path)
29         if path:sub(1,1) ~= "/" then
30                 path = "/"..path;
31         end
32         local level = 0;
33         for component in path:gmatch("([^/]+)/") do
34                 if component == ".." then
35                         level = level - 1;
36                 elseif component ~= "." then
37                         level = level + 1;
38                 end
39                 if level < 0 then
40                         return nil;
41                 end
42         end
43         return path;
44 end
45
46 function serve_file(event, path)
47         local response = event.response;
48         path = path and preprocess_path(path);
49         if not path then
50                 return 400;
51         end
52         local full_path = http_base..path;
53         if stat(full_path, "mode") == "directory" then
54                 if stat(full_path.."/index.html", "mode") == "file" then
55                         return serve_file(event, path.."/index.html");
56                 end
57                 return 403;
58         end
59         local f, err = open(full_path, "rb");
60         if not f then
61                 return 404;
62         end
63         local data = f:read("*a");
64         f:close();
65         if not data then
66                 return 403;
67         end
68         local ext = path:match("%.([^.]*)$");
69         response.headers.content_type = mime_map[ext]; -- Content-Type should be nil when not known
70         return response:send(data);
71 end
72
73 module:provides("http", {
74         route = {
75                 ["/*"] = serve_file;
76         };
77 });
78