mod_http_index/mod_http_index.lua
changeset 1573 0d8cc6971cdb
child 1593 3e4d15ae2133
child 1829 1b5c817cb642
equal deleted inserted replaced
1572:1aa894db3585 1573:0d8cc6971cdb
       
     1 local st = require "util.stanza";
       
     2 local url = require"socket.url";
       
     3 
       
     4 module:depends"http";
       
     5 
       
     6 -- local dump = require"util.serialization".new"dump".serialize;
       
     7 
       
     8 local function template(data)
       
     9 	--[[ DOC
       
    10 	Like util.template, but deals with plain text
       
    11 	Returns a closure that is called with a table of values
       
    12 	{name} is substituted for values["name"] and is XML escaped
       
    13 	{name!} is substituted without XML escaping
       
    14 	{name?} is optional and is replaced with an empty string if no value exists
       
    15 	]]
       
    16 	return function(values)
       
    17 		return (data:gsub("{([^}]-)(%p?)}", function (name, opt)
       
    18 			local value = values[name];
       
    19 			if value then
       
    20 				if opt ~= "!" then
       
    21 					return st.xml_escape(value);
       
    22 				end
       
    23 				return value;
       
    24 			elseif opt == "?" then
       
    25 				return "";
       
    26 			end
       
    27 		end));
       
    28 	end
       
    29 end
       
    30 
       
    31 -- TODO Move templates into files
       
    32 local base = template(template[[
       
    33 <!DOCTYPE html>
       
    34 <html>
       
    35 <head>
       
    36 <meta charset="utf-8">
       
    37 <meta name="viewport" content="width=device-width, initial-scale=1">
       
    38 <meta name="generator" value="prosody/{prosody_version} mod_{mod_name}">
       
    39 <link rel="canonical" href="{canonical}">
       
    40 <title>{title}</title>
       
    41 <style>
       
    42 body{background-color:#eeeeec;margin:1ex 0;padding-bottom:3em;font-family:Arial,Helvetica,sans-serif;}
       
    43 header,footer{margin:1ex 1em;}
       
    44 footer{font-size:smaller;color:#babdb6;}
       
    45 .content{background-color:white;padding:1em;list-style-position:inside;}
       
    46 nav{font-size:large;margin:1ex 1ex;clear:both;line-height:1.5em;}
       
    47 nav a{padding: 1ex;text-decoration:none;}
       
    48 nav a[rel="up"]{font-size:smaller;}
       
    49 nav a[rel="prev"]{float:left;}
       
    50 nav a[rel="next"]{float:right;}
       
    51 nav a[rel="next::after"]{content:" →";}
       
    52 nav a[rel="prev::before"]{content:"← ";}
       
    53 nav a:empty::after,nav a:empty::before{content:""}
       
    54 @media screen and (min-width: 460px) {
       
    55 nav{font-size:x-large;margin:1ex 1em;}
       
    56 }
       
    57 a:link,a:visited{color:#2e3436;text-decoration:none;}
       
    58 a:link:hover,a:visited:hover{color:#3465a4;}
       
    59 ul,ol{padding:0;}
       
    60 li{list-style:none;}
       
    61 hr{visibility:hidden;clear:both;}
       
    62 br{clear:both;}
       
    63 li time{float:right;font-size:small;opacity:0.2;}
       
    64 li:hover time{opacity:1;}
       
    65 .room-list .description{font-size:smaller;}
       
    66 q.body::before,q.body::after{content:"";}
       
    67 .presence .verb{font-style:normal;color:#30c030;}
       
    68 .presence.unavailable .verb{color:#c03030;}
       
    69 </style>
       
    70 </head>
       
    71 <body>
       
    72 <header>
       
    73 <h1>{title}</h1>
       
    74 {header!}
       
    75 </header>
       
    76 <hr>
       
    77 <div class="content">
       
    78 {body!}
       
    79 </div>
       
    80 <hr>
       
    81 <footer>
       
    82 {footer!}
       
    83 <br>
       
    84 <div class="powered-by">Prosody {prosody_version?}</div>
       
    85 </footer>
       
    86 </body>
       
    87 </html>
       
    88 ]] { prosody_version = prosody.version, mod_name = module.name });
       
    89 
       
    90 local canonical = module:http_url(nil, "/");
       
    91 local page_template = template(base{
       
    92 	canonical = canonical;
       
    93 	title = "HTTP stuff";
       
    94 	header = "";
       
    95 	body = [[
       
    96 <nav>
       
    97 <ul>
       
    98 {lines!}
       
    99 </ul>
       
   100 </nav>
       
   101 ]];
       
   102 	footer = "";
       
   103 });
       
   104 local line_template = template[[
       
   105 <li><a href="{url}" title="{module}">{name}</a></li>
       
   106 ]];
       
   107 
       
   108 local function relative(base, link)
       
   109 	base = url.parse(base);
       
   110 	link = url.parse(link);
       
   111 	for k,v in pairs(base) do
       
   112 		if link[k] == v then
       
   113 			link[k] = nil;
       
   114 		end
       
   115 	end
       
   116 	return url.build(link);
       
   117 end
       
   118 
       
   119 local function handler(event)
       
   120 	local items = module:get_host_items("http-provider");
       
   121 	local item;
       
   122 	for i = 1, #items do
       
   123 		item = items[i];
       
   124 		if module.name ~= item._provided_by then
       
   125 			items[i] = line_template{
       
   126 				name = item.name;
       
   127 				module = "mod_" .. item._provided_by;
       
   128 				url = relative(canonical, module:http_url(item.name, item.default_path));
       
   129 			};
       
   130 		else
       
   131 			items[i] = "";
       
   132 		end
       
   133 	end
       
   134 	event.response.headers.content_type = "text/html";
       
   135 	return page_template{
       
   136 		lines = table.concat(items);
       
   137 	};
       
   138 end
       
   139 
       
   140 module:provides("http", {
       
   141 	route = {
       
   142 		["GET /"] = handler;
       
   143 	};
       
   144 	default_path = "/";
       
   145 });