25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

In mod_offline:

o  Remove any compatibility code: the core of Ejabberd expects new
structures.
o  Add table conversion.
o  Add try/catch block around exmpp_stringprep:*prep/1 uses.

To permit the complete removal of the compatibility code, jlib had to be
changed too: the timestamp_to_xml/1 function now returns an #xmlel.

SVN Revision: 1575
This commit is contained in:
Jean-Sébastien Pédron 2008-09-25 10:46:00 +00:00
parent c74ab439ef
commit c068d20588
3 changed files with 195 additions and 118 deletions

View File

@ -1,3 +1,12 @@
2008-09-25 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/jlib.erl (timestamp_to_xml): Create an #xmlel element, not an
old #xmlelement.
* src/mod_offline.erl: Remove any compatibility code: the core of
Ejabberd expects new structures. Add table conversion. Add try/catch
block around exmpp_stringprep:*prep/1 uses.
2008-09-23 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_vcard.erl (process_sm_iq): Fix a bug where a badmatch

View File

@ -68,6 +68,8 @@
short_prepd_jid/1,
short_prepd_bare_jid/1]).
-include_lib("exmpp/include/exmpp_xml.hrl").
-include("jlib.hrl").
%send_iq(From, To, ID, SubTags) ->
@ -517,12 +519,11 @@ timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}) ->
[Year, Month, Day, Hour, Minute, Second])).
timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) ->
{xmlelement, "x",
[{"xmlns", ?NS_DELAY},
{"stamp", lists:flatten(
io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
[Year, Month, Day, Hour, Minute, Second]))}],
[]}.
Timestamp = lists:flatten(
io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
[Year, Month, Day, Hour, Minute, Second])),
exmpp_xml:set_attribute(#xmlel{ns = ?NS_DELAY, name = 'x'},
'stamp', Timestamp).
now_to_utc_string({MegaSecs, Secs, MicroSecs}) ->
{{Year, Month, Day}, {Hour, Minute, Second}} =

View File

@ -157,16 +157,13 @@ store_packet(From, To, Packet) ->
#jid{lnode = LUser, ldomain = LServer} = To,
TimeStamp = now(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children),
% XXX OLD FORMAT: Packet is stored in the old format.
PacketOld = exmpp_xml:xmlel_to_xmlelement(Packet,
[?DEFAULT_NS], ?PREFIXED_NS),
gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) !
#offline_msg{us = {LUser, LServer},
timestamp = TimeStamp,
expire = Expire,
from = From,
to = To,
packet = PacketOld},
packet = Packet},
stop;
_ ->
ok
@ -233,80 +230,76 @@ find_x_expire(TimeStamp, [_ | Els]) ->
resend_offline_messages(User, Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
Rs = mnesia:wread({offline_msg, US}),
mnesia:delete({offline_msg, US}),
Rs
end,
case mnesia:transaction(F) of
{atomic, Rs} ->
lists:foreach(
fun(R) ->
Packet = case R#offline_msg.packet of
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
% XXX OLD FORMAT: Convert From & To.
ejabberd_sm !
{route,
jlib:from_old_jid(R#offline_msg.from),
jlib:from_old_jid(R#offline_msg.to),
exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp)))}
end,
lists:keysort(#offline_msg.timestamp, Rs));
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
Rs = mnesia:wread({offline_msg, US}),
mnesia:delete({offline_msg, US}),
Rs
end,
case mnesia:transaction(F) of
{atomic, Rs} ->
lists:foreach(
fun(R) ->
Packet = R#offline_msg.packet,
ejabberd_sm !
{route,
R#offline_msg.from,
R#offline_msg.to,
exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp)))}
end,
lists:keysort(#offline_msg.timestamp, Rs));
_ ->
ok
end
catch
_ ->
ok
end.
pop_offline_messages(Ls, User, Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
Rs = mnesia:wread({offline_msg, US}),
mnesia:delete({offline_msg, US}),
Rs
end,
case mnesia:transaction(F) of
{atomic, Rs} ->
TS = now(),
Ls ++ lists:map(
fun(R) ->
Packet = case R#offline_msg.packet of
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
% XXX OLD FORMAT: Convert From & To.
{route,
jlib:from_old_jid(R#offline_msg.from),
jlib:from_old_jid(R#offline_msg.to),
exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp)))}
end,
lists:filter(
fun(R) ->
case R#offline_msg.expire of
never ->
true;
TimeStamp ->
TS < TimeStamp
end
end,
lists:keysort(#offline_msg.timestamp, Rs)));
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
Rs = mnesia:wread({offline_msg, US}),
mnesia:delete({offline_msg, US}),
Rs
end,
case mnesia:transaction(F) of
{atomic, Rs} ->
TS = now(),
Ls ++ lists:map(
fun(R) ->
Packet = R#offline_msg.packet,
{route,
R#offline_msg.from,
R#offline_msg.to,
exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp)))}
end,
lists:filter(
fun(R) ->
case R#offline_msg.expire of
never ->
true;
TimeStamp ->
TS < TimeStamp
end
end,
lists:keysort(#offline_msg.timestamp, Rs)));
_ ->
Ls
end
catch
_ ->
Ls
end.
@ -350,19 +343,24 @@ remove_old_messages(Days) ->
mnesia:transaction(F).
remove_user(User, Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
mnesia:delete({offline_msg, US})
end,
mnesia:transaction(F).
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
mnesia:delete({offline_msg, US})
end,
mnesia:transaction(F)
catch
_ ->
ok
end.
update_table() ->
Fields = record_info(fields, offline_msg),
case mnesia:table_info(offline_msg, attributes) of
Fields ->
ok;
convert_to_exmpp();
[user, timestamp, expire, from, to, packet] ->
?INFO_MSG("Converting offline_msg table from "
"{user, timestamp, expire, from, to, packet} format", []),
@ -378,11 +376,19 @@ update_table() ->
F1 = fun() ->
mnesia:write_lock_table(mod_offline_tmp_table),
mnesia:foldl(
fun(#offline_msg{us = U, packet = P} = R, _) ->
fun(#offline_msg{us = U, from = F, to = T, packet = P} = R, _) ->
U1 = convert_jid_to_exmpp(U),
F1 = jlib:from_old_jid(F),
T1 = jlib:from_old_jid(T),
P1 = exmpp_xml:xmlelement_to_xmlel(
P,
[?DEFAULT_NS],
?PREFIXED_NS),
New_R = R#offline_msg{
us = {U, Host},
packet = exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS)
us = {U1, Host},
from = F1,
to = T1,
packet = P1
},
mnesia:dirty_write(
mod_offline_tmp_table,
@ -415,12 +421,19 @@ update_table() ->
offline_msg,
fun({_, U, TS, F, T, P}) ->
Expire = find_x_expire(TS, P#xmlelement.children),
#offline_msg{us = U,
U1 = convert_jid_to_exmpp(U),
F1 = jlib:from_old_jid(F),
T1 = jlib:from_old_jid(T),
P1 = exmpp_xml:xmlelement_to_xmlel(
P,
[?DEFAULT_NS],
?PREFIXED_NS),
#offline_msg{us = U1,
timestamp = TS,
expire = Expire,
from = F,
to = T,
packet = P}
from = F1,
to = T1,
packet = P1}
end, Fields),
F1 = fun() ->
mnesia:write_lock_table(mod_offline_tmp_table),
@ -447,27 +460,64 @@ update_table() ->
mnesia:transform_table(offline_msg, ignore, Fields)
end.
convert_to_exmpp() ->
Fun = fun() ->
case mnesia:first(offline_msg) of
'$end_of_table' ->
none;
Key ->
case mnesia:read({offline_msg, Key}) of
[#offline_msg{packet = #xmlel{}} | _] ->
none;
[#offline_msg{packet = #xmlelement{}} | _] ->
mnesia:foldl(fun convert_to_exmpp2/2,
done, offline_msg, write)
end
end
end,
mnesia:transaction(Fun).
convert_to_exmpp2(#offline_msg{
us = {US_U, US_S},
from = From,
to = To,
packet = Packet} = R, Acc) ->
% Remove old entry.
mnesia:delete_object(R),
% Convert "" to undefined in JIDs.
US_U1 = convert_jid_to_exmpp(US_U),
US_S1 = convert_jid_to_exmpp(US_S),
From1 = jlib:from_old_jid(From),
To1 = jlib:from_old_jid(To),
% Convert stanza.
Packet1 = exmpp_xml:xmlelement_to_xmlel(Packet,
[?DEFAULT_NS], ?PREFIXED_NS),
% Prepare the new record.
New_R = R#offline_msg{
us = {US_U1, US_S1},
from = From1,
to = To1,
packet = Packet1},
% Write the new record.
mnesia:write(New_R),
Acc.
convert_jid_to_exmpp("") -> undefined;
convert_jid_to_exmpp(V) -> V.
%% Helper functions:
%% Warn senders that their messages have been discarded:
discard_warn_sender(Msgs) ->
lists:foreach(
fun(#offline_msg{from=From, to=To, packet=Packet0}) ->
Packet = case Packet0 of
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
fun(#offline_msg{from=From, to=To, packet=Packet}) ->
ErrText = "Your contact offline message queue is full. The message has been discarded.",
Error = exmpp_stanza:error('resource-constraint',
{"en", ErrText}),
Err = exmpp_stanza:reply_with_error(Packet, Error),
ejabberd_router:route(
jlib:from_old_jid(To),
jlib:from_old_jid(From), Err)
To,
From, Err)
end, Msgs).
@ -482,10 +532,21 @@ webadmin_page(_, Host,
webadmin_page(Acc, _, _) -> Acc.
user_queue(User, Server, Query, Lang) ->
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)},
Res = user_queue_parse_query(US, Query),
Msgs = lists:keysort(#offline_msg.timestamp,
mnesia:dirty_read({offline_msg, US})),
{US, Msgs, Res} = try
US0 = {
exmpp_stringprep:nodeprep(User),
exmpp_stringprep:nameprep(Server)
},
{
US0,
lists:keysort(#offline_msg.timestamp,
mnesia:dirty_read({offline_msg, US0})),
user_queue_parse_query(US0, Query)
}
catch
_ ->
{{"invalid", "invalid"}, [], nothing}
end,
FMsgs =
lists:map(
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
@ -497,11 +558,9 @@ user_queue(User, Server, Query, Lang) ->
io_lib:format(
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
[Year, Month, Day, Hour, Minute, Second])),
SFrom = exmpp_jid:jid_to_list(jlib:from_old_jid(From)),
STo = exmpp_jid:jid_to_list(jlib:from_old_jid(To)),
Packet0 = exmpp_xml:xmlelement_to_xmlel(Packet,
[?DEFAULT_NS], ?PREFIXED_NS),
Packet1 = exmpp_stanza:set_jids(Packet0, SFrom, STo),
SFrom = exmpp_jid:jid_to_list(From),
STo = exmpp_jid:jid_to_list(To),
Packet1 = exmpp_stanza:set_jids(Packet, SFrom, STo),
FPacket = exmpp_xml:node_to_list(
exmpp_xml:indent_document(Packet1, <<" ">>),
[?DEFAULT_NS], ?PREFIXED_NS),
@ -571,8 +630,16 @@ us_to_list({User, Server}) ->
exmpp_jid:jid_to_list(User, Server).
webadmin_user(Acc, User, Server, Lang) ->
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)},
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
FQueueLen = [?AC("queue/",
integer_to_list(QueueLen))],
FQueueLen = try
US = {
exmpp_stringprep:nodeprep(User),
exmpp_stringprep:nameprep(Server)
},
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
[?AC("queue/",
integer_to_list(QueueLen))]
catch
_ ->
[?C("?")]
end,
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen.