Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 101708 | Differences between
and this patch

Collapse All | Expand All

(-)src/mod_muc/mod_muc_room.erl (-10 / +38 lines)
Lines 49-55 Link Here
49
		 password_protected = false,
49
		 password_protected = false,
50
		 password = "",
50
		 password = "",
51
		 anonymous = true,
51
		 anonymous = true,
52
		 logging = false % TODO
52
		 logging = false
53
		}).
53
		}).
54
54
55
-record(user, {jid,
55
-record(user, {jid,
Lines 357-363 Link Here
357
			NewState =
357
			NewState =
358
			    add_user_presence_un(From, Packet, StateData),
358
			    add_user_presence_un(From, Packet, StateData),
359
			send_new_presence(From, NewState),
359
			send_new_presence(From, NewState),
360
			remove_online_user(From, NewState);
360
			Reason = case xml:get_subtag(Packet, "status") of
361
				false -> "";
362
				Status_el -> xml:get_tag_cdata(Status_el)
363
			end,
364
			remove_online_user(From, NewState, Reason);
361
		    _ ->
365
		    _ ->
362
			StateData
366
			StateData
363
		end;
367
		end;
Lines 848-857 Link Here
848
			      nick = Nick,
852
			      nick = Nick,
849
			      role = Role},
853
			      role = Role},
850
			StateData#state.users),
854
			StateData#state.users),
855
    mod_muc_log:add_to_log(join, {Nick, StateData}, StateData),
851
    StateData#state{users = Users}.
856
    StateData#state{users = Users}.
852
857
853
remove_online_user(JID, StateData) ->
858
remove_online_user(JID, StateData) ->
859
	remove_online_user(JID, StateData, "").
860
861
remove_online_user(JID, StateData, Reason) ->
854
    LJID = jlib:jid_tolower(JID),
862
    LJID = jlib:jid_tolower(JID),
863
    mod_muc_log:add_to_log(leave, {LJID, Reason, StateData}, StateData),
855
    Users = ?DICT:erase(LJID, StateData#state.users),
864
    Users = ?DICT:erase(LJID, StateData#state.users),
856
    StateData#state{users = Users}.
865
    StateData#state{users = Users}.
857
866
Lines 1278-1283 Link Here
1278
	   end, StateData#state.users),
1287
	   end, StateData#state.users),
1279
    NewStateData = StateData#state{users = Users},
1288
    NewStateData = StateData#state{users = Users},
1280
    send_nick_changing(JID, OldNick, NewStateData),
1289
    send_nick_changing(JID, OldNick, NewStateData),
1290
    mod_muc_log:add_to_log(nickchange, {OldNick, Nick, StateData}, StateData),
1281
    NewStateData.
1291
    NewStateData.
1282
1292
1283
send_nick_changing(JID, OldNick, StateData) ->
1293
send_nick_changing(JID, OldNick, StateData) ->
Lines 1377-1382 Link Here
1377
    Size = lists:flatlength(xml:element_to_string(SPacket)),
1387
    Size = lists:flatlength(xml:element_to_string(SPacket)),
1378
    Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, TimeStamp, Size},
1388
    Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, TimeStamp, Size},
1379
		   StateData#state.history),
1389
		   StateData#state.history),
1390
    mod_muc_log:add_to_log(text, {FromNick, Packet, StateData}, StateData),
1380
    StateData#state{history = Q1}.
1391
    StateData#state{history = Q1}.
1381
1392
1382
send_history(JID, Shift, StateData) ->
1393
send_history(JID, Shift, StateData) ->
Lines 1883-1888 Link Here
1883
		    end
1894
		    end
1884
	    end,
1895
	    end,
1885
    lists:foreach(fun(J) ->
1896
    lists:foreach(fun(J) ->
1897
			  mod_muc_log:add_to_log(kickban, {J, Reason, Code, StateData}, StateData),
1886
			  send_kickban_presence1(J, Reason, Code, StateData)
1898
			  send_kickban_presence1(J, Reason, Code, StateData)
1887
		  end, LJIDs).
1899
		  end, LJIDs).
1888
1900
Lines 1930-1936 Link Here
1930
			{?NS_XDATA, "cancel"} ->
1942
			{?NS_XDATA, "cancel"} ->
1931
			    {result, [], StateData};
1943
			    {result, [], StateData};
1932
			{?NS_XDATA, "submit"} ->
1944
			{?NS_XDATA, "submit"} ->
1933
			    set_config(XEl, StateData);
1945
			    case check_allowed_log_change(XEl, StateData, From) of
1946
					allow -> set_config(XEl, StateData);
1947
					deny -> {error, ?ERR_BAD_REQUEST}
1948
				end;
1934
			_ ->
1949
			_ ->
1935
			    {error, ?ERR_BAD_REQUEST}
1950
			    {error, ?ERR_BAD_REQUEST}
1936
		    end;
1951
		    end;
Lines 1951-1957 Link Here
1951
	    {xmlelement, Name, Attrs, Els} = SubEl,
1966
	    {xmlelement, Name, Attrs, Els} = SubEl,
1952
	    case xml:remove_cdata(Els) of
1967
	    case xml:remove_cdata(Els) of
1953
		[] ->
1968
		[] ->
1954
		    get_config(Lang, StateData);
1969
		    get_config(Lang, StateData, From);
1955
		[Item] ->
1970
		[Item] ->
1956
		    case xml:get_tag_attr("affiliation", Item) of
1971
		    case xml:get_tag_attr("affiliation", Item) of
1957
			false ->
1972
			false ->
Lines 1980-1985 Link Here
1980
	    {error, ?ERRT_FORBIDDEN(Lang, ErrText)}
1995
	    {error, ?ERRT_FORBIDDEN(Lang, ErrText)}
1981
    end.
1996
    end.
1982
1997
1998
check_allowed_log_change(XEl, StateData, From) ->
1999
	case lists:keymember("logging", 1, jlib:parse_xdata_submit(XEl)) of
2000
		false -> allow;
2001
		true -> mod_muc_log:check_access_log(StateData#state.server_host, From)
2002
	end.
1983
2003
1984
2004
1985
-define(XFIELD(Type, Label, Var, Val),
2005
-define(XFIELD(Type, Label, Var, Val),
Lines 2002-2008 Link Here
2002
	?XFIELD("text-private", Label, Var, Val)).
2022
	?XFIELD("text-private", Label, Var, Val)).
2003
2023
2004
2024
2005
get_config(Lang, StateData) ->
2025
get_config(Lang, StateData, From) ->
2006
    Config = StateData#state.config,
2026
    Config = StateData#state.config,
2007
    Res =
2027
    Res =
2008
	[{xmlelement, "title", [],
2028
	[{xmlelement, "title", [],
Lines 2052-2062 Link Here
2052
			end),
2072
			end),
2053
	 ?BOOLXFIELD("Make room anonymous?",
2073
	 ?BOOLXFIELD("Make room anonymous?",
2054
		     "anonymous",
2074
		     "anonymous",
2055
		     Config#config.anonymous),
2075
		     Config#config.anonymous)
2056
	 ?BOOLXFIELD("Enable logging?",
2076
	] ++ case mod_muc_log:check_access_log(StateData#state.server_host, From) of
2057
		     "logging",
2077
		allow ->
2058
		     Config#config.logging)
2078
		 [?BOOLXFIELD(
2059
	],
2079
				case gen_mod:get_module_opt(StateData#state.server_host, mod_muc, allow_room_log, true) of
2080
					true -> "Enable logging";
2081
					false -> "Enable logging" ++ " (disabled by the admin)"
2082
				end,
2083
				"logging",
2084
				Config#config.logging)];
2085
		_ -> []
2086
	end,
2060
    {result, [{xmlelement, "instructions", [],
2087
    {result, [{xmlelement, "instructions", [],
2061
	       [{xmlcdata,
2088
	       [{xmlcdata,
2062
		 translate:translate(
2089
		 translate:translate(
Lines 2070-2075 Link Here
2070
2097
2071
set_config(XEl, StateData) ->
2098
set_config(XEl, StateData) ->
2072
    XData = jlib:parse_xdata_submit(XEl),
2099
    XData = jlib:parse_xdata_submit(XEl),
2100
    mod_muc_log:add_to_log(roomconfig_change, {XData, StateData}, StateData),
2073
    case XData of
2101
    case XData of
2074
	invalid ->
2102
	invalid ->
2075
	    {error, ?ERR_BAD_REQUEST};
2103
	    {error, ?ERR_BAD_REQUEST};
(-)src/mod_muc/Makefile.in (+1 lines)
Lines 12-17 Link Here
12
EFLAGS = -I .. -pz ..
12
EFLAGS = -I .. -pz ..
13
OBJS   = \
13
OBJS   = \
14
	$(OUTDIR)/mod_muc.beam \
14
	$(OUTDIR)/mod_muc.beam \
15
	$(OUTDIR)/mod_muc_log.beam \
15
	$(OUTDIR)/mod_muc_room.beam
16
	$(OUTDIR)/mod_muc_room.beam
16
17
17
all:    $(OBJS)
18
all:    $(OBJS)
(-)src/mod_muc/mod_muc.erl (+2 lines)
Lines 45-50 Link Here
45
    Access = gen_mod:get_opt(access, Opts, all),
45
    Access = gen_mod:get_opt(access, Opts, all),
46
    AccessCreate = gen_mod:get_opt(access_create, Opts, all),
46
    AccessCreate = gen_mod:get_opt(access_create, Opts, all),
47
    AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
47
    AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
48
    mod_muc_log:start(Opts),
48
    register(gen_mod:get_module_proc(Host, ?PROCNAME),
49
    register(gen_mod:get_module_proc(Host, ?PROCNAME),
49
	     spawn(?MODULE, init,
50
	     spawn(?MODULE, init,
50
		   [MyHost, Host, {Access, AccessCreate, AccessAdmin}])).
51
		   [MyHost, Host, {Access, AccessCreate, AccessAdmin}])).
Lines 258-263 Link Here
258
    ok.
259
    ok.
259
260
260
stop(Host) ->
261
stop(Host) ->
262
    mod_muc_log:stop(),
261
    Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
263
    Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
262
    Proc ! stop,
264
    Proc ! stop,
263
    {wait, Proc}.
265
    {wait, Proc}.
(-)src/mod_muc/mod_muc_log.erl (+481 lines)
Line 0 Link Here
1
%%%----------------------------------------------------------------------
2
%%% File    : mod_muc_log.erl
3
%%% Author  : Badlop
4
%%% Purpose : MUC room logging
5
%%% Created : 
6
%%% Id      : 
7
%%%----------------------------------------------------------------------
8
9
-module(mod_muc_log).
10
-author('').
11
-vsn('').
12
13
%-behaviour(gen_mod).
14
15
-export([start/1,
16
	 stop/0,
17
	 init_log/1,
18
	 check_access_log/2,
19
	 add_to_log/3]).
20
21
-include("ejabberd.hrl").
22
-include("jlib.hrl").
23
-define(T(Text), translate:translate("Lang", Text)).
24
25
-define(PROCNAME, ejabberd_mod_muc_log).
26
-record(room, {jid, title, subject, subject_author, config}).
27
28
%Copied from mod_muc_room.erl
29
-define(DICT, dict).
30
-record(config, {title = "",
31
		 allow_change_subj = true,
32
		 allow_query_users = true,
33
		 allow_private_messages = true,
34
		 public = true,
35
		 public_list = true,
36
		 persistent = false,
37
		 moderated = false, % TODO
38
		 members_by_default = true,
39
		 members_only = false,
40
		 allow_user_invites = false,
41
		 password_protected = false,
42
		 password = "",
43
		 anonymous = true,
44
		 logging = false
45
		}).
46
-record(user, {jid,
47
	       nick,
48
	       role,
49
	       last_presence}).
50
-record(state, {room,
51
		host,
52
		server_host,
53
		access,
54
		jid,
55
		config = #config{},
56
		users = ?DICT:new(),
57
		affiliations = ?DICT:new(),
58
		history = lqueue_new(20),
59
		subject = "",
60
		subject_author = "",
61
		just_created = false}).
62
63
64
%%----------------------------------------------------------------------
65
%% Module control
66
67
start(Opts) ->
68
	case gen_mod:get_opt(allow_room_log, Opts, true) of
69
		true ->
70
			OutDir = gen_mod:get_opt(outdir, Opts, "www/muc"),
71
			DirType	= gen_mod:get_opt(dirtype, Opts, subdirs),
72
			CSSFile = gen_mod:get_opt(cssfile, Opts, false),
73
			CSSFile = gen_mod:get_opt(cssfile, Opts, false),
74
			AccessLog = gen_mod:get_opt(access_log, Opts, muc_admin),
75
			case lists:member(?PROCNAME, registered()) of
76
				false ->
77
					register(?PROCNAME, spawn(?MODULE, init_log, [{OutDir, DirType, CSSFile, AccessLog}]));
78
				true ->
79
					ok
80
			end;
81
		false ->
82
			ok
83
	end.
84
 
85
init_log(O) ->
86
    loop_log(O).
87
 
88
loop_log(Options) ->
89
	receive
90
		{log, Data} ->
91
			add_message_to_log2(Data, Options),
92
			loop_log(Options);
93
		{check_access_log, ServerHost, From, Pid} ->
94
			{_, _, _, AccessLog} = Options,
95
			Pid ! acl:match_rule(ServerHost, AccessLog, From),
96
			loop_log(Options);
97
		stop ->
98
			% TODO
99
			ok;
100
		_ ->
101
			loop_log(Options)
102
	end.
103
 
104
stop() ->
105
    ?PROCNAME ! stop.
106
107
check_access_log(ServerHost, From) ->
108
	case whereis(?PROCNAME) of
109
		undefined -> false;
110
		_ -> 
111
			?PROCNAME ! {check_access_log, ServerHost, From, self()},
112
			receive A -> A end
113
	end.
114
115
116
%%----------------------------------------------------------------------
117
%% Frontend
118
119
% Check if this room is configured is logged
120
add_to_log(A, D, StateData) ->
121
    case (StateData#state.config)#config.logging of
122
      true -> add_to_log(A, D);
123
      false -> ok
124
    end.
125
126
% Check if MUC logging is allowed
127
add_to_log(A, D) ->
128
    case whereis(?PROCNAME) of
129
      undefined -> ok;
130
      _ -> add_to_log2(A, D)
131
    end.
132
133
add_to_log2(text, {Nick, Packet, StateData}) ->
134
	case {xml:get_subtag(Packet, "subject"), xml:get_subtag(Packet, "body")} of
135
		{false, false} ->
136
			ok;
137
		{false, SubEl} ->
138
			Message = {body, htmlize(xml:get_tag_cdata(SubEl))},
139
			add_message_to_log(Nick, Message, StateData);
140
		{SubEl, _false} ->
141
			Message = {subject, htmlize(xml:get_tag_cdata(SubEl))},
142
			add_message_to_log(Nick, Message, StateData)
143
		end;
144
145
add_to_log2(roomconfig_change, {XData, StateData}) ->
146
    add_message_to_log("eeeaaae", {roomconfig_change, XData}, StateData);
147
148
add_to_log2(nickchange, {OldNick, NewNick, StateData}) ->
149
    add_message_to_log(NewNick, {nickchange, OldNick}, StateData);
150
151
add_to_log2(join, {Nick, StateData}) ->
152
    add_message_to_log(Nick, {join}, StateData);
153
154
add_to_log2(leave, {LJID, Reason, StateData}) ->
155
	{ok, #user{nick = Nick}} =
156
    	?DICT:find(LJID, StateData#state.users),
157
	case Reason of
158
		"" -> add_message_to_log(Nick, {leave}, StateData);
159
		_ -> add_message_to_log(Nick, {leave, Reason}, StateData)
160
	end;
161
162
add_to_log2(kickban, {LJID, Reason, Code, StateData}) ->
163
	{ok, #user{nick = Nick}} =
164
	    ?DICT:find(LJID, StateData#state.users),
165
    add_message_to_log(Nick, {kickban, Code, Reason}, StateData).
166
167
168
%%----------------------------------------------------------------------
169
%% Core
170
171
add_message_to_log(Nick, Message, StateData) ->
172
    ?PROCNAME ! {log, {Nick, Message, StateData}}.
173
174
add_message_to_log2({Nick, Message, StateData}, Options) ->
175
	{OutDir, DirType, CSSFile, _AccessLog} = Options,
176
	Room = get_room_info(StateData),
177
178
    % Timestamp, Date and Time
179
    TimeStamp = jlib:timestamp_to_iso(calendar:now_to_universal_time(now())),
180
    Year = string:substr(TimeStamp, 1, 4),
181
    Month = string:substr(TimeStamp, 5, 2),
182
    Day = string:substr(TimeStamp, 7, 2),
183
    A1 = string:concat(Year, "-"),
184
    A2 = string:concat(A1, Month),
185
    A3 = string:concat(A2, "-"),
186
    Date = string:concat(A3, Day),
187
188
    % Directory and file names
189
    {Dir, Filename} = case DirType of
190
      subdirs ->  
191
        {filename:join(Year, Month), Day};
192
      plain -> 
193
        {"", Date}
194
    end,
195
    Fd = filename:join([OutDir, Room#room.jid, Dir]),
196
    Fn = filename:join([Fd, string:concat(Filename, ".html")]),
197
198
    % Open file, create if it does not exist, create parent dirs if needed
199
    case file:read_file_info(Fn) of
200
      {ok, _} ->
201
        {ok, F} = file:open(Fn, [append]);
202
      {error, enoent} ->
203
        make_dir_rec(Fd),
204
        {ok, F} = file:open(Fn, [append]),
205
		Datestring = get_dateweek(date()),
206
        put_header(F, Room, Datestring, CSSFile)
207
    end,
208
209
    % Build message
210
    Text = case Message of
211
      {roomconfig_change, XData} ->  
212
		RoomConfig = roomconfigwire_to_string(XData),
213
		put_room_config(F, RoomConfig),
214
        io_lib:format("<font class=\"system\">~s</font><br/>", 
215
                        [?T("Chatroom configuration modified")]);
216
      {join} ->  
217
        io_lib:format("<font class=\"system\">~s ~s</font><br/>", 
218
                        [Nick, ?T("joins the room")]);
219
      {leave} ->  
220
        io_lib:format("<font class=\"system\">~s ~s</font><br/>", 
221
                        [Nick, ?T("leaves the room")]);
222
      {leave, Reason} ->  
223
        io_lib:format("<font class=\"system\">~s ~s: ~s</font><br/>", 
224
                        [Nick, ?T("leaves the room"), Reason]);
225
      {kickban, "307", ""} ->  
226
        io_lib:format("<font class=\"system\">~s ~s</font><br/>", 
227
                        [Nick, ?T("has been kicked")]);
228
      {kickban, "307", Reason} ->  
229
        io_lib:format("<font class=\"system\">~s ~s: ~s</font><br/>", 
230
                        [Nick, ?T("has been kicked"), Reason]);
231
      {kickban, "301", ""} ->  
232
        io_lib:format("<font class=\"system\">~s ~s</font><br/>", 
233
                        [Nick, ?T("has been banned")]);
234
      {kickban, "301", Reason} ->  
235
        io_lib:format("<font class=\"system\">~s ~s: ~s</font><br/>", 
236
                        [Nick, ?T("has been banned"), Reason]);
237
      {nickchange, OldNick} ->  
238
        io_lib:format("<font class=\"system\">~s ~s ~s</font><br/>", 
239
                        [OldNick, ?T("is now known as"), Nick]);
240
      {subject, T} ->  
241
        io_lib:format("<font class=\"system\">~s~s~s</font><br/>", 
242
                        [Nick, ?T(" has set the subject to: "), T]);
243
      {body, T} ->  
244
        case regexp:first_match(T, "^/me\s") of
245
          {match, _, _} ->
246
            io_lib:format("<font class=\"emote\">~s ~s</font><br/>", 
247
                            [Nick, string:substr(T, 5)]);
248
          nomatch ->
249
            io_lib:format("<font class=\"normal\">&lt;~s&gt;</font> ~s<br/>", 
250
                            [Nick, T])
251
        end
252
    end,
253
    Time = string:substr(TimeStamp, 10, 8),
254
255
    % Write message
256
    file:write(F, io_lib:format("<a name=\"~s\" href=\"#~s\" class=\"ts\">[~s]</a> ~s~n", 
257
                            [Time, Time, Time, Text])),
258
259
    % Close file
260
    file:close(F),
261
262
    ok.
263
264
265
%%----------------------------------------------------------------------
266
%% Utilities
267
268
get_dateweek(Dt) ->
269
	Weekday = case calendar:day_of_the_week(Dt) of
270
		1 -> ?T("Monday");
271
		2 -> ?T("Tuesday");
272
		3 -> ?T("Wednesday");
273
		4 -> ?T("Thursday");
274
		5 -> ?T("Friday");
275
		6 -> ?T("Saturday");
276
		7 -> ?T("Sunday")
277
		end,
278
	{Y, M, D} = Dt,
279
	Month = case M of
280
		1 -> ?T("January");
281
		2 -> ?T("February");
282
		3 -> ?T("March");
283
		4 -> ?T("April");
284
		5 -> ?T("May");
285
		6 -> ?T("June");
286
		7 -> ?T("July");
287
		8 -> ?T("August");
288
		9 -> ?T("September");
289
		10 -> ?T("October");
290
		11 -> ?T("November");
291
		12 -> ?T("December")
292
		end,
293
	case ?MYLANG of
294
		"en" -> io_lib:format("~s, ~s ~w, ~w", [Weekday, Month, D, Y]);
295
		"es" -> io_lib:format("~s ~w de ~s de ~w", [Weekday, D, Month, Y]);
296
		_    -> io_lib:format("~s, ~w ~s ~w", [Weekday, D, Month, Y])
297
	end.
298
299
make_dir_rec(Dir) ->
300
    case file:read_file_info(Dir) of
301
      {ok, _} ->
302
        ok;
303
      {error, enoent} ->
304
        DirS = filename:split(Dir),
305
        DirR = lists:sublist(DirS, length(DirS)-1),
306
        make_dir_rec(filename:join(DirR)),
307
        file:make_dir(Dir)
308
    end.
309
310
fw(F, S, O) -> file:write(F, io_lib:format(S++"~n", O)).
311
fw(F, S) -> fw(F, S, []).
312
313
put_header(F, Room, Date, CSSFile) ->
314
	fw(F, "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"),
315
    fw(F, "<html>"),
316
    %fw(F, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">"),
317
    fw(F, "<head>"),
318
    %fw(F, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"),
319
    fw(F, "<title>~s - ~s</title>", [Room#room.title, Date]),
320
	put_header_css(F, CSSFile),
321
	put_header_script(F),
322
    fw(F, "</head>"),
323
    fw(F, "<body>"),
324
    fw(F, "<div class=\"mucname\">ejabberd/mod_muc log</div>"),
325
    fw(F, "<div class=\"roomtitle\">~s</div>", [Room#room.title]),
326
    fw(F, "<div class=\"roomjid\">~s</div>", [Room#room.jid]),
327
    fw(F, "<div class=\"logdate\">~s</div>", [Date]),
328
    case {Room#room.subject_author, Room#room.subject} of
329
		{"", ""} -> ok;
330
		{SuA, Su} -> fw(F, "<div class=\"roomsubject\">~s~s~s</div>", [SuA, ?T(" has set the subject to: "), Su])
331
	end,
332
    RoomConfig = roomconfig_to_string(Room#room.config),
333
	put_room_config(F, RoomConfig),
334
    fw(F, "<br/>").
335
336
put_header_css(F, false) ->
337
    fw(F, "<style type=\"text/css\">"),
338
    fw(F, "<!--"),
339
    fw(F, ".ts {color: #AAAAAA; text-decoration: none;}"),
340
    fw(F, ".system {color: #009900; font-weight: bold;}"),
341
    fw(F, ".emote {color: #AA0099;}"),
342
    fw(F, ".self {color: #CC0000;}"),
343
    fw(F, ".normal {color: #0000AA;}"),
344
    fw(F, "div.mucname {color: #AAAAAA; text-align: right; font-family: monospace; letter-spacing: 3px;}"),
345
    fw(F, "div.roomtitle {color: #336699; font-size: 24px; font-weight: bold; font-family: sans-serif; border-bottom: #224466 solid 3pt; letter-spacing: 3px; margin-left: 20pt;}"),
346
    fw(F, "div.roomjid {color: #336699; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; margin-left: 20pt;}"),
347
    fw(F, "div.logdate {color: #663399; font-size: 20px; font-weight: bold; font-family: sans-serif; letter-spacing: 2px; border-bottom: #224466 solid 1pt; margin-left:80pt; margin-top:40px;}"),
348
    fw(F, "div.roomsubject {color: #336699; font-size: 18px; font-family: sans-serif; margin-left: 80pt; margin-bottom: 10px;}"),
349
    fw(F, "div.rc {color: #336699; font-size: 12px; font-family: sans-serif; margin-left: 60%; text-align: right; background: #f3f6f9; border-bottom: 1px solid #336699; border-right: 4px solid #336699;}"),
350
    fw(F, "div.rct {font-weight: bold; background: #e3e6e9; padding-right: 10px;}"),
351
    fw(F, "div.rcos {padding-right: 10px;}"),
352
    fw(F, "div.rcoe {color: green;}"),
353
    fw(F, "div.rcod {color: red;}"),
354
    fw(F, "div.rcoe:after {content: \": v\";}"),
355
    fw(F, "div.rcod:after {content: \": x\";}"),
356
    fw(F, "div.rcot:after {}"),
357
    fw(F, "//-->"),
358
    fw(F, "</style>");
359
360
put_header_css(F, CSSFile) ->
361
    fw(F, "<link rel=\"stylesheet\" type=\"text/css\" href=\"~s\" media=\"all\">", [CSSFile]).
362
363
put_header_script(F) ->
364
    fw(F, "<script type=\"text/javascript\">"),
365
    fw(F, "function sh(e) // Show/Hide an element"),
366
    fw(F, "{if(document.getElementById(e).style.display=='none')"),
367
    fw(F, "{document.getElementById(e).style.display='block';}"),
368
    fw(F, "else {document.getElementById(e).style.display='none';}}"),
369
    fw(F, "</script>").
370
371
put_room_config(F, RoomConfig) ->
372
	{_, Now2, _} = now(),
373
	fw(F, "<div class=\"rc\">"),
374
	fw(F,   "<div class=\"rct\" onClick=\"sh('a~p');return false;\">~s</div>", [Now2, ?T("Room Configuration")]),
375
	fw(F,   "<div class=\"rcos\" id=\"a~p\" style=\"display: none;\" ><br/>~s</div>", [Now2, RoomConfig]),
376
	fw(F, "</div>").
377
378
htmlize(S1) ->
379
	S2_list = string:tokens(S1, "\n"),
380
	lists:foldl(
381
		fun(Si, Res) -> 
382
			Si2 = htmlize2(Si),
383
			case Res of
384
				"" -> Si2;
385
				_ -> Res ++ "<br/>" ++ Si2
386
			end
387
		end, 
388
		"",
389
		S2_list).
390
391
htmlize2(S1) ->
392
    S2 = element(2, regexp:gsub(S1, "<", "\\&lt;")),
393
    S3 = element(2, regexp:gsub(S2, ">", "\\&gt;")),
394
    S4 = element(2, regexp:gsub(S3, "(http|ftp)://.[^ ]*", "<a href=\"&\">&</a>")),
395
    element(2, regexp:gsub(S4, "  ", "\\&nbsp;")).
396
397
get_room_info(StateData) ->
398
    Room1 = element(2, StateData),
399
    Room2 = element(3, StateData),
400
    Room3 = string:concat(Room1, "@"),
401
    RoomJID = string:concat(Room3, Room2),
402
	#room{
403
		jid = RoomJID,
404
		title = (StateData#state.config)#config.title,
405
		subject = StateData#state.subject,
406
		subject_author = StateData#state.subject_author,
407
		config = StateData#state.config
408
	}.
409
410
roomconfig_to_string(RoomConfig) ->
411
	Options = [
412
		{RoomConfig#config.allow_change_subj, allow_change_subj},
413
		{RoomConfig#config.allow_query_users, allow_query_users},
414
		{RoomConfig#config.allow_private_messages, allow_private_messages},
415
		{RoomConfig#config.public, public},
416
		{RoomConfig#config.public_list, public_list},
417
		{RoomConfig#config.persistent, persistent},
418
		{RoomConfig#config.moderated, moderated},
419
		{RoomConfig#config.members_by_default, members_by_default},
420
		{RoomConfig#config.members_only, members_only},
421
		{RoomConfig#config.allow_user_invites, allow_user_invites},
422
		{RoomConfig#config.password_protected, password_protected},
423
		{RoomConfig#config.anonymous, anonymous}
424
	],
425
	rc_to_string(Options).
426
427
roomconfigwire_to_string(XData) ->
428
	Options = [ 
429
		{case Value_str of "0" -> false; "1" -> true; [] -> false; T -> {text, T} end, list_to_atom(Name_str)} 
430
		|| {Name_str, [Value_str]} <- XData ],
431
	rc_to_string(Options).
432
433
rc_to_string(Options) ->
434
	% Get title, if available
435
	Title = case lists:keysearch(title, 2, Options) of
436
		{value, Tuple} -> [Tuple];
437
		false -> []
438
	end,
439
	
440
	% Remove title from list
441
	Os1 = lists:keydelete(title, 2, Options),
442
	
443
	% Order list
444
	Os2 = lists:keysort(2, Os1),
445
	
446
	% Add title to ordered list
447
	Options2 = Title ++ Os2,
448
449
	lists:foldl(
450
		fun({RC, O}, R) -> 
451
			O2 = ?T(get_roomconfig_text(O)),
452
			R2 = case RC of
453
				false -> "<div class=\"rcod\">" ++ O2 ++ "</div>";
454
				true -> "<div class=\"rcoe\">" ++ O2 ++ "</div>";
455
				{text, T} -> 
456
					case O of
457
						password -> []; % Don't print passwords on log
458
						title -> "<div class=\"rcot\">" ++ ?T("Room title") ++ ": \"" ++ T ++ "\"</div>";
459
						_ -> "\"" ++ T ++ "\""
460
					end
461
			end,
462
			R ++ R2
463
		end,
464
		"",
465
		Options2).
466
467
get_roomconfig_text(title) -> "Room title";
468
get_roomconfig_text(persistent) -> "Make room persistent";
469
get_roomconfig_text(public) -> "Make room public searchable";
470
get_roomconfig_text(public_list) -> "Make participants list public";
471
get_roomconfig_text(password_protected) -> "Make room password protected";
472
get_roomconfig_text(password) -> "Password";
473
get_roomconfig_text(anonymous) -> "Make room semianonymous";
474
get_roomconfig_text(members_only) -> "Make room members-only";
475
get_roomconfig_text(moderated) -> "Make room moderated";
476
get_roomconfig_text(members_by_default) -> "Default users as participants";
477
get_roomconfig_text(allow_change_subj) -> "Allow users to change subject";
478
get_roomconfig_text(allow_private_messages) -> "Allow users to send private messages";
479
get_roomconfig_text(allow_query_users) -> "Allow users to query other users";
480
get_roomconfig_text(allow_user_invites) -> "Allow users to send ";
481
get_roomconfig_text(logging) ->  "Enable logging".
(-)src/mod_muc/Makefile.win32 (+4 lines)
Lines 6-11 Link Here
6
6
7
OBJS = \
7
OBJS = \
8
	$(OUTDIR)\mod_muc.beam \
8
	$(OUTDIR)\mod_muc.beam \
9
	$(OUTDIR)\mod_muc_log.beam \
9
	$(OUTDIR)\mod_muc_room.beam
10
	$(OUTDIR)\mod_muc_room.beam
10
11
11
ALL : $(OBJS)
12
ALL : $(OBJS)
Lines 16-20 Link Here
16
$(OUTDIR)\mod_muc.beam : mod_muc.erl
17
$(OUTDIR)\mod_muc.beam : mod_muc.erl
17
	erlc -W $(EFLAGS) -o $(OUTDIR) mod_muc.erl
18
	erlc -W $(EFLAGS) -o $(OUTDIR) mod_muc.erl
18
19
20
$(OUTDIR)\mod_muc_log.beam : mod_muc_log.erl
21
	erlc -W $(EFLAGS) -o $(OUTDIR) mod_muc_log.erl
22
19
$(OUTDIR)\mod_muc_room.beam : mod_muc_room.erl
23
$(OUTDIR)\mod_muc_room.beam : mod_muc_room.erl
20
	erlc -W $(EFLAGS) -o $(OUTDIR) mod_muc_room.erl
24
	erlc -W $(EFLAGS) -o $(OUTDIR) mod_muc_room.erl

Return to bug 101708