Changeset

6198:7205e0348bbe

mod_muc_log_http: Delete because obsolete
author Kim Alvefur <zash@zash.se>
date Sun, 09 Feb 2025 17:17:10 +0100
parents 6197:ba8f5cdc1676
children 6199:fe8222112cf4
files mod_muc_log_http/README.md mod_muc_log_http/muc_log_http/mod_muc_log_http.lua mod_muc_log_http/muc_log_http/themes/prosody/components_bit.html mod_muc_log_http/muc_log_http/themes/prosody/components_body.html mod_muc_log_http/muc_log_http/themes/prosody/day_bann.html mod_muc_log_http/muc_log_http/themes/prosody/day_body.html mod_muc_log_http/muc_log_http/themes/prosody/day_bodynp.html mod_muc_log_http/muc_log_http/themes/prosody/day_dayLink.html mod_muc_log_http/muc_log_http/themes/prosody/day_kick.html mod_muc_log_http/muc_log_http/themes/prosody/day_message.html mod_muc_log_http/muc_log_http/themes/prosody/day_messageMe.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_join.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_leave.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusChange.html mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusText.html mod_muc_log_http/muc_log_http/themes/prosody/day_reason.html mod_muc_log_http/muc_log_http/themes/prosody/day_time.html mod_muc_log_http/muc_log_http/themes/prosody/day_title.html mod_muc_log_http/muc_log_http/themes/prosody/day_titleChange.html mod_muc_log_http/muc_log_http/themes/prosody/days_bit.html mod_muc_log_http/muc_log_http/themes/prosody/days_body.html mod_muc_log_http/muc_log_http/themes/prosody/days_rooms_bit.html mod_muc_log_http/muc_log_http/themes/prosody/doc.html mod_muc_log_http/muc_log_http/themes/prosody/month_day.html mod_muc_log_http/muc_log_http/themes/prosody/month_emptyDay.html mod_muc_log_http/muc_log_http/themes/prosody/month_footer.html mod_muc_log_http/muc_log_http/themes/prosody/month_header.html mod_muc_log_http/muc_log_http/themes/prosody/month_weekDay.html mod_muc_log_http/muc_log_http/themes/prosody/rooms_bit.html mod_muc_log_http/muc_log_http/themes/prosody/rooms_body.html mod_muc_log_http/muc_log_http/themes/prosody/year_title.html
diffstat 31 files changed, 7 insertions(+), 955 deletions(-) [+]
line wrap: on
line diff
--- a/mod_muc_log_http/README.md	Sun Feb 09 17:15:27 2025 +0100
+++ b/mod_muc_log_http/README.md	Sun Feb 09 17:17:10 2025 +0100
@@ -1,9 +1,15 @@
 ---
 labels:
-- 'Stage-Beta'
+- 'Stage-Obsolete'
 summary: Provides a web interface to stored chatroom logs
 ...
 
+::: {.alert .alert-danger}
+This module depends on an obsolete module for storing data in an inefficient format.
+
+For a modern approach, see [mod_http_muc_log] which relies on [mod_muc_mam][doc:modules:mod_muc_mam].
+:::
+
 Introduction
 ============
 
--- a/mod_muc_log_http/muc_log_http/mod_muc_log_http.lua	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,759 +0,0 @@
-module:depends("http");
-
-local prosody = prosody;
-local hosts = prosody.hosts;
-local my_host = module:get_host();
-local strchar = string.char;
-local strformat = string.format;
-local split_jid = require "util.jid".split;
-local config_get = require "core.configmanager".get;
-local urldecode = require "net.http".urldecode;
-local http_event = require "net.http.server".fire_event;
-local datamanager = require"core.storagemanager".olddm;
-local data_load, data_getpath = datamanager.load, datamanager.getpath;
-local datastore = "muc_log";
-local url_base = "muc_log";
-local config = nil;
-local table, tostring, tonumber = table, tostring, tonumber;
-local os_date, os_time = os.date, os.time;
-local str_format = string.format;
-local io_open = io.open;
-local themes_parent = (module.path and module.path:gsub("[/\\][^/\\]*$", "")  or (prosody.paths.plugins or "./plugins") .. "/muc_log_http") .. "/themes";
-
-local lom = require "lxp.lom";
-local lfs = require "lfs";
-local html = {};
-local theme;
-
--- Helper Functions
-
-local p_encode = datamanager.path_encode;
-local function store_exists(node, host, today)
-	if lfs.attributes(data_getpath(node, host, datastore .. "/" .. today), "mode") then return true; else return false; end
-end
-
--- Module Definitions
-
-local function html_escape(t)
-	if t then
-		t = t:gsub("<", "&lt;");
-		t = t:gsub(">", "&gt;");
-		t = t:gsub("(http://[%a%d@%.:/&%?=%-_#%%~]+)", function(h)
-			h = urlunescape(h)
-			return "<a href='" .. h .. "'>" .. h .. "</a>";
-		end);
-		t = t:gsub("\n", "<br />");
-		t = t:gsub("%%", "%%%%");
-	else
-		t = "";
-	end
-	return t;
-end
-
-function create_doc(body, title)
-	if not body then return "" end
-	body = body:gsub("%%", "%%%%");
-	return html.doc:gsub("###BODY_STUFF###", body)
-		:gsub("<title>muc_log</title>", "<title>"..(title and html_escape(title) or "Chatroom logs").."</title>");
-end
-
-function urlunescape (url)
-	url = url:gsub("+", " ")
-	url = url:gsub("%%(%x%x)", function(h) return strchar(tonumber(h,16)) end)
-	url = url:gsub("\r\n", "\n")
-	return url
-end
-local function urlencode(s)
-	return s and (s:gsub("[^a-zA-Z0-9.~_-]", function (c) return ("%%%02x"):format(c:byte()); end));
-end
-
-local function get_room_from_jid(jid)
-	local node, host = split_jid(jid);
-	local component = hosts[host];
-	if component then
-		local muc = component.modules.muc
-		if muc and rawget(muc,"rooms") then
-			-- We're running 0.9.x or 0.10 (old MUC API)
-			return muc.rooms[jid];
-		elseif muc and rawget(muc,"get_room_from_jid") then
-			-- We're running >0.10 (new MUC API)
-			return muc.get_room_from_jid(jid);
-		else
-			return
-		end
-	end
-end
-
-local function get_room_list(host)
-	local component = hosts[host];
-	local list = {};
-	if component then
-		local muc = component.modules.muc
-		if muc and rawget(muc,"rooms") then
-			-- We're running 0.9.x or 0.10 (old MUC API)
-			for _, room in pairs(muc.rooms) do
-				list[room.jid] = room;
-			end
-			return list;
-		elseif muc and rawget(muc,"each_room") then
-			-- We're running >0.10 (new MUC API)
-			for room, _ in muc.each_room() do
-				list[room.jid] = room;
-			end
-			return list;
-		end
-	end
-end
-
-local function generate_room_list(host)
-		local rooms;
-
-		for jid, room in pairs(get_room_list(host)) do
-			local node = split_jid(jid);
-			if not room._data.hidden and room._data.logging and node then
-				rooms = (rooms or "") .. html.rooms.bit:gsub("###ROOM###", urlencode(node)):gsub("###COMPONENT###", host);
-			end
-		end
-
-		if rooms then
-			return html.rooms.body:gsub("###ROOMS_STUFF###", rooms):gsub("###COMPONENT###", host), "Chatroom logs for "..host;
-		end
-end
-
--- Calendar stuff
-local function get_days_for_month(month, year)
-	if month == 2 then
-		local is_leap_year = (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0;
-		return is_leap_year and 29 or 28;
-	elseif (month < 8 and month%2 == 1) or (month >= 8 and month%2 == 0) then
-		return 31;
-	end
-	return 30;
-end
-
-local function create_month(month, year, callback)
-	local html_str = html.month.header;
-	local days = get_days_for_month(month, year);
-	local time = os_time{year=year, month=month, day=1};
-	local dow = tostring(os_date("%a", time))
-	local title = tostring(os_date("%B", time));
-	local week_days = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
-	local week_day = 0;
-	local weeks = 1;
-	local _available_for_one_day = false;
-
-	local week_days_html = "";
-	for _, tmp in ipairs(week_days) do
-		week_days_html = week_days_html .. html.month.weekDay:gsub("###DAY###", tmp) .. "\n";
-	end
-
-	html_str = html_str:gsub("###TITLE###", title):gsub("###WEEKDAYS###", week_days_html);
-
-	for i = 1, 31 do
-		week_day = week_day + 1;
-		if week_day == 1 then html_str = html_str .. "<tr>\n"; end
-		if i == 1 then
-			for _, tmp in ipairs(week_days) do
-				if dow ~= tmp then
-					html_str = html_str .. html.month.emptyDay .. "\n";
-					week_day = week_day + 1;
-				else
-					break;
-				end
-			end
-		end
-		if i < days + 1 then
-			local tmp = tostring(i);
-			if callback and callback.callback then
-				tmp = callback.callback(callback.path, i, month, year, callback.room, callback.webpath);
-			end
-			if tmp == nil then
-				tmp = tostring(i);
-			else
-				_available_for_one_day = true;
-			end
-			html_str = html_str .. html.month.day:gsub("###DAY###", tmp) .. "\n";
-		end
-
-		if i >= days then
-			break;
-		end
-
-		if week_day == 7 then
-			week_day = 0;
-			weeks = weeks + 1;
-			html_str = html_str .. "</tr>\n";
-		end
-	end
-
-	if week_day + 1 < 8 or weeks < 6 then
-		week_day = week_day + 1;
-		if week_day > 7 then
-			week_day = 1;
-		end
-		if week_day == 1 then
-			weeks = weeks + 1;
-		end
-		for y = weeks, 6 do
-			if week_day == 1 then
-				html_str = html_str .. "<tr>\n";
-			end
-			for i = week_day, 7 do
-				html_str = html_str .. html.month.emptyDay .. "\n";
-			end
-			week_day = 1
-			html_str = html_str .. "</tr>\n";
-		end
-	end
-	html_str = html_str .. html.month.footer;
-	if _available_for_one_day then
-		return html_str;
-	end
-end
-
-local function create_year(year, callback)
-	local year = year;
-	local tmp;
-	if tonumber(year) <= 99 then
-		year = year + 2000;
-	end
-	local html_str = "";
-	for i=1, 12 do
-		tmp = create_month(i, year, callback);
-		if tmp then
-			html_str = html_str .. "<div style='float: left; padding: 5px;'>\n" .. tmp .. "</div>\n";
-		end
-	end
-	if html_str ~= "" then
-		return "<div name='yearDiv' style='padding: 40px; text-align: center;'>" .. html.year.title:gsub("###YEAR###", tostring(year)) .. html_str .. "</div><br style='clear:both;'/> \n";
-	end
-	return "";
-end
-
-local function day_callback(path, day, month, year, room, webpath)
-	local webpath = webpath or ""
-	local year = year;
-	if year > 2000 then
-		year = year - 2000;
-	end
-	local bare_day = str_format("20%.02d-%.02d-%.02d", year, month, day);
-	room = p_encode(room);
-	local attributes, err = lfs.attributes(path.."/"..str_format("%.02d%.02d%.02d", year, month, day).."/"..room..".dat");
-	if attributes ~= nil and attributes.mode == "file" then
-		local s = html.days.bit;
-		s = s:gsub("###BARE_DAY###", webpath .. bare_day);
-		s = s:gsub("###DAY###", day);
-		return s;
-	end
-	return;
-end
-
-local function generate_day_room_content(bare_room_jid)
-	local days = "";
-	local days_array = {};
-	local tmp;
-	local node, host = split_jid(bare_room_jid);
-	local path = data_getpath(node, host, datastore);
-	local room = nil;
-	local next_room = "";
-	local previous_room = "";
-	local rooms = "";
-	local attributes = nil;
-	local since = "";
-	local to = "";
-	local topic = "";
-	local component = hosts[host];
-
-	if not(get_room_from_jid(bare_room_jid)) then
-		return;
-	end
-
-	path = path:gsub("/[^/]*$", "");
-	attributes = lfs.attributes(path);
-	do
-		local found = 0;
-		module:log("debug", generate_room_list(host));
-		for jid, room in pairs(get_room_list(host)) do
-			local node = split_jid(jid)
-			if not room._data.hidden and room._data.logging and node then
-				if found == 0 then
-					previous_room = node
-				elseif found == 1 then
-					next_room = node
-					found = -1
-				end
-				if jid == bare_room_jid then
-					found = 1
-				end
-
-				rooms = rooms .. html.days.rooms.bit:gsub("###ROOM###", urlencode(node));
-			end
-		end
-
-		room = get_room_from_jid(bare_room_jid);
-		if room._data.hidden or not room._data.logging then
-			room = nil;
-		end
-	end
-	if attributes and room then
-		local already_done_years = {};
-		topic = room._data.subject or "(no subject)"
-		if topic:len() > 135 then
-			topic = topic:sub(1, topic:find(" ", 120)) .. " ..."
-		end
-		local folders = {};
-		for folder in lfs.dir(path) do table.insert(folders, folder); end
-		table.sort(folders);
-		for _, folder in ipairs(folders) do
-			local year, month, day = folder:match("^(%d%d)(%d%d)(%d%d)");
-			if year then
-				to = tostring(os_date("%B %Y", os_time({ day=tonumber(day), month=tonumber(month), year=2000+tonumber(year) })));
-				if since == "" then since = to; end
-				if not already_done_years[year] then
-					module:log("debug", "creating overview for: %s", to);
-					days = create_year(year, {callback=day_callback, path=path, room=node}) .. days;
-					already_done_years[year] = true;
-				end
-			end
-		end
-	end
-
-	tmp = html.days.body:gsub("###DAYS_STUFF###", days);
-	tmp = tmp:gsub("###PREVIOUS_ROOM###", previous_room == "" and node or previous_room);
-	tmp = tmp:gsub("###NEXT_ROOM###", next_room == "" and node or next_room);
-	tmp = tmp:gsub("###ROOMS###", rooms);
-	tmp = tmp:gsub("###ROOMTOPIC###", topic);
-	tmp = tmp:gsub("###SINCE###", since);
-	tmp = tmp:gsub("###TO###", to);
-	return tmp:gsub("###JID###", bare_room_jid), "Chatroom logs for "..bare_room_jid;
-end
-
-local function parse_iq(stanza, time, nick)
-	local text = nil;
-	local victim = nil;
-	if(stanza.attr.type == "set") then
-		for _,tag in ipairs(stanza) do
-			if tag.tag == "query" then
-				for _,item in ipairs(tag) do
-					if item.tag == "item" and item.attr.nick ~= nil and item.attr.role == 'none' then
-						victim = item.attr.nick;
-						for _,reason in ipairs(item) do
-							if reason.tag == "reason" then
-								text = reason[1];
-								break;
-							end
-						end
-						break;
-					end
-				end
-				break;
-			end
-		end
-		if victim then
-			if text then
-				text = html.day.reason:gsub("###REASON###", html_escape(text));
-			else
-				text = "";
-			end
-			return html.day.kick:gsub("###TIME_STUFF###", time):gsub("###VICTIM###", victim):gsub("###REASON_STUFF###", text);
-		end
-	end
-	return;
-end
-
-local function parse_presence(stanza, time, nick)
-	local ret = "";
-	local show_join = "block"
-
-	if config and not config.show_join then
-		show_join = "none";
-	end
-
-	if stanza.attr.type == nil then
-		local show_status = "block"
-		if config and not config.show_status then
-			show_status = "none";
-		end
-		local show, status = nil, "";
-		local already_joined = false;
-		for _, tag in ipairs(stanza) do
-			if tag.tag == "alreadyJoined" then
-				already_joined = true;
-			elseif tag.tag == "show" then
-				show = tag[1];
-			elseif tag.tag == "status" and tag[1] ~= nil then
-				status = tag[1];
-			end
-		end
-		if already_joined == true then
-			if show == nil then
-				show = "online";
-			end
-			ret = html.day.presence.statusChange:gsub("###TIME_STUFF###", time);
-			if status ~= "" then
-				status = html.day.presence.statusText:gsub("###STATUS###", html_escape(status));
-			end
-			ret = ret:gsub("###SHOW###", show):gsub("###NICK###", nick):gsub("###SHOWHIDE###", show_status):gsub("###STATUS_STUFF###", status);
-		else
-			ret = html.day.presence.join:gsub("###TIME_STUFF###", time):gsub("###SHOWHIDE###", show_join):gsub("###NICK###", nick);
-		end
-	elseif stanza.attr.type == "unavailable" then
-
-		ret = html.day.presence.leave:gsub("###TIME_STUFF###", time):gsub("###SHOWHIDE###", show_join):gsub("###NICK###", nick);
-	end
-	return ret;
-end
-
-local function parse_message(stanza, time, nick)
-	local body, title, ret = nil, nil, "";
-
-	for _,tag in ipairs(stanza) do
-		if tag.tag == "body" then
-			body = tag[1];
-			if nick then
-				break;
-			end
-		elseif tag.tag == "nick" and nick == nil then
-			nick = html_escape(tag[1]);
-			if body or title then
-				break;
-			end
-		elseif tag.tag == "subject" then
-			title = tag[1];
-			if nick then
-				break;
-			end
-		end
-	end
-	if nick and body then
-		body = html_escape(body);
-		local me = body:find("^/me");
-		local template = "";
-		if not me then
-			template = html.day.message;
-		else
-			template = html.day.messageMe;
-			body = body:gsub("^/me ", "");
-		end
-		ret = template:gsub("###TIME_STUFF###", time):gsub("###NICK###", nick):gsub("###MSG###", body);
-	elseif nick and title then
-		title = html_escape(title);
-		ret = html.day.titleChange:gsub("###TIME_STUFF###", time):gsub("###NICK###", nick):gsub("###TITLE###", title);
-	end
-	return ret;
-end
-
-local function increment_day(bare_day)
-	local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$");
-	local leapyear = false;
-	module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year))
-
-	day = tonumber(day);
-	month = tonumber(month);
-	year = tonumber(year);
-
-	if year%4 == 0 and year%100 == 0 then
-		if year%400 == 0 then
-			leapyear = true;
-		else
-			leapyear = false; -- turn of the century but not a leapyear
-		end
-	elseif year%4 == 0 then
-		leapyear = true;
-	end
-
-	if (month == 2 and leapyear and day + 1 > 29) or
-		(month == 2 and not leapyear and day + 1 > 28) or
-		(month < 8 and month%2 == 1 and day + 1 > 31) or
-		(month < 8 and month%2 == 0 and day + 1 > 30) or
-		(month >= 8 and month%2 == 0 and day + 1 > 31) or
-		(month >= 8 and month%2 == 1 and day + 1 > 30)
-	then
-		if month + 1 > 12 then
-			year = year + 1;
-			month = 1;
-			day = 1;
-		else
-			month = month + 1;
-			day = 1;
-		end
-	else
-		day = day + 1;
-	end
-	return strformat("20%.02d-%.02d-%.02d", year, month, day);
-end
-
-local function find_next_day(bare_room_jid, bare_day)
-	local node, host = split_jid(bare_room_jid);
-	local day = increment_day(bare_day);
-	local max_trys = 7;
-
-	module:log("debug", day);
-	while(not store_exists(node, host, day)) do
-		max_trys = max_trys - 1;
-		if max_trys == 0 then
-			break;
-		end
-		day = increment_day(day);
-	end
-	if max_trys == 0 then
-		return nil;
-	else
-		return day;
-	end
-end
-
-local function decrement_day(bare_day)
-	local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$");
-	local leapyear = false;
-	module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year))
-
-	day = tonumber(day);
-	month = tonumber(month);
-	year = tonumber(year);
-
-	if year%4 == 0 and year%100 == 0 then
-		if year%400 == 0 then
-			leapyear = true;
-		else
-			leapyear = false; -- turn of the century but not a leapyear
-		end
-	elseif year%4 == 0 then
-		leapyear = true;
-	end
-
-	if day - 1 == 0 then
-		if month - 1 == 0 then
-			year = year - 1;
-			month = 12;
-			day = 31;
-		else
-			month = month - 1;
-			if (month == 2 and leapyear) then day = 29
-			elseif (month == 2 and not leapyear) then day = 28
-			elseif (month < 8 and month%2 == 1) or (month >= 8 and month%2 == 0) then day = 31
-			else day = 30
-			end
-		end
-	else
-		day = day - 1;
-	end
-	return strformat("20%.02d-%.02d-%.02d", year, month, day);
-end
-
-local function find_previous_day(bare_room_jid, bare_day)
-	local node, host = split_jid(bare_room_jid);
-	local day = decrement_day(bare_day);
-	local max_trys = 7;
-	module:log("debug", day);
-	while(not store_exists(node, host, day)) do
-		max_trys = max_trys - 1;
-		if max_trys == 0 then
-			break;
-		end
-		day = decrement_day(day);
-	end
-	if max_trys == 0 then
-		return nil;
-	else
-		return day;
-	end
-end
-
-local function parse_day(bare_room_jid, room_subject, bare_day)
-	local ret = "";
-	local year;
-	local month;
-	local day;
-	local tmp;
-	local node, host = split_jid(bare_room_jid);
-	local year, month, day = bare_day:match("^20(%d%d)-(%d%d)-(%d%d)$");
-	local previous_day = find_previous_day(bare_room_jid, bare_day);
-	local next_day = find_next_day(bare_room_jid, bare_day);
-	local temptime = {day=0, month=0, year=0};
-	local path = data_getpath(node, host, datastore);
-	path = path:gsub("/[^/]*$", "");
-	local calendar = ""
-
-	if tonumber(year) <= 99 then
-		year = year + 2000;
-	end
-
-	temptime.day = tonumber(day)
-	temptime.month = tonumber(month)
-	temptime.year = tonumber(year)
-	calendar = create_month(temptime.month, temptime.year, {callback=day_callback, path=path, room=node, webpath="../"}) or ""
-
-	if bare_day then
-		local data = data_load(node, host, datastore .. "/" .. bare_day:match("^20(.*)"):gsub("-", ""));
-		if data then
-			for i=1, #data, 1 do
-				local stanza = lom.parse(data[i]);
-				if stanza and stanza.attr and stanza.attr.time then
-					local timeStuff = html.day.time:gsub("###TIME###", stanza.attr.time):gsub("###UTC###", stanza.attr.utc or stanza.attr.time);
-					if stanza[1] ~= nil then
-						local nick;
-						local tmp;
-
-						-- grep nick from "from" resource
-						if stanza[1].attr.from then -- presence and messages
-							nick = html_escape(stanza[1].attr.from:match("/(.+)$"));
-						elseif stanza[1].attr.to then -- iq
-							nick = html_escape(stanza[1].attr.to:match("/(.+)$"));
-						end
-
-						if stanza[1].tag == "presence" and nick then
-							tmp = parse_presence(stanza[1], timeStuff, nick);
-						elseif stanza[1].tag == "message" then
-							tmp = parse_message(stanza[1], timeStuff, nick);
-						elseif stanza[1].tag == "iq" then
-							tmp = parse_iq(stanza[1], timeStuff, nick);
-						else
-							module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bare_room_jid, year .. "/" .. month .. "/" .. day);
-						end
-						if tmp then
-							ret = ret .. tmp
-							tmp = nil;
-						end
-					end
-				end
-			end
-		end
-		if ret ~= "" then
-			if next_day then
-				next_day = html.day.dayLink:gsub("###DAY###", next_day):gsub("###TEXT###", "&gt;")
-			end
-			if previous_day then
-				previous_day = html.day.dayLink:gsub("###DAY###", previous_day):gsub("###TEXT###", "&lt;");
-			end
-			ret = ret:gsub("%%", "%%%%");
-			if config.show_presences then
-				tmp = html.day.body:gsub("###DAY_STUFF###", ret):gsub("###JID###", bare_room_jid);
-			else
-				tmp = html.day.bodynp:gsub("###DAY_STUFF###", ret):gsub("###JID###", bare_room_jid);
-			end
-			tmp = tmp:gsub("###CALENDAR###", calendar);
-			tmp = tmp:gsub("###DATE###", tostring(os_date("%A, %B %d, %Y", os_time(temptime))));
-			tmp = tmp:gsub("###TITLE_STUFF###", html.day.title:gsub("###TITLE###", room_subject));
-			tmp = tmp:gsub("###STATUS_CHECKED###", config.show_status and "checked='checked'" or "");
-			tmp = tmp:gsub("###JOIN_CHECKED###", config.show_join and "checked='checked'" or "");
-			tmp = tmp:gsub("###NEXT_LINK###", next_day or "");
-			tmp = tmp:gsub("###PREVIOUS_LINK###", previous_day or "");
-
-			return tmp, "Chatroom logs for "..bare_room_jid.." ("..tostring(os_date("%A, %B %d, %Y", os_time(temptime)))..")";
-		end
-	end
-end
-
-local function handle_error(code, err) return http_event("http-error", { code = code, message = err }); end
-function handle_request(event)
-	local response = event.response;
-	local request = event.request;
-	local room;
-
-	local node, day, more = request.url.path:match("^/"..url_base.."/+([^/]*)/*([^/]*)/*(.*)$");
-
-	if more ~= "" then
-		response.status_code = 404;
-		return response:send(handle_error(response.status_code, "Unknown URL."));
-	end
-	if node == "" then node = nil; end
-	if day  == "" then day  = nil; end
-
-	node = urldecode(node);
-
-	if not html.doc then
-		response.status_code = 500;
-		return response:send(handle_error(response.status_code, "Muc Theme is not loaded."));
-	end
-
-	if node then room = get_room_from_jid(node.."@"..my_host); end
-	if node and not room then
-		response.status_code = 404;
-		return response:send(handle_error(response.status_code, "Room doesn't exist."));
-	end
-	if room and (room._data.hidden or not room._data.logging) then
-		response.status_code = 404;
-		return response:send(handle_error(response.status_code, "There're no logs for this room."));
-	end
-
-	if not node then -- room list for component
-		return response:send(create_doc(generate_room_list(my_host)));
-	elseif not day then -- room's listing
-		return response:send(create_doc(generate_day_room_content(node.."@"..my_host)));
-	else
-		if not day:match("^20(%d%d)-(%d%d)-(%d%d)$") then
-			local y,m,d = day:match("^(%d%d)(%d%d)(%d%d)$");
-			if not y then
-				response.status_code = 404;
-				return response:send(handle_error(response.status_code, "No entries for that year."));
-			end
-			response.status_code = 301;
-			response.headers = { ["Location"] = request.url.path:match("^/"..url_base.."/+[^/]*").."/20"..y.."-"..m.."-"..d.."/" };
-			return response:send();
-		end
-
-		local body = create_doc(parse_day(node.."@"..my_host, room._data.subject or "", day));
-		if body == "" then
-			response.status_code = 404;
-			return response:send(handle_error(response.status_code, "Day entry doesn't exist."));
-		end
-		return response:send(body);
-	end
-end
-
-local function read_file(filepath)
-	local f,err = io_open(filepath, "r");
-	if not f then return f,err; end
-	local t = f:read("*all");
-	f:close()
-	return t;
-end
-
-local function load_theme(path)
-	for file in lfs.dir(path) do
-		if file:match("%.html$") then
-			module:log("debug", "opening theme file: " .. file);
-			local content,err = read_file(path .. "/" .. file);
-			if not content then return content,err; end
-
-			-- html.a.b.c = content of a_b_c.html
-			local tmp = html;
-			for idx in file:gmatch("([^_]*)_") do
-				tmp[idx] = tmp[idx] or {};
-				tmp = tmp[idx];
-			end
-			tmp[file:match("([^_]*)%.html$")] = content;
-		end
-	end
-	return true;
-end
-
-function module.load()
-	config = module:get_option("muc_log_http", {});
-	if module:get_option_boolean("muc_log_presences", true) then config.show_presences = true end
-	if config.show_status == nil then config.show_status = true; end
-	if config.show_join == nil then config.show_join = true; end
-	if config.url_base and type(config.url_base) == "string" then url_base = config.url_base; end
-
-	theme = config.theme or "prosody";
-	local theme_path = themes_parent .. "/" .. tostring(theme);
-	local attributes, err = lfs.attributes(theme_path);
-	if attributes == nil or attributes.mode ~= "directory" then
-		module:log("error", "Theme folder of theme \"".. tostring(theme) .. "\" isn't existing. expected Path: " .. theme_path);
-		return false;
-	end
-
-	local themeLoaded,err = load_theme(theme_path);
-	if not themeLoaded then
-		module:log("error", "Theme \"%s\" is missing something: %s", tostring(theme), err);
-		return false;
-	end
-
-	module:provides("http", {
-		default_path = url_base,
-		route = {
-			["GET /*"] = handle_request;
-		}
-	});
-end
--- a/mod_muc_log_http/muc_log_http/themes/prosody/components_bit.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a href="###COMPONENT###/">###COMPONENT###</a><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/components_body.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<h2>Available Multi-User Chats:</h2><hr /><p>
-###COMPONENTS_STUFF###
-</p><hr />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_bann.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TIME_STUFF###<span class="muc_bann"> *** ###VICTIM### got banned###REASON_STUFF###</span><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_body.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<div id="title">
-	<div id="date">###DATE###</div>
-	<div id="roomjid">###JID###</div>
-	<div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div>
-</div>
-<div id="calendar">
-	<div id="navigation">
-		###PREVIOUS_LINK### <a class="nav" href="../">^</a>###NEXT_LINK###
-	</div>
-	###CALENDAR###
-</div>
-<div id="topic">###TITLE_STUFF###</div>
-<br />
-<input id="toggleJoinLeave" type="checkbox" onclick="showHide('muc_joinLeave_container')" ###JOIN_CHECKED###/><label for="toggleJoinLeave">show/hide joins and leaves</label>
-<input id="toggleStatus" type="checkbox" onclick="showHide('muc_statusChange_container')" ###STATUS_CHECKED###/><label for="toggleStatus">show/hide status changes</label>
-<input id="toggleUTC" type="checkbox" onclick="changeTimeDisplay()" /><label for="toggleUTC">show time in local time, rather than in UTC</label>
-<div id="main">###DAY_STUFF###</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_bodynp.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-<div id="title">
-	<div id="date">###DATE###</div>
-	<div id="roomjid">###JID###</div>
-	<div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div>
-</div>
-<div id="calendar">
-	<div id="navigation">
-		###PREVIOUS_LINK### <a class="nav" href="../">^</a>###NEXT_LINK###
-	</div>
-	###CALENDAR###
-</div>
-<div id="topic">###TITLE_STUFF###</div>
-<br />
-<input id="toggleUTC" type="checkbox" onclick="changeTimeDisplay()" /><label for="toggleUTC">show time in local time, rather than in UTC</label>
-<div id="main">###DAY_STUFF###</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_dayLink.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a class="nav" href="../###DAY###/">###TEXT###</a>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_kick.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TIME_STUFF###<span class="muc_kick"> *** ###VICTIM### got kicked###REASON_STUFF###</span><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_message.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TIME_STUFF###<span class="muc_msg_nick">&lt;###NICK###&gt;</span> ###MSG###<br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_messageMe.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TIME_STUFF###<span class="muc_msg_me">*###NICK### ###MSG###</span><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_join.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<div class="muc_joinLeave_container">###TIME_STUFF###<span class="muc_join"> *** ###NICK### has joined the room</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_leave.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<div class="muc_joinLeave_container">###TIME_STUFF###<span class="muc_leave"> *** ###NICK### has left the room</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusChange.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<div class="muc_statusChange_container">###TIME_STUFF###<span class="muc_statusChange"> *** ###NICK### shows as "###SHOW###"###STATUS_STUFF###</span><br /></div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_presence_statusText.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
- and his status message is "###STATUS###"
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_reason.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-, the reason was "###REASON###"
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_time.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a name="###TIME###" href="####TIME###" class="timestuff">[<span name="time" id="###UTC###">###TIME###</span>]</a>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_title.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TITLE###
--- a/mod_muc_log_http/muc_log_http/themes/prosody/day_titleChange.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-###TIME_STUFF###<span class="muc_titleChange"> *** ###NICK### changed the title to "###TITLE###"</span><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_bit.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a href="###BARE_DAY###/">###DAY###</a><br />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_body.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-<div id="title">
-	<div id="date">###SINCE### - ###TO###</div>
-	<div id="roomjid">###JID###</div>
-	<div id="links">(join via <a class="component" href="xmpp:###JID###?join">client</a>)</div>
-</div>
-<div id="calendar">
-	<div id="navigation">
-		<a class="nav" href="../###PREVIOUS_ROOM###/">&lt;</a>
-		<a class="nav" href="../">^</a>
-		<a class="nav" href="../###NEXT_ROOM###/">&gt;</a>
-	</div>
-	<div class="weekday">List of rooms for this component</div>
-	<div id="roomList">###ROOMS###</div>
-</div>
-<div class="topic">###ROOMTOPIC###</div>
-<div id="main">
-###DAYS_STUFF###
-</div>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/days_rooms_bit.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a href="../###ROOM###/">###ROOM###</a><br />
--- a/mod_muc_log_http/muc_log_http/themes/prosody/doc.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-<html>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
-<head>
-	<title>muc_log</title>
-</head>
-<script type="text/javascript"><!--
-var utc = true;
-var timezoneOffset = (parseInt((new Date()).getTimezoneOffset()) * 60) * (-1);
-function changeTimeDisplay() {
-    var eles = document.getElementsByName("time");
-    utc = !utc;
-    for (var i = 0; i < eles.length; i++) {
-        var tmp = eles[i].id.split(":");
-        var d;
-        if(tmp.length == 3) {
-            if(!utc)
-                tmp[2] = Number(tmp[2]) + timezoneOffset;
-            d = new Date(0, 0, 0, Number(tmp[0]), Number(tmp[1]), Number(tmp[2]));
-        }
-        else {
-            if(!utc)
-                tmp[0] = Number(tmp[0]) + timezoneOffset;
-            d = new Date(0, 0, 0, 0, 0, Number(tmp[0]));
-        }
-
-        eles[i].innerHTML = (d.getHours() <= 9 ? "0" + d.getHours() : d.getHours()) + ":";
-        eles[i].innerHTML += (d.getMinutes() <= 9 ? "0" + d.getMinutes() : d.getMinutes()) + ":";
-        eles[i].innerHTML += (d.getSeconds() <= 9 ? "0" + d.getSeconds() : d.getSeconds());
-    }
-}
-
-function showHide(name) {
-	var eles = document.getElementsByClassName(name);
-	for (var i = 0; i < eles.length; i++) {
-		eles[i].style.display = eles[i].style.display != "none" ? "none" : "";
-	}
-}
-
-/* IE compat: */
-onload=function(){
-	if (document.getElementsByClassName == undefined) {
-		document.getElementsByClassName = function(className)
-		{
-			var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
-			var allElements = document.getElementsByTagName("*");
-			var results = [];
-
-			var element;
-			for (var i = 0; (element = allElements[i]) != null; i++) {
-				var elementClass = element.className;
-				if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
-					results.push(element);
-			}
-
-			return results;
-		}
-	}
-}
---></script>
-<style type="text/css">
-#title {
-	border-bottom: #f29b00 solid 3pt; padding-bottom: 3px; width: 100%;
-	color: #000000; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; text-decoration: none; margin-bottom: 3pt;
-}
-#date {
-	float: right;
-}
-#links {
-	font-size: 9px; font-family: Verdana; letter-spacing: 1px;
-}
-#topic {
-	color: #000000; font-size: 18px; font-family: sans-serif;
-}
-#calendar {float: right; margin-left: 10pt;}
-#navigation {text-align: center}
-#roomList {padding-left: 5px; padding-right: 5px; border: 1px solid black;}
-
-#main {overflow: auto; border: 2px solid gray; padding: 3px; margin-top: 1em}
-
-a {color: #6197df; text-decoration: none;}
-
-a.nav {color: #6197df; font-family: monospace; letter-spacing: 7px; font-size: 24px; text-decoration: none;}
-a.log {color: #6197df; text-decoration: none;}
-a.log_today {color: #f29b00; text-decoration: none;}
-
-.day { font: 12px Verdana; height: 17px; color: #BBBBBB}
-.weekday { font: 10px Verdana; height: 17px; color: #FFFFFF; background-color: #000000; margin-top: 50px;
-	padding-left: 5px; padding-right: 5px; padding-top: 3px; text-align: center;}
-.timestuff {color: #AAAAAA; text-decoration: none;}
-.muc_join {color: #009900; font-style: italic;}
-.muc_leave {color: #009900; font-style: italic;}
-.muc_statusChange {color: #009900; font-style: italic;}
-.muc_title {color: #BBBBBB; font-size: 32px;}
-.muc_titleChange {color: #009900; font-style: italic;}
-.muc_kick {color: #009900; font-style: italic;}
-.muc_bann {color: #009900; font-style: italic;}
-.muc_msg_nick {color: #0000AA;}
-.muc_msg_me {color: #0000AA;}
-.month_title {font: 10pt Verdana;}
-.year_title {font: bold 16px Verdana;}
-.footer {margin-top: 20pt; text-align: center;}
-
-label {margin-right: 2em}
-thead {font: 25pt bold; text-align: center}
-tbody {border: solid black 1px;}
-img {border: 0px}
-body {margin-left: 20pt; margin-right: 20pt;}
-</style>
-<body>
-###BODY_STUFF###
-<div class="footer"><a href="http://prosody.im"><img alt="Powered by Prosody" src="http://prosody.im/files/powered_by_prosody_80x30.png"/></a></div>
-</body>
-</html>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_day.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-    <td class="day" valign="middle" align="center">###DAY###</td>
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_emptyDay.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-    <td class="day">&nbsp;</td>
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_footer.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-</tbody></table>
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_header.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<table rules="groups" cellpadding="5">
-<thead><tr><td colspan="7">###TITLE###</td></tr></thead>
-<tbody>
-<tr>###WEEKDAYS###</tr>
--- a/mod_muc_log_http/muc_log_http/themes/prosody/month_weekDay.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-    <th class="weekday" valign="middle" align="center">###DAY###</th>
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/rooms_bit.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<a href="###ROOM###/">###ROOM###</a><br />
--- a/mod_muc_log_http/muc_log_http/themes/prosody/rooms_body.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<h2>Available rooms on ###COMPONENT###:</h2><hr /><p>
-###ROOMS_STUFF###
-</p><hr />
\ No newline at end of file
--- a/mod_muc_log_http/muc_log_http/themes/prosody/year_title.html	Sun Feb 09 17:15:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<div class=year_title"><a name="###YEAR###">###YEAR###</a></div>