* src/mod_muc/mod_muc_log.erl: MUC log files options: plaintext

format; filename with only room name (EJAB-596)
* doc/guide.tex: Document both options
* doc/guide.html: Likewise

SVN Revision: 1531
This commit is contained in:
Badlop 2008-08-18 19:08:30 +00:00
parent 4ae1bda33f
commit e37723f4a2
4 changed files with 182 additions and 100 deletions

View File

@ -1,5 +1,10 @@
2008-08-18 Badlop <badlop@process-one.net>
* src/mod_muc/mod_muc_log.erl: MUC log files options: plaintext
format; filename with only room name (EJAB-596)
* doc/guide.tex: Document both options
* doc/guide.html: Likewise
* src/mod_register.erl: Change password using mod_register always
returns success regardless of real result (EJAB-723)
* src/ejabberd_auth.erl: Likewise

View File

@ -2184,26 +2184,38 @@ file or if they need to use the embedded CSS file. Allowed values are
include the embedded CSS code. With the latter, you can specify the URL of the
custom CSS file (for example: &#X2018;http://example.com/my.css&#X2019;). The default value
is <TT>false</TT>.
</DD><DT CLASS="dt-description"><B><TT>dirname</TT></B></DT><DD CLASS="dd-description">
Allows to configure the name of the room directory.
Allowed values are <TT>room_jid</TT> and <TT>room_name</TT>.
With the first value, the room directory name will be the full room JID.
With the latter, the room directory name will be only the room name,
not including the MUC service name.
The default value is <TT>room_jid</TT>.
</DD><DT CLASS="dt-description"><B><TT>dirtype</TT></B></DT><DD CLASS="dd-description">
The type of the created directories can be specified with this option. Allowed
values are <TT>subdirs</TT> and <TT>plain</TT>. With the first value,
subdirectories are created for each year and month. With the latter, the
names of the log files contain the full date, and there are no subdirectories.
The default value is <TT>subdirs</TT>.
</DD><DT CLASS="dt-description"><B><TT>file_format</TT></B></DT><DD CLASS="dd-description">
Define the format of the log files:
<TT>html</TT> stores in HTML format,
<TT>plaintext</TT> stores in plain text.
The default value is <TT>html</TT>.
</DD><DT CLASS="dt-description"><B><TT>outdir</TT></B></DT><DD CLASS="dd-description">
This option sets the full path to the directory in which the HTML files should
be stored. Make sure the <TT>ejabberd</TT> daemon user has write access on that
directory. The default value is <TT>"www/muc"</TT>.
</DD><DT CLASS="dt-description"><B><TT>timezone</TT></B></DT><DD CLASS="dd-description">
The time zone for the logs is configurable with this option. Allowed values
are <TT>local</TT> and <TT>universal</TT>. With the first value, the local time,
as reported to Erlang by the operating system, will be used. With the latter,
GMT/UTC time will be used. The default value is <TT>local</TT>.
</DD><DT CLASS="dt-description"><B><TT>spam_prevention</TT></B></DT><DD CLASS="dd-description">
To prevent spam, the <TT>spam_prevention</TT> option adds a special attribute
to links that prevent their indexation by search engines. The default value
is <TT>true</TT>, which mean that nofollow attributes will be added to user
submitted links.
</DD><DT CLASS="dt-description"><B><TT>timezone</TT></B></DT><DD CLASS="dd-description">
The time zone for the logs is configurable with this option. Allowed values
are <TT>local</TT> and <TT>universal</TT>. With the first value, the local time,
as reported to Erlang by the operating system, will be used. With the latter,
GMT/UTC time will be used. The default value is <TT>local</TT>.
</DD><DT CLASS="dt-description"><B><TT>top_link</TT></B></DT><DD CLASS="dd-description">
With this option you can customize the link on the top right corner of each
log file. The syntax of this option is <TT>{"URL", "Text"}</TT>. The default
@ -2225,6 +2237,7 @@ time zone will be GMT/UTC. Finally, the top link will be
{access_log, muc},
{cssfile, "http://example.com/my.css"},
{dirtype, plain},
{dirname, room_jid},
{outdir, "/var/www/muclogs"},
{timezone, universal},
{spam_prevention, true},

View File

@ -2828,26 +2828,38 @@ Options:
include the embedded CSS code. With the latter, you can specify the URL of the
custom CSS file (for example: `http://example.com/my.css'). The default value
is \term{false}.
\titem{dirname}\ind{options!dirname}
Allows to configure the name of the room directory.
Allowed values are \term{room\_jid} and \term{room\_name}.
With the first value, the room directory name will be the full room JID.
With the latter, the room directory name will be only the room name,
not including the MUC service name.
The default value is \term{room\_jid}.
\titem{dirtype}\ind{options!dirtype}
The type of the created directories can be specified with this option. Allowed
values are \term{subdirs} and \term{plain}. With the first value,
subdirectories are created for each year and month. With the latter, the
names of the log files contain the full date, and there are no subdirectories.
The default value is \term{subdirs}.
\titem{file\_format}\ind{options!file\_format}
Define the format of the log files:
\term{html} stores in HTML format,
\term{plaintext} stores in plain text.
The default value is \term{html}.
\titem{outdir}\ind{options!outdir}
This option sets the full path to the directory in which the HTML files should
be stored. Make sure the \ejabberd{} daemon user has write access on that
directory. The default value is \term{"www/muc"}.
\titem{timezone}\ind{options!timezone}
The time zone for the logs is configurable with this option. Allowed values
are \term{local} and \term{universal}. With the first value, the local time,
as reported to Erlang by the operating system, will be used. With the latter,
GMT/UTC time will be used. The default value is \term{local}.
\titem{spam\_prevention}\ind{options!spam\_prevention}
To prevent spam, the \term{spam\_prevention} option adds a special attribute
to links that prevent their indexation by search engines. The default value
is \term{true}, which mean that nofollow attributes will be added to user
submitted links.
\titem{timezone}\ind{options!timezone}
The time zone for the logs is configurable with this option. Allowed values
are \term{local} and \term{universal}. With the first value, the local time,
as reported to Erlang by the operating system, will be used. With the latter,
GMT/UTC time will be used. The default value is \term{local}.
\titem{top\_link}\ind{options!top\_link}
With this option you can customize the link on the top right corner of each
log file. The syntax of this option is \term{\{"URL", "Text"\}}. The default
@ -2872,6 +2884,7 @@ Examples:
{access_log, muc},
{cssfile, "http://example.com/my.css"},
{dirtype, plain},
{dirname, room_jid},
{outdir, "/var/www/muclogs"},
{timezone, universal},
{spam_prevention, true},

View File

@ -52,6 +52,8 @@
-record(state, {host,
out_dir,
dir_type,
dir_name,
file_format,
css_file,
access,
lang,
@ -113,6 +115,8 @@ check_access_log(Host, From) ->
init([Host, Opts]) ->
OutDir = gen_mod:get_opt(outdir, Opts, "www/muc"),
DirType = gen_mod:get_opt(dirtype, Opts, subdirs),
DirName = gen_mod:get_opt(dirname, Opts, room_jid),
FileFormat = gen_mod:get_opt(file_format, Opts, html), % Allowed values: html|plaintext
CSSFile = gen_mod:get_opt(cssfile, Opts, false),
AccessLog = gen_mod:get_opt(access_log, Opts, muc_admin),
Timezone = gen_mod:get_opt(timezone, Opts, local),
@ -129,6 +133,8 @@ init([Host, Opts]) ->
{ok, #state{host = Host,
out_dir = OutDir,
dir_type = DirType,
dir_name = DirName,
file_format = FileFormat,
css_file = CSSFile,
access = AccessLog,
lang = Lang,
@ -231,10 +237,10 @@ add_to_log2(kickban, {Nick, Reason, Code}, Room, Opts, State) ->
%%----------------------------------------------------------------------
%% Core
build_filename_string(TimeStamp, OutDir, RoomJID, DirType) ->
build_filename_string(TimeStamp, OutDir, RoomJID, DirType, DirName, FileFormat) ->
{{Year, Month, Day}, _Time} = TimeStamp,
% Directory and file names
%% Directory and file names
{Dir, Filename, Rel} =
case DirType of
subdirs ->
@ -248,55 +254,75 @@ build_filename_string(TimeStamp, OutDir, RoomJID, DirType) ->
[Year, Month, Day])),
{"", Date, "."}
end,
Fd = filename:join([OutDir, RoomJID, Dir]),
Fn = filename:join([Fd, Filename ++ ".html"]),
Fnrel = filename:join([Rel, Dir, Filename ++ ".html"]),
RoomString = case DirName of
room_jid -> RoomJID;
room_name -> get_room_name(RoomJID)
end,
Extension = case FileFormat of
html -> ".html";
plaintext -> ".txt"
end,
Fd = filename:join([OutDir, RoomString, Dir]),
Fn = filename:join([Fd, Filename ++ Extension]),
Fnrel = filename:join([Rel, Dir, Filename ++ Extension]),
{Fd, Fn, Fnrel}.
% calculate day before
get_room_name(RoomJID) ->
JID = jlib:string_to_jid(RoomJID),
JID#jid.user.
%% calculate day before
get_timestamp_daydiff(TimeStamp, Daydiff) ->
{Date1, HMS} = TimeStamp,
Date2 = calendar:gregorian_days_to_date(
calendar:date_to_gregorian_days(Date1) + Daydiff),
{Date2, HMS}.
% Try to close the previous day log, if it exists
close_previous_log(Fn, Images_dir) ->
%% Try to close the previous day log, if it exists
close_previous_log(Fn, Images_dir, FileFormat) ->
case file:read_file_info(Fn) of
{ok, _} ->
{ok, F} = file:open(Fn, [append]),
%fw(F, "<div class=\"legend\">ejabberd/mod_muc log<span class=\"w3c\">"),
fw(F, "<div class=\"legend\">"),
fw(F, " <a href=\"http://www.ejabberd.im\"><img style=\"border:0\" src=\"~s/powered-by-ejabberd.png\" alt=\"Powered by ejabberd\"/></a>", [Images_dir]),
fw(F, " <a href=\"http://www.erlang.org/\"><img style=\"border:0\" src=\"~s/powered-by-erlang.png\" alt=\"Powered by Erlang\"/></a>", [Images_dir]),
fw(F, "<span class=\"w3c\">"),
fw(F, " <a href=\"http://validator.w3.org/check?uri=referer\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/valid-xhtml10.png\" alt=\"Valid XHTML 1.0 Transitional\" /></a>", [Images_dir]),
fw(F, " <a href=\"http://jigsaw.w3.org/css-validator/\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/vcss.png\" alt=\"Valid CSS!\"/></a>", [Images_dir]),
fw(F, "</span></div></body></html>"),
write_last_lines(F, Images_dir, FileFormat),
file:close(F);
_ -> ok
end.
write_last_lines(_, _, plaintext) ->
ok;
write_last_lines(F, Images_dir, _FileFormat) ->
%%fw(F, "<div class=\"legend\">ejabberd/mod_muc log<span class=\"w3c\">"),
fw(F, "<div class=\"legend\">"),
fw(F, " <a href=\"http://www.ejabberd.im\"><img style=\"border:0\" src=\"~s/powered-by-ejabberd.png\" alt=\"Powered by ejabberd\"/></a>", [Images_dir]),
fw(F, " <a href=\"http://www.erlang.org/\"><img style=\"border:0\" src=\"~s/powered-by-erlang.png\" alt=\"Powered by Erlang\"/></a>", [Images_dir]),
fw(F, "<span class=\"w3c\">"),
fw(F, " <a href=\"http://validator.w3.org/check?uri=referer\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/valid-xhtml10.png\" alt=\"Valid XHTML 1.0 Transitional\" /></a>", [Images_dir]),
fw(F, " <a href=\"http://jigsaw.w3.org/css-validator/\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/vcss.png\" alt=\"Valid CSS!\"/></a>", [Images_dir]),
fw(F, "</span></div></body></html>").
add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
Nick = htmlize(Nick1),
#state{out_dir = OutDir,
dir_type = DirType,
dir_name = DirName,
file_format = FileFormat,
css_file = CSSFile,
lang = Lang,
timezone = Timezone,
spam_prevention = NoFollow,
top_link = TopLink} = State,
Room = get_room_info(RoomJID, Opts),
Nick = htmlize(Nick1, FileFormat),
Nick2 = htmlize("<"++Nick1++">", FileFormat),
Now = now(),
TimeStamp = case Timezone of
local -> calendar:now_to_local_time(Now);
universal -> calendar:now_to_universal_time(Now)
end,
{Fd, Fn, _Dir} = build_filename_string(TimeStamp, OutDir, Room#room.jid, DirType),
{Fd, Fn, _Dir} = build_filename_string(TimeStamp, OutDir, Room#room.jid, DirType, DirName, FileFormat),
{Date, Time} = TimeStamp,
% Open file, create if it does not exist, create parent dirs if needed
%% Open file, create if it does not exist, create parent dirs if needed
case file:read_file_info(Fn) of
{ok, _} ->
{ok, F} = file:open(Fn, [append]);
@ -308,32 +334,32 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
TimeStampYesterday = get_timestamp_daydiff(TimeStamp, -1),
{_FdYesterday, FnYesterday, DatePrev} =
build_filename_string(
TimeStampYesterday, OutDir, Room#room.jid, DirType),
TimeStampYesterday, OutDir, Room#room.jid, DirType, DirName, FileFormat),
TimeStampTomorrow = get_timestamp_daydiff(TimeStamp, 1),
{_FdTomorrow, _FnTomorrow, DateNext} =
build_filename_string(
TimeStampTomorrow, OutDir, Room#room.jid, DirType),
TimeStampTomorrow, OutDir, Room#room.jid, DirType, DirName, FileFormat),
HourOffset = calc_hour_offset(TimeStamp),
put_header(F, Room, Datestring, CSSFile, Lang,
HourOffset, DatePrev, DateNext, TopLink),
HourOffset, DatePrev, DateNext, TopLink, FileFormat),
Images_dir = filename:join([OutDir, "images"]),
Images_dir = filename:join([OutDir, "images"]),
file:make_dir(Images_dir),
create_image_files(Images_dir),
Images_url = case DirType of
subdirs -> "../../../images";
plain -> "../images"
end,
close_previous_log(FnYesterday, Images_url)
create_image_files(Images_dir),
Images_url = case DirType of
subdirs -> "../../../images";
plain -> "../images"
end,
close_previous_log(FnYesterday, Images_url, FileFormat)
end,
% Build message
%% Build message
Text = case Message of
roomconfig_change ->
RoomConfig = roomconfig_to_string(Room#room.config, Lang),
put_room_config(F, RoomConfig, Lang),
RoomConfig = roomconfig_to_string(Room#room.config, Lang, FileFormat),
put_room_config(F, RoomConfig, Lang, FileFormat),
io_lib:format("<font class=\"mrcm\">~s</font><br/>",
[?T("Chatroom configuration modified")]);
join ->
@ -344,19 +370,19 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
[Nick, ?T("leaves the room")]);
{leave, Reason} ->
io_lib:format("<font class=\"ml\">~s ~s: ~s</font><br/>",
[Nick, ?T("leaves the room"), htmlize(Reason,NoFollow)]);
[Nick, ?T("leaves the room"), htmlize(Reason,NoFollow,FileFormat)]);
{kickban, "301", ""} ->
io_lib:format("<font class=\"mb\">~s ~s</font><br/>",
[Nick, ?T("has been banned")]);
{kickban, "301", Reason} ->
io_lib:format("<font class=\"mb\">~s ~s: ~s</font><br/>",
[Nick, ?T("has been banned"), htmlize(Reason)]);
[Nick, ?T("has been banned"), htmlize(Reason,FileFormat)]);
{kickban, "307", ""} ->
io_lib:format("<font class=\"mk\">~s ~s</font><br/>",
[Nick, ?T("has been kicked")]);
{kickban, "307", Reason} ->
io_lib:format("<font class=\"mk\">~s ~s: ~s</font><br/>",
[Nick, ?T("has been kicked"), htmlize(Reason)]);
[Nick, ?T("has been kicked"), htmlize(Reason,FileFormat)]);
{kickban, "321", ""} ->
io_lib:format("<font class=\"mk\">~s ~s</font><br/>",
[Nick, ?T("has been kicked because of an affiliation change")]);
@ -368,18 +394,18 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
[Nick, ?T("has been kicked because of a system shutdown")]);
{nickchange, OldNick} ->
io_lib:format("<font class=\"mnc\">~s ~s ~s</font><br/>",
[htmlize(OldNick), ?T("is now known as"), Nick]);
[htmlize(OldNick,FileFormat), ?T("is now known as"), Nick]);
{subject, T} ->
io_lib:format("<font class=\"msc\">~s~s~s</font><br/>",
[Nick, ?T(" has set the subject to: "), htmlize(T,NoFollow)]);
[Nick, ?T(" has set the subject to: "), htmlize(T,NoFollow,FileFormat)]);
{body, T} ->
case regexp:first_match(T, "^/me\s") of
{match, _, _} ->
io_lib:format("<font class=\"mne\">~s ~s</font><br/>",
[Nick, string:substr(htmlize(T), 5)]);
[Nick, string:substr(htmlize(T,FileFormat), 5)]);
nomatch ->
io_lib:format("<font class=\"mn\">&lt;~s&gt;</font> ~s<br/>",
[Nick, htmlize(T,NoFollow)])
io_lib:format("<font class=\"mn\">~s</font> ~s<br/>",
[Nick2, htmlize(T,NoFollow,FileFormat)])
end
end,
{Hour, Minute, Second} = Time,
@ -388,11 +414,11 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
{_, _, Microsecs} = Now,
STimeUnique = io_lib:format("~s.~w", [STime, Microsecs]),
% Write message
file:write(F, io_lib:format("<a id=\"~s\" name=\"~s\" href=\"#~s\" class=\"ts\">[~s]</a> ~s~n",
[STimeUnique, STimeUnique, STimeUnique, STime, Text])),
%% Write message
fw(F, io_lib:format("<a id=\"~s\" name=\"~s\" href=\"#~s\" class=\"ts\">[~s]</a> ",
[STimeUnique, STimeUnique, STimeUnique, STime]) ++ Text, FileFormat),
% Close file
%% Close file
file:close(F),
ok.
@ -443,13 +469,13 @@ make_dir_rec(Dir) ->
end.
% {ok, F1}=file:open("valid-xhtml10.png", [read]).
% {ok, F1b}=file:read(F1, 1000000).
% c("../../ejabberd/src/jlib.erl").
% jlib:encode_base64(F1b).
%% {ok, F1}=file:open("valid-xhtml10.png", [read]).
%% {ok, F1b}=file:read(F1, 1000000).
%% c("../../ejabberd/src/jlib.erl").
%% jlib:encode_base64(F1b).
image_base64("powered-by-erlang.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAYAAAD+xQNoAAADN0lEQVRo3u1a"
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAYAAAD+xQNoAAADN0lEQVRo3u1a"
"P0waURz+rjGRRQ+nUyRCYmJyDPTapDARaSIbTUjt1gVSh8ZW69aBAR0cWLSx"
"CXWp59LR1jbdqKnGxoQuRZZrSYyHEVM6iZMbHewROA7u3fHvkr5vOn737vcu"
"33ffu9/vcQz+gef5Cij6CkmSGABgFEH29r5SVvqIsTEOHo8HkiQxDBXEOjg9"
@ -471,7 +497,7 @@ image_base64("powered-by-erlang.png") ->
"KF/d/wX3cJvREzl1vAAAAABJRU5ErkJggg==";
image_base64("valid-xhtml10.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAAEjEcpEAAACiFBMVEUAAADe"
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAAEjEcpEAAACiFBMVEUAAADe"
"5+fOezmtra3ejEKlhELvvWO9WlrehELOe3vepaWclHvetVLGc3PerVKcCAj3"
"vVqUjHOUe1JjlL0xOUpjjL2UAAC91ueMrc7vrVKlvdbW3u+EpcbO3ufO1ucY"
"WpSMKQi9SiF7e3taWkoQEAiMczkQSoxaUkpzc3O1lEoICACEazEhGAgIAACE"
@ -527,7 +553,7 @@ image_base64("valid-xhtml10.png") ->
"QZ+RYfpNE/4Xosmq7jsZAJsAAAAASUVORK5CYII=";
image_base64("vcss.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAABKVBMVEUAAAAj"
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAABKVBMVEUAAAAj"
"Ix8MR51ZVUqAdlmdnZ3ejEWLDAuNjY1kiMG0n2d9fX19Ghfrp1FtbW3y39+3"
"Ph6lIRNdXV2qJBFcVUhcVUhPT0/dsmpUfLr57+/u7u4/PDWZAACZAADOp1Gd"
"GxG+SyTgvnNdSySzk16+mkuxw+BOS0BOS0DOzs7MzMy4T09RRDwsJBG+vr73"
@ -555,7 +581,7 @@ image_base64("vcss.png") ->
"AElFTkSuQmCC";
image_base64("powered-by-ejabberd.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAMAAADJG/NaAAAAw1BMVEUAAAAj"
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAMAAADJG/NaAAAAw1BMVEUAAAAj"
"BgYtBAM5AwFCAAAYGAJNAABcAABIDQ5qAAAoJRV7AACFAAAoKSdJHByLAAAw"
"Lwk1NQA1MzFJKyo4NxtDQQBEQT5KSCxSTgBSUBlgQ0JYSEpZWQJPUU5hYABb"
"W0ZiYClcW1poaCVwbQRpaDhzYWNsakhuZ2VrbFZ8dwCEgAB3dnd4d2+OjACD"
@ -579,27 +605,43 @@ image_base64("powered-by-ejabberd.png") ->
"AElFTkSuQmCC".
create_image_files(Images_dir) ->
Filenames = [
"powered-by-ejabberd.png",
"powered-by-erlang.png",
"valid-xhtml10.png",
"vcss.png"
],
lists:foreach(
fun(Filename) ->
Filename_full = filename:join([Images_dir, Filename]),
{ok, F} = file:open(Filename_full, [write]),
Image = jlib:decode_base64(image_base64(Filename)),
io:format(F, "~s", [Image]),
file:close(F)
end,
Filenames),
ok.
Filenames = ["powered-by-ejabberd.png",
"powered-by-erlang.png",
"valid-xhtml10.png",
"vcss.png"
],
lists:foreach(
fun(Filename) ->
Filename_full = filename:join([Images_dir, Filename]),
{ok, F} = file:open(Filename_full, [write]),
Image = jlib:decode_base64(image_base64(Filename)),
io:format(F, "~s", [Image]),
file:close(F)
end,
Filenames),
ok.
fw(F, S, O) -> io:format(F, S ++ "~n", O).
fw(F, S) -> fw(F, S, []).
fw(F, S) -> fw(F, S, [], html).
put_header(F, Room, Date, CSSFile, Lang, Hour_offset, Date_prev, Date_next, Top_link) ->
fw(F, S, O) when is_list(O) ->
fw(F, S, O, html);
fw(F, S, FileFormat) when is_atom(FileFormat) ->
fw(F, S, [], FileFormat).
fw(F, S, O, FileFormat) ->
S1 = io_lib:format(S ++ "~n", O),
S2 = case FileFormat of
html ->
S1;
plaintext ->
{ok, Res, _} = regexp:gsub(S1, "<[^>]*>", ""),
Res
end,
io:format(F, S2, []).
put_header(_, _, _, _, _, _, _, _, _, plaintext) ->
ok;
put_header(F, Room, Date, CSSFile, Lang, Hour_offset, Date_prev, Date_next, Top_link, FileFormat) ->
fw(F, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"),
fw(F, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"~s\" lang=\"~s\">", [Lang, Lang]),
fw(F, "<head>"),
@ -618,8 +660,8 @@ put_header(F, Room, Date, CSSFile, Lang, Hour_offset, Date_prev, Date_next, Top_
{"", ""} -> ok;
{SuA, Su} -> fw(F, "<div class=\"roomsubject\">~s~s~s</div>", [SuA, ?T(" has set the subject to: "), Su])
end,
RoomConfig = roomconfig_to_string(Room#room.config, Lang),
put_room_config(F, RoomConfig, Lang),
RoomConfig = roomconfig_to_string(Room#room.config, Lang, FileFormat),
put_room_config(F, RoomConfig, Lang, FileFormat),
Time_offset_str = case Hour_offset<0 of
true -> io_lib:format("~p", [Hour_offset]);
false -> io_lib:format("+~p", [Hour_offset])
@ -669,7 +711,9 @@ put_header_script(F) ->
fw(F, "else {document.getElementById(e).style.display='none';}}"),
fw(F, "</script>").
put_room_config(F, RoomConfig, Lang) ->
put_room_config(_F, _RoomConfig, _Lang, plaintext) ->
ok;
put_room_config(F, RoomConfig, Lang, _FileFormat) ->
{_, Now2, _} = now(),
fw(F, "<div class=\"rc\">"),
fw(F, "<div class=\"rct\" onclick=\"sh('a~p');return false;\">~s</div>", [Now2, ?T("Room Configuration")]),
@ -680,11 +724,18 @@ put_room_config(F, RoomConfig, Lang) ->
%% The default behaviour is to ignore the nofollow spam prevention on links
%% (NoFollow=false)
htmlize(S1) ->
htmlize(S1, false).
htmlize(S1, html).
htmlize(S1, plaintext) ->
S1;
htmlize(S1, FileFormat) ->
htmlize(S1, false, FileFormat).
%% The NoFollow parameter tell if the spam prevention should be applied to the link found
%% true means 'apply nofollow on links'.
htmlize(S1, NoFollow) ->
htmlize(S1, _NoFollow, plaintext) ->
S1;
htmlize(S1, NoFollow, _FileFormat) ->
S2_list = string:tokens(S1, "\n"),
lists:foldl(
fun(Si, Res) ->
@ -735,20 +786,20 @@ get_room_info(RoomJID, Opts) ->
config = Opts
}.
roomconfig_to_string(Options, Lang) ->
% Get title, if available
roomconfig_to_string(Options, Lang, FileFormat) ->
%% Get title, if available
Title = case lists:keysearch(title, 1, Options) of
{value, Tuple} -> [Tuple];
false -> []
end,
% Remove title from list
%% Remove title from list
Os1 = lists:keydelete(title, 1, Options),
% Order list
%% Order list
Os2 = lists:sort(Os1),
% Add title to ordered list
%% Add title to ordered list
Options2 = Title ++ Os2,
lists:foldl(
@ -765,7 +816,7 @@ roomconfig_to_string(Options, Lang) ->
T ->
case Opt of
password -> "<div class=\"rcoe\">" ++ OptText ++ "</div>";
title -> "<div class=\"rcot\">" ++ ?T("Room title") ++ ": \"" ++ htmlize(T) ++ "\"</div>";
title -> "<div class=\"rcot\">" ++ ?T("Room title") ++ ": \"" ++ htmlize(T, FileFormat) ++ "\"</div>";
_ -> "\"" ++ T ++ "\""
end
end,
@ -795,7 +846,7 @@ get_roomconfig_text(_) -> undefined.
get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME).
calc_hour_offset(TimeHere) ->
TimeZero = calendar:now_to_universal_time(now()),
TimeHereHour = calendar:datetime_to_gregorian_seconds(TimeHere) div 3600,
TimeZeroHour = calendar:datetime_to_gregorian_seconds(TimeZero) div 3600,
TimeHereHour - TimeZeroHour.
TimeZero = calendar:now_to_universal_time(now()),
TimeHereHour = calendar:datetime_to_gregorian_seconds(TimeHere) div 3600,
TimeZeroHour = calendar:datetime_to_gregorian_seconds(TimeZero) div 3600,
TimeHereHour - TimeZeroHour.