aboutsummaryrefslogtreecommitdiff
path: root/src/mod_muc_log.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_muc_log.erl')
-rw-r--r--src/mod_muc_log.erl180
1 files changed, 89 insertions, 91 deletions
diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl
index d94151418..1f32f6f9b 100644
--- a/src/mod_muc_log.erl
+++ b/src/mod_muc_log.erl
@@ -5,7 +5,7 @@
%%% Created : 12 Mar 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
-%%% ejabberd, Copyright (C) 2002-2015 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -25,6 +25,10 @@
-module(mod_muc_log).
+-protocol({xep, 334, '0.2'}).
+
+-behaviour(ejabberd_config).
+
-author('badlop@process-one.net').
-behaviour(gen_server).
@@ -35,21 +39,17 @@
-export([start_link/2, start/2, stop/1, transform_module_options/1,
check_access_log/2, add_to_log/5]).
-%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2, code_change/3]).
+ handle_info/2, terminate/2, code_change/3,
+ mod_opt_type/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("jlib.hrl").
-
+-include("mod_muc.hrl").
-include("mod_muc_room.hrl").
-%% Copied from mod_muc/mod_muc.erl
--record(muc_online_room, {name_host = {<<>>, <<>>} :: {binary(), binary()},
- pid = self() :: pid()}).
-
-define(T(Text), translate:translate(Lang, Text)).
-define(PROCNAME, ejabberd_mod_muc_log).
-record(room, {jid, title, subject, subject_author, config}).
@@ -74,23 +74,14 @@
%%====================================================================
%% API
%%====================================================================
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the server
-%%--------------------------------------------------------------------
start_link(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
start(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
- ChildSpec =
- {Proc,
- {?MODULE, start_link, [Host, Opts]},
- temporary,
- 1000,
- worker,
- [?MODULE]},
+ ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
+ temporary, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
stop(Host) ->
@@ -121,19 +112,11 @@ transform_module_options(Opts) ->
%%====================================================================
%% gen_server callbacks
%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%--------------------------------------------------------------------
init([Host, Opts]) ->
OutDir = gen_mod:get_opt(outdir, Opts,
fun iolist_to_binary/1,
<<"www/muc">>),
- DirType = gen_mod:get_opt(dirtype, Opts,
+ DirType = gen_mod:get_opt(dirtype, Opts,
fun(subdirs) -> subdirs;
(plain) -> plain
end, subdirs),
@@ -179,31 +162,17 @@ init([Host, Opts]) ->
{ok,
#logstate{host = Host, out_dir = OutDir,
dir_type = DirType, dir_name = DirName,
- file_format = FileFormat, file_permissions = FilePermissions, css_file = CSSFile,
+ file_format = FileFormat, css_file = CSSFile,
+ file_permissions = FilePermissions,
access = AccessLog, lang = Lang, timezone = Timezone,
spam_prevention = NoFollow, top_link = Top_link}}.
-%%--------------------------------------------------------------------
-%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% {stop, Reason, State}
-%% Description: Handling call messages
-%%--------------------------------------------------------------------
handle_call({check_access_log, ServerHost, FromJID}, _From, State) ->
Reply = acl:match_rule(ServerHost, State#logstate.access, FromJID),
{reply, Reply, State};
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
handle_cast({add_to_log, Type, Data, Room, Opts}, State) ->
case catch add_to_log2(Type, Data, Room, Opts, State) of
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
@@ -212,49 +181,30 @@ handle_cast({add_to_log, Type, Data, Room, Opts}, State) ->
{noreply, State};
handle_cast(_Msg, State) -> {noreply, State}.
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
handle_info(_Info, State) -> {noreply, State}.
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> void()
-%% Description: This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any necessary
-%% cleaning up. When it returns, the gen_server terminates with Reason.
-%% The return value is ignored.
-%%--------------------------------------------------------------------
terminate(_Reason, _State) -> ok.
-%%--------------------------------------------------------------------
-%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) -> {ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
add_to_log2(text, {Nick, Packet}, Room, Opts, State) ->
- case {xml:get_subtag(Packet, <<"no-store">>),
- xml:get_subtag(Packet, <<"no-permanent-store">>)}
- of
- {false, false} ->
- case {xml:get_subtag(Packet, <<"subject">>),
- xml:get_subtag(Packet, <<"body">>)}
- of
- {false, false} -> ok;
- {false, SubEl} ->
- Message = {body, xml:get_tag_cdata(SubEl)},
- add_message_to_log(Nick, Message, Room, Opts, State);
- {SubEl, _} ->
- Message = {subject, xml:get_tag_cdata(SubEl)},
- add_message_to_log(Nick, Message, Room, Opts, State)
- end;
- {_, _} -> ok
+ case has_no_permanent_store_hint(Packet) of
+ false ->
+ case {fxml:get_subtag(Packet, <<"subject">>),
+ fxml:get_subtag(Packet, <<"body">>)}
+ of
+ {false, false} -> ok;
+ {false, SubEl} ->
+ Message = {body, fxml:get_tag_cdata(SubEl)},
+ add_message_to_log(Nick, Message, Room, Opts, State);
+ {SubEl, _} ->
+ Message = {subject, fxml:get_tag_cdata(SubEl)},
+ add_message_to_log(Nick, Message, Room, Opts, State)
+ end;
+ true -> ok
end;
add_to_log2(roomconfig_change, _Occupants, Room, Opts,
State) ->
@@ -327,7 +277,7 @@ build_filename_string(TimeStamp, OutDir, RoomJID,
{Fd, Fn, Fnrel}.
get_room_name(RoomJID) ->
- JID = jlib:string_to_jid(RoomJID), JID#jid.user.
+ JID = jid:from_string(RoomJID), JID#jid.user.
%% calculate day before
get_timestamp_daydiff(TimeStamp, Daydiff) ->
@@ -349,12 +299,11 @@ close_previous_log(Fn, Images_dir, FileFormat) ->
write_last_lines(_, _, plaintext) -> ok;
write_last_lines(F, Images_dir, _FileFormat) ->
-%% list_to_integer/2 was introduced in OTP R14
fw(F, <<"<div class=\"legend\">">>),
fw(F,
<<" <a href=\"http://www.ejabberd.im\"><img "
"style=\"border:0\" src=\"~s/powered-by-ejabbe"
- "rd.png\" alt=\"Powered by ejabberd\"/></a>">>,
+ "rd.png\" alt=\"Powered by ejabberd - robust, scalable and extensible XMPP server\"/></a>">>,
[Images_dir]),
fw(F,
<<" <a href=\"http://www.erlang.org/\"><img "
@@ -378,7 +327,7 @@ write_last_lines(F, Images_dir, _FileFormat) ->
fw(F, <<"</span></div></body></html>">>).
set_filemode(Fn, {FileMode, FileGroup}) ->
- ok = file:change_mode(Fn, list_to_integer(integer_to_list(FileMode), 8)),
+ ok = file:change_mode(Fn, list_to_integer(integer_to_list(FileMode), 8)),
ok = file:change_group(Fn, FileGroup).
htmlize_nick(Nick1, html) ->
@@ -397,7 +346,7 @@ add_message_to_log(Nick1, Message, RoomJID, Opts,
Room = get_room_info(RoomJID, Opts),
Nick = htmlize(Nick1, FileFormat),
Nick2 = htmlize_nick(Nick1, FileFormat),
- Now = now(),
+ Now = p1_time_compat:timestamp(),
TimeStamp = case Timezone of
local -> calendar:now_to_local_time(Now);
universal -> calendar:now_to_universal_time(Now)
@@ -951,7 +900,7 @@ put_header_script(F) ->
put_room_config(_F, _RoomConfig, _Lang, plaintext) ->
ok;
put_room_config(F, RoomConfig, Lang, _FileFormat) ->
- {_, Now2, _} = now(),
+ {_, Now2, _} = p1_time_compat:timestamp(),
fw(F, <<"<div class=\"rc\">">>),
fw(F,
<<"<div class=\"rct\" onclick=\"sh('a~p');return "
@@ -968,7 +917,7 @@ put_room_occupants(_F, _RoomOccupants, _Lang,
ok;
put_room_occupants(F, RoomOccupants, Lang,
_FileFormat) ->
- {_, Now2, _} = now(),
+ {_, Now2, _} = p1_time_compat:timestamp(),
%% htmlize
%% The default behaviour is to ignore the nofollow spam prevention on links
%% (NoFollow=false)
@@ -1048,7 +997,7 @@ get_room_info(RoomJID, Opts) ->
{value, {_, SA}} -> SA;
false -> <<"">>
end,
- #room{jid = jlib:jid_to_string(RoomJID), title = Title,
+ #room{jid = jid:to_string(RoomJID), title = Title,
subject = Subject, subject_author = SubjectAuthor,
config = Opts}.
@@ -1163,10 +1112,7 @@ roomoccupants_to_string(Users, _FileFormat) ->
Users1 /= []],
iolist_to_binary([<<"<div class=\"rcot\">">>, Res, <<"</div>">>]).
-%% Users = [{JID, Nick, Role}]
group_by_role(Users) ->
-%% Role = atom()
-%% Users = [{JID, Nick}]
{Ms, Ps, Vs, Ns} = lists:foldl(fun ({JID, Nick,
moderator},
{Mod, Par, Vis, Non}) ->
@@ -1212,7 +1158,7 @@ role_users_to_string(RoleS, Users) ->
<<RoleS/binary, ": ", UsersString/binary>>.
get_room_occupants(RoomJIDString) ->
- RoomJID = jlib:string_to_jid(RoomJIDString),
+ RoomJID = jid:from_string(RoomJIDString),
RoomName = RoomJID#jid.luser,
MucService = RoomJID#jid.lserver,
StateData = get_room_state(RoomName, MucService),
@@ -1238,10 +1184,11 @@ get_room_state(RoomPid) ->
get_state),
R.
-get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME).
+get_proc_name(Host) ->
+ gen_mod:get_module_proc(Host, ?PROCNAME).
calc_hour_offset(TimeHere) ->
- TimeZero = calendar:now_to_universal_time(now()),
+ TimeZero = calendar:universal_time(),
TimeHereHour =
calendar:datetime_to_gregorian_seconds(TimeHere) div
3600,
@@ -1252,3 +1199,54 @@ calc_hour_offset(TimeHere) ->
fjoin(FileList) ->
list_to_binary(filename:join([binary_to_list(File) || File <- FileList])).
+
+has_no_permanent_store_hint(Packet) ->
+ fxml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS)
+ =/= false orelse
+ fxml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS)
+ =/= false orelse
+ fxml:get_subtag_with_xmlns(Packet, <<"no-permanent-store">>, ?NS_HINTS)
+ =/= false orelse
+ fxml:get_subtag_with_xmlns(Packet, <<"no-permanent-storage">>, ?NS_HINTS)
+ =/= false.
+
+mod_opt_type(access_log) ->
+ fun (A) when is_atom(A) -> A end;
+mod_opt_type(cssfile) -> fun iolist_to_binary/1;
+mod_opt_type(dirname) ->
+ fun (room_jid) -> room_jid;
+ (room_name) -> room_name
+ end;
+mod_opt_type(dirtype) ->
+ fun (subdirs) -> subdirs;
+ (plain) -> plain
+ end;
+mod_opt_type(file_format) ->
+ fun (html) -> html;
+ (plaintext) -> plaintext
+ end;
+mod_opt_type(file_permissions) ->
+ fun (SubOpts) ->
+ F = fun ({mode, Mode}, {_M, G}) -> {Mode, G};
+ ({group, Group}, {M, _G}) -> {M, Group}
+ end,
+ lists:foldl(F, {644, 33}, SubOpts)
+ end;
+mod_opt_type(outdir) -> fun iolist_to_binary/1;
+mod_opt_type(spam_prevention) ->
+ fun (B) when is_boolean(B) -> B end;
+mod_opt_type(timezone) ->
+ fun (local) -> local;
+ (universal) -> universal
+ end;
+mod_opt_type(top_link) ->
+ fun ([{S1, S2}]) ->
+ {iolist_to_binary(S1), iolist_to_binary(S2)}
+ end;
+mod_opt_type(_) ->
+ [access_log, cssfile, dirname, dirtype, file_format,
+ file_permissions, outdir, spam_prevention, timezone,
+ top_link].
+
+opt_type(language) -> fun iolist_to_binary/1;
+opt_type(_) -> [language].