Mercurial > prosody-modules
comparison mod_muc_log_http/muc_log_http/mod_muc_log_http.lua @ 105:cef943f0a551
mod_muc_log_http: themified ...
author | Thilo Cestonaro <thilo@cestona.ro> |
---|---|
date | Tue, 08 Dec 2009 21:12:40 +0100 |
parents | mod_muc_log_http/mod_muc_log_http.lua@dc0fe152cadc |
children | 0e4e000e3de9 |
comparison
equal
deleted
inserted
replaced
104:dc0fe152cadc | 105:cef943f0a551 |
---|---|
1 -- Copyright (C) 2009 Thilo Cestonaro | |
2 -- | |
3 -- This project is MIT/X11 licensed. Please see the | |
4 -- COPYING file in the source package for more information. | |
5 -- | |
6 | |
7 local prosody = prosody; | |
8 local tabSort = table.sort; | |
9 local tonumber = _G.tonumber; | |
10 local tostring = _G.tostring; | |
11 local strformat = string.format; | |
12 local splitJid = require "util.jid".split; | |
13 local config_get = require "core.configmanager".get; | |
14 local httpserver = require "net.httpserver"; | |
15 local datamanager = require "util.datamanager"; | |
16 local data_load, data_getpath = datamanager.load, datamanager.getpath; | |
17 local datastore = "muc_log"; | |
18 local urlBase = "muc_log"; | |
19 local muc_hosts = {}; | |
20 local config = nil; | |
21 local tostring = _G.tostring; | |
22 local tonumber = _G.tonumber; | |
23 local os_date, os_time = os.date, os.time; | |
24 local str_format = string.format; | |
25 local io_open = io.open; | |
26 local themesParent = (CFG_PLUGINDIR or "./plugins/") .. "muc_log_http/themes"; | |
27 | |
28 local lom = require "lxp.lom"; | |
29 | |
30 --[[ LuaFileSystem | |
31 * URL: http://www.keplerproject.org/luafilesystem/index.html | |
32 * Install: luarocks install luafilesystem | |
33 * ]] | |
34 local lfs = require "lfs"; | |
35 | |
36 | |
37 --[[ | |
38 * Default templates for the html output. | |
39 ]]-- | |
40 local html = {}; | |
41 local theme = "default"; | |
42 | |
43 local function checkDatastorePathExists(node, host, today, create) | |
44 create = create or false; | |
45 local path = data_getpath(node, host, datastore, "dat", true); | |
46 path = path:gsub("/[^/]*$", ""); | |
47 | |
48 -- check existance | |
49 local attributes, err = lfs.attributes(path); | |
50 if attributes == nil or attributes.mode ~= "directory" then | |
51 module:log("warn", "muc_log folder isn't a folder: %s", path); | |
52 return false; | |
53 end | |
54 | |
55 attributes, err = lfs.attributes(path .. "/" .. today); | |
56 if attributes == nil then | |
57 if create then | |
58 return lfs.mkdir(path .. "/" .. today); | |
59 else | |
60 return false; | |
61 end | |
62 elseif attributes.mode == "directory" then | |
63 return true; | |
64 end | |
65 return false; | |
66 end | |
67 | |
68 function createDoc(body) | |
69 if body then | |
70 return html.doc:gsub("###BODY_STUFF###", body); | |
71 end | |
72 end | |
73 | |
74 local function htmlEscape(t) | |
75 t = t:gsub("<", "<"); | |
76 t = t:gsub(">", ">"); | |
77 t = t:gsub("(http://[%a%d@%.:/&%?=%-_#]+)", [[<a href="%1">%1</a>]]); | |
78 t = t:gsub("\n", "<br />"); | |
79 return t; | |
80 end | |
81 | |
82 function splitUrl(url) | |
83 local tmp = url:sub(string.len("/muc_log/") + 1); | |
84 local day = nil; | |
85 local room = nil; | |
86 local component = nil; | |
87 local at = nil; | |
88 local slash = nil; | |
89 local slash2 = nil; | |
90 | |
91 slash = tmp:find("/"); | |
92 if slash then | |
93 component = tmp:sub(1, slash - 1); | |
94 if tmp:len() > slash then | |
95 room = tmp:sub(slash + 1); | |
96 slash = room:find("/"); | |
97 if slash then | |
98 tmp = room; | |
99 room = tmp:sub(1, slash - 1); | |
100 if tmp:len() > slash then | |
101 day = tmp:sub(slash + 1); | |
102 slash = day:find("/"); | |
103 if slash then | |
104 day = day:sub(1, slash - 1); | |
105 end | |
106 end | |
107 end | |
108 end | |
109 end | |
110 | |
111 return room, component, day; | |
112 end | |
113 | |
114 local function generateComponentListSiteContent() | |
115 local components = ""; | |
116 for component,muc_host in pairs(muc_hosts or {}) do | |
117 components = components .. html.components.bit:gsub("###COMPONENT###", component); | |
118 end | |
119 if components ~= "" then | |
120 return html.components.body:gsub("###COMPONENTS_STUFF###", components); | |
121 end | |
122 end | |
123 | |
124 local function generateRoomListSiteContent(component) | |
125 local rooms = ""; | |
126 if prosody.hosts[component] and prosody.hosts[component].muc ~= nil then | |
127 for jid, room in pairs(prosody.hosts[component].muc.rooms) do | |
128 local node = splitJid(jid); | |
129 if not room._data.hidden and node then | |
130 rooms = rooms .. html.rooms.bit:gsub("###ROOM###", node):gsub("###COMPONENT###", component); | |
131 end | |
132 end | |
133 if rooms ~= "" then | |
134 return html.rooms.body:gsub("###ROOMS_STUFF###", rooms):gsub("###COMPONENT###", component); | |
135 end | |
136 end | |
137 end | |
138 | |
139 -- Calendar stuff | |
140 local function getDaysForMonth(month, year) | |
141 local daysCount = 30; | |
142 local leapyear = false; | |
143 | |
144 if year%4 == 0 and year%100 == 0 then | |
145 if year%400 == 0 then | |
146 leapyear = true; | |
147 else | |
148 leapyear = false; -- turn of the century but not a leapyear | |
149 end | |
150 elseif year%4 == 0 then | |
151 leapyear = true; | |
152 end | |
153 | |
154 if month == 2 and leapyear then | |
155 daysCount = 29; | |
156 elseif month == 2 and not leapyear then | |
157 daysCount = 28; | |
158 elseif month < 8 and month%2 == 1 or | |
159 month >= 8 and month%2 == 0 | |
160 then | |
161 daysCount = 31; | |
162 end | |
163 return daysCount; | |
164 end | |
165 | |
166 local function createMonth(month, year, dayCallback) | |
167 local htmlStr = html.month.header; | |
168 local days = getDaysForMonth(month, year); | |
169 local time = os_time{year=year, month=month, day=1}; | |
170 local dow = tostring(os_date("%a", time)) | |
171 local title = tostring(os_date("%B", time)); | |
172 local weekDays = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; | |
173 local weekDay = 0; | |
174 local weeks = 1; | |
175 local logAvailableForMinimumOneDay = false; | |
176 | |
177 local weekDaysHtml = ""; | |
178 for _, tmp in ipairs(weekDays) do | |
179 weekDaysHtml = weekDaysHtml .. html.month.weekDay:gsub("###DAY###", tmp) .. "\n"; | |
180 end | |
181 | |
182 htmlStr = htmlStr:gsub("###TITLE###", title):gsub("###WEEKDAYS###", weekDaysHtml); | |
183 | |
184 for i = 1, 31 do | |
185 weekDay = weekDay + 1; | |
186 if weekDay == 1 then htmlStr = htmlStr .. "<tr>\n"; end | |
187 if i == 1 then | |
188 for _, tmp in ipairs(weekDays) do | |
189 if dow ~= tmp then | |
190 htmlStr = htmlStr .. html.month.emptyDay .. "\n"; | |
191 weekDay = weekDay + 1; | |
192 else | |
193 break; | |
194 end | |
195 end | |
196 end | |
197 if i < days + 1 then | |
198 local tmp = tostring("<font color='#DDDDDD'>"..tostring(i).."</font>"); | |
199 if dayCallback ~= nil and dayCallback.callback ~= nil then | |
200 tmp = dayCallback.callback(dayCallback.path, i, month, year); | |
201 end | |
202 if tmp == nil then | |
203 tmp = tostring("<font color='#DDDDDD'>"..tostring(i).."</font>"); | |
204 else | |
205 logAvailableForMinimumOneDay = true; | |
206 end | |
207 htmlStr = htmlStr .. html.month.day:gsub("###DAY###", tmp) .. "\n"; | |
208 end | |
209 | |
210 if i >= days then | |
211 break; | |
212 end | |
213 | |
214 if weekDay == 7 then | |
215 weekDay = 0; | |
216 weeks = weeks + 1; | |
217 htmlStr = htmlStr .. "</tr>\n"; | |
218 end | |
219 end | |
220 | |
221 if weekDay + 1 < 8 or weeks < 6 then | |
222 weekDay = weekDay + 1; | |
223 if weekDay > 7 then | |
224 weekDay = 1; | |
225 end | |
226 if weekDay == 1 then | |
227 weeks = weeks + 1; | |
228 end | |
229 for y = weeks, 6 do | |
230 if weekDay == 1 then | |
231 htmlStr = htmlStr .. "<tr>\n"; | |
232 end | |
233 for i = weekDay, 7 do | |
234 htmlStr = htmlStr .. html.month.emptyDay .. "\n"; | |
235 end | |
236 weekDay = 1 | |
237 htmlStr = htmlStr .. "</tr>\n"; | |
238 end | |
239 end | |
240 htmlStr = htmlStr .. html.month.footer; | |
241 if logAvailableForMinimumOneDay then | |
242 return htmlStr; | |
243 end | |
244 end | |
245 | |
246 local function createYear(year, dayCallback) | |
247 local year = year; | |
248 local tmp; | |
249 if tonumber(year) <= 99 then | |
250 year = year + 2000; | |
251 end | |
252 local htmlStr = "<div name='yearDiv' style='padding: 40px; text-align: center;'>" .. html.year.title:gsub("###YEAR###", tostring(year)); | |
253 for i=1, 12 do | |
254 tmp = createMonth(i, year, dayCallback); | |
255 if tmp then | |
256 htmlStr = htmlStr .. "<div style='float: left; padding: 5px;'>\n" .. tmp .. "</div>\n"; | |
257 end | |
258 end | |
259 return htmlStr .. "</div><br style='clear:both;'/> \n"; | |
260 end | |
261 | |
262 local function perDayCallback(path, day, month, year) | |
263 local year = year; | |
264 if year > 2000 then | |
265 year = year - 2000; | |
266 end | |
267 local bareDay = str_format("%.02d%.02d%.02d", year, month, day); | |
268 local attributes, err = lfs.attributes(path.."/"..bareDay) | |
269 if attributes ~= nil and attributes.mode == "directory" then | |
270 local s = html.days.bit; | |
271 s = s:gsub("###BARE_DAY###", bareDay); | |
272 s = s:gsub("###DAY###", day); | |
273 return s; | |
274 end | |
275 return; | |
276 end | |
277 | |
278 local function generateDayListSiteContentByRoom(bareRoomJid) | |
279 local days = ""; | |
280 local arrDays = {}; | |
281 local tmp; | |
282 local node, host, resource = splitJid(bareRoomJid); | |
283 local path = data_getpath(node, host, datastore); | |
284 local room = nil; | |
285 local attributes = nil; | |
286 | |
287 path = path:gsub("/[^/]*$", ""); | |
288 attributes = lfs.attributes(path); | |
289 if muc_hosts ~= nil and muc_hosts[host] and prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil and prosody.hosts[host].muc.rooms[bareRoomJid] ~= nil then | |
290 room = prosody.hosts[host].muc.rooms[bareRoomJid]; | |
291 if room._data.hidden then | |
292 room = nil | |
293 end | |
294 end | |
295 if attributes ~= nil and room ~= nil then | |
296 local alreadyDoneYears = {}; | |
297 for file in lfs.dir(path) do | |
298 local year, month, day = file:match("^(%d%d)(%d%d)(%d%d)"); | |
299 if year ~= nil and alreadyDoneYears[year] == nil then | |
300 days = days .. createYear(year, {callback=perDayCallback, path=path}); | |
301 alreadyDoneYears[year] = true; | |
302 end | |
303 end | |
304 end | |
305 | |
306 if days ~= "" then | |
307 tmp = html.days.body:gsub("###DAYS_STUFF###", days); | |
308 return tmp:gsub("###JID###", bareRoomJid); | |
309 end | |
310 end | |
311 | |
312 local function parseIqStanza(stanza, timeStuff, nick) | |
313 local text = nil; | |
314 local victim = nil; | |
315 if(stanza.attr.type == "set") then | |
316 for _,tag in ipairs(stanza) do | |
317 if tag.tag == "query" then | |
318 for _,item in ipairs(tag) do | |
319 if item.tag == "item" and item.attr.nick ~= nil and tostring(item.attr.role) == 'none' then | |
320 victim = item.attr.nick; | |
321 for _,reason in ipairs(item) do | |
322 if reason.tag == "reason" then | |
323 text = reason[1]; | |
324 break; | |
325 end | |
326 end | |
327 break; | |
328 end | |
329 end | |
330 break; | |
331 end | |
332 end | |
333 if victim ~= nil then | |
334 if text ~= nil then | |
335 text = html.day.reason:gsub("###REASON###", htmlEscape(text)); | |
336 else | |
337 text = ""; | |
338 end | |
339 return html.day.kick:gsub("###TIME_STUFF###", timeStuff):gsub("###VICTIM###", victim):gsub("###REASON_STUFF###", text); | |
340 end | |
341 end | |
342 return; | |
343 end | |
344 | |
345 local function parsePresenceStanza(stanza, timeStuff, nick) | |
346 local ret = ""; | |
347 local showJoin = "block" | |
348 | |
349 if config and not config.showJoin then | |
350 showJoin = "none"; | |
351 end | |
352 | |
353 if stanza.attr.type == nil then | |
354 local showStatus = "block" | |
355 if config and not config.showStatus then | |
356 showStatus = "none"; | |
357 end | |
358 local show, status = nil, ""; | |
359 local alreadyJoined = false; | |
360 for _, tag in ipairs(stanza) do | |
361 if tag.tag == "alreadyJoined" then | |
362 alreadyJoined = true; | |
363 elseif tag.tag == "show" then | |
364 show = tag[1]; | |
365 elseif tag.tag == "status" then | |
366 status = tag[1]; | |
367 end | |
368 end | |
369 if alreadyJoined == true then | |
370 if show == nil then | |
371 show = "online"; | |
372 end | |
373 ret = html.day.presence.statusChange:gsub("###TIME_STUFF###", timeStuff); | |
374 if status ~= "" then | |
375 status = html.day.presence.statusText:gsub("###STATUS###", htmlEscape(status)); | |
376 end | |
377 ret = ret:gsub("###SHOW###", show):gsub("###NICK###", nick):gsub("###SHOWHIDE###", showStatus):gsub("###STATUS_STUFF###", status); | |
378 else | |
379 ret = html.day.presence.join:gsub("###TIME_STUFF###", timeStuff):gsub("###SHOWHIDE###", showJoin):gsub("###NICK###", nick); | |
380 end | |
381 elseif stanza.attr.type ~= nil and stanza.attr.type == "unavailable" then | |
382 | |
383 ret = html.day.presence.leave:gsub("###TIME_STUFF###", timeStuff):gsub("###SHOWHIDE###", showJoin):gsub("###NICK###", nick); | |
384 end | |
385 return ret; | |
386 end | |
387 | |
388 local function parseMessageStanza(stanza, timeStuff, nick) | |
389 local body, title, ret = nil, nil, ""; | |
390 | |
391 for _,tag in ipairs(stanza) do | |
392 if tag.tag == "body" then | |
393 body = tag[1]; | |
394 if nick ~= nil then | |
395 break; | |
396 end | |
397 elseif tag.tag == "nick" and nick == nil then | |
398 nick = htmlEscape(tag[1]); | |
399 if body ~= nil or title ~= nil then | |
400 break; | |
401 end | |
402 elseif tag.tag == "subject" then | |
403 title = tag[1]; | |
404 if nick ~= nil then | |
405 break; | |
406 end | |
407 end | |
408 end | |
409 if nick ~= nil and body ~= nil then | |
410 body = htmlEscape(body); | |
411 local me = body:find("^/me"); | |
412 local template = ""; | |
413 if not me then | |
414 template = html.day.message; | |
415 else | |
416 template = html.day.messageMe; | |
417 body = body:gsub("^/me ", ""); | |
418 end | |
419 ret = template:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick):gsub("###MSG###", body); | |
420 elseif nick ~= nil and title ~= nil then | |
421 title = htmlEscape(title); | |
422 ret = html.day.titleChange:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick):gsub("###TITLE###", title); | |
423 end | |
424 return ret; | |
425 end | |
426 | |
427 local function incrementDay(bare_day) | |
428 local year, month, day = bare_day:match("^(%d%d)(%d%d)(%d%d)"); | |
429 local leapyear = false; | |
430 module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year)) | |
431 | |
432 day = tonumber(day); | |
433 month = tonumber(month); | |
434 year = tonumber(year); | |
435 | |
436 if year%4 == 0 and year%100 == 0 then | |
437 if year%400 == 0 then | |
438 leapyear = true; | |
439 else | |
440 leapyear = false; -- turn of the century but not a leapyear | |
441 end | |
442 elseif year%4 == 0 then | |
443 leapyear = true; | |
444 end | |
445 | |
446 if (month == 2 and leapyear and day + 1 > 29) or | |
447 (month == 2 and not leapyear and day + 1 > 28) or | |
448 (month < 8 and month%2 == 1 and day + 1 > 31) or | |
449 (month < 8 and month%2 == 0 and day + 1 > 30) or | |
450 (month >= 8 and month%2 == 0 and day + 1 > 31) or | |
451 (month >= 8 and month%2 == 1 and day + 1 > 30) | |
452 then | |
453 if month + 1 > 12 then | |
454 year = year + 1; | |
455 else | |
456 month = month + 1; | |
457 end | |
458 else | |
459 day = day + 1; | |
460 end | |
461 return strformat("%.02d%.02d%.02d", year, month, day); | |
462 end | |
463 | |
464 local function findNextDay(bareRoomJid, bare_day) | |
465 local node, host, resource = splitJid(bareRoomJid); | |
466 local day = incrementDay(bare_day); | |
467 local max_trys = 7; | |
468 | |
469 module:log("debug", day); | |
470 while(not checkDatastorePathExists(node, host, day, false)) do | |
471 max_trys = max_trys - 1; | |
472 if max_trys == 0 then | |
473 break; | |
474 end | |
475 day = incrementDay(day); | |
476 end | |
477 if max_trys == 0 then | |
478 return nil; | |
479 else | |
480 return day; | |
481 end | |
482 end | |
483 | |
484 local function decrementDay(bare_day) | |
485 local year, month, day = bare_day:match("^(%d%d)(%d%d)(%d%d)"); | |
486 module:log("debug", tostring(day).."/"..tostring(month).."/"..tostring(year)) | |
487 day = tonumber(day); | |
488 month = tonumber(month); | |
489 year = tonumber(year); | |
490 | |
491 if day - 1 == 0 then | |
492 if month - 1 == 0 then | |
493 year = year - 1; | |
494 else | |
495 month = month - 1; | |
496 end | |
497 else | |
498 day = day - 1; | |
499 end | |
500 return strformat("%.02d%.02d%.02d", year, month, day); | |
501 end | |
502 | |
503 local function findPreviousDay(bareRoomJid, bare_day) | |
504 local node, host, resource = splitJid(bareRoomJid); | |
505 local day = decrementDay(bare_day); | |
506 local max_trys = 7; | |
507 module:log("debug", day); | |
508 while(not checkDatastorePathExists(node, host, day, false)) do | |
509 max_trys = max_trys - 1; | |
510 if max_trys == 0 then | |
511 break; | |
512 end | |
513 day = decrementDay(day); | |
514 end | |
515 if max_trys == 0 then | |
516 return nil; | |
517 else | |
518 return day; | |
519 end | |
520 end | |
521 | |
522 local function parseDay(bareRoomJid, roomSubject, bare_day) | |
523 local ret = ""; | |
524 local year; | |
525 local month; | |
526 local day; | |
527 local tmp; | |
528 local node, host, resource = splitJid(bareRoomJid); | |
529 local year, month, day = bare_day:match("^(%d%d)(%d%d)(%d%d)"); | |
530 local previousDay = findPreviousDay(bareRoomJid, bare_day); | |
531 local nextDay = findNextDay(bareRoomJid, bare_day); | |
532 | |
533 if bare_day ~= nil then | |
534 local data = data_load(node, host, datastore .. "/" .. bare_day); | |
535 if data ~= nil then | |
536 for i=1, #data, 1 do | |
537 local stanza = lom.parse(data[i]); | |
538 if stanza ~= nil and stanza.attr ~= nil and stanza.attr.time ~= nil then | |
539 local timeStuff = html.day.time:gsub("###TIME###", stanza.attr.time); | |
540 if stanza[1] ~= nil then | |
541 local nick; | |
542 local tmp; | |
543 | |
544 -- grep nick from "from" resource | |
545 if stanza[1].attr.from ~= nil then -- presence and messages | |
546 nick = htmlEscape(stanza[1].attr.from:match("/(.+)$")); | |
547 elseif stanza[1].attr.to ~= nil then -- iq | |
548 nick = htmlEscape(stanza[1].attr.to:match("/(.+)$")); | |
549 end | |
550 | |
551 if stanza[1].tag == "presence" and nick ~= nil then | |
552 tmp = parsePresenceStanza(stanza[1], timeStuff, nick); | |
553 elseif stanza[1].tag == "message" then | |
554 tmp = parseMessageStanza(stanza[1], timeStuff, nick); | |
555 elseif stanza[1].tag == "iq" then | |
556 tmp = parseIqStanza(stanza[1], timeStuff, nick); | |
557 else | |
558 module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bareRoomJid, year .. "/" .. month .. "/" .. day); | |
559 end | |
560 if tmp ~= nil then | |
561 ret = ret .. tmp | |
562 tmp = nil; | |
563 end | |
564 end | |
565 end | |
566 end | |
567 end | |
568 if ret ~= "" then | |
569 if nextDay then | |
570 nextDay = html.day.dayLink:gsub("###DAY###", nextDay):gsub("###TEXT###", "next day >>") | |
571 end | |
572 if previousDay then | |
573 previousDay = html.day.dayLink:gsub("###DAY###", previousDay):gsub("###TEXT###", "<< previous day"); | |
574 end | |
575 tmp = html.day.body:gsub("###DAY_STUFF###", ret):gsub("###JID###", bareRoomJid); | |
576 tmp = tmp:gsub("###YEAR###", year):gsub("###MONTH###", month):gsub("###DAY###", day); | |
577 tmp = tmp:gsub("###TITLE_STUFF###", html.day.title:gsub("###TITLE###", roomSubject)); | |
578 tmp = tmp:gsub("###STATUS_CHECKED###", config.showStatus and "checked='checked'" or ""); | |
579 tmp = tmp:gsub("###JOIN_CHECKED###", config.showJoin and "checked='checked'" or ""); | |
580 tmp = tmp:gsub("###NEXT_LINK###", nextDay or ""); | |
581 tmp = tmp:gsub("###PREVIOUS_LINK###", previousDay or ""); | |
582 | |
583 return tmp; | |
584 end | |
585 end | |
586 end | |
587 | |
588 function handle_request(method, body, request) | |
589 local node, host, day = splitUrl(request.url.path); | |
590 | |
591 if muc_hosts ~= nil then | |
592 if node ~= nil and host ~= nil then | |
593 local bare = node .. "@" .. host; | |
594 if prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil then | |
595 if prosody.hosts[host].muc.rooms[bare] ~= nil then | |
596 local room = prosody.hosts[host].muc.rooms[bare]; | |
597 if day == nil then | |
598 return createDoc(generateDayListSiteContentByRoom(bare)); | |
599 else | |
600 local subject = "" | |
601 if room._data ~= nil and room._data.subject ~= nil then | |
602 subject = room._data.subject; | |
603 end | |
604 return createDoc(parseDay(bare, subject, day)); | |
605 end | |
606 else | |
607 return createDoc(generateRoomListSiteContent(host)); | |
608 end | |
609 else | |
610 return createDoc(generateComponentListSiteContent()); | |
611 end | |
612 elseif host ~= nil then | |
613 return createDoc(generateRoomListSiteContent(host)); | |
614 else | |
615 return createDoc(generateComponentListSiteContent()); | |
616 end | |
617 end | |
618 return; | |
619 end | |
620 | |
621 -- Compatibility: Lua-5.1 | |
622 function split(str, pat) | |
623 local t = {} -- NOTE: use {n = 0} in Lua-5.0 | |
624 local fpat = "(.-)" .. pat | |
625 local last_end = 1 | |
626 local s, e, cap = str:find(fpat, 1) | |
627 while s do | |
628 if s ~= 1 or cap ~= "" then | |
629 table.insert(t,cap) | |
630 end | |
631 last_end = e+1 | |
632 s, e, cap = str:find(fpat, last_end) | |
633 end | |
634 if last_end <= #str then | |
635 cap = str:sub(last_end) | |
636 table.insert(t, cap) | |
637 end | |
638 return t | |
639 end | |
640 | |
641 local function assign(arr, content) | |
642 local tmp = html; | |
643 local idx = nil; | |
644 for _,i in ipairs(arr) do | |
645 if idx ~= nil then | |
646 if tmp[idx] == nil then | |
647 tmp[idx] = {}; | |
648 end | |
649 tmp = tmp[idx]; | |
650 end | |
651 idx = i; | |
652 end | |
653 tmp[idx] = content; | |
654 end | |
655 | |
656 local function readFile(filepath) | |
657 local f = assert(io_open(filepath, "r")); | |
658 local t = f:read("*all"); | |
659 f:close() | |
660 return t; | |
661 end | |
662 | |
663 local function loadTheme(path) | |
664 local iter = lfs.dir(path); | |
665 for file in iter do | |
666 if file ~= "." and file ~= ".." then | |
667 module:log("debug", "opening theme file: " .. file); | |
668 local tmp = split(file:gsub("\.html$", ""), "_"); | |
669 local content = readFile(path .. "/" .. file); | |
670 assign(tmp, content); | |
671 end | |
672 end | |
673 return true; | |
674 end | |
675 | |
676 function module.load() | |
677 config = config_get("*", "core", "muc_log_http") or {}; | |
678 if config.showStatus == nil then | |
679 config.showStatus = true; | |
680 end | |
681 if config.showJoin == nil then | |
682 config.showJoin = true; | |
683 end | |
684 | |
685 theme = config.theme or "default"; | |
686 local themePath = themesParent .. "/" .. tostring(theme); | |
687 local attributes, err = lfs.attributes(themePath); | |
688 if attributes == nil or attributes.mode ~= "directory" then | |
689 module:log("error", "Theme folder of theme \"".. tostring(theme) .. "\" isn't existing. expected Path: " .. themePath); | |
690 return false; | |
691 end | |
692 | |
693 -- module:log("debug", (require "util.serialization").serialize(html)); | |
694 if(not loadTheme(themePath)) then | |
695 module:log("error", "Theme \"".. tostring(theme) .. "\" is missing something."); | |
696 return false; | |
697 end | |
698 -- module:log("debug", (require "util.serialization").serialize(html)); | |
699 | |
700 httpserver.new_from_config({ config.http_port or true }, handle_request, { base = urlBase, ssl = false, port = 5290 }); | |
701 | |
702 for jid, host in pairs(prosody.hosts) do | |
703 if host.muc then | |
704 local enabledModules = config_get(jid, "core", "modules_enabled"); | |
705 if enabledModules then | |
706 for _,mod in ipairs(enabledModules) do | |
707 if(mod == "muc_log") then | |
708 module:log("debug", "component: %s", tostring(jid)); | |
709 muc_hosts[jid] = true; | |
710 break; | |
711 end | |
712 end | |
713 end | |
714 end | |
715 end | |
716 module:log("debug", "loaded mod_muc_log_http"); | |
717 end | |
718 | |
719 function module.unload() | |
720 muc_hosts = nil; | |
721 module:log("debug", "unloaded mod_muc_log_http"); | |
722 end | |
723 | |
724 module:add_event_hook("component-activated", function(component, config) | |
725 if config.core and config.core.modules_enabled then | |
726 for _,mod in ipairs(config.core.modules_enabled) do | |
727 if(mod == "muc_log") then | |
728 module:log("debug", "component: %s", tostring(component)); | |
729 muc_hosts[component] = true; | |
730 break; | |
731 end | |
732 end | |
733 end | |
734 end); |