25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-26 16:26:24 +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> 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 * 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_jid/1,
short_prepd_bare_jid/1]). short_prepd_bare_jid/1]).
-include_lib("exmpp/include/exmpp_xml.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
%send_iq(From, To, ID, SubTags) -> %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])). [Year, Month, Day, Hour, Minute, Second])).
timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) -> timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) ->
{xmlelement, "x", Timestamp = lists:flatten(
[{"xmlns", ?NS_DELAY},
{"stamp", lists:flatten(
io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w", io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
[Year, Month, Day, Hour, Minute, Second]))}], [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}) -> now_to_utc_string({MegaSecs, Secs, MicroSecs}) ->
{{Year, Month, Day}, {Hour, Minute, Second}} = {{Year, Month, Day}, {Hour, Minute, Second}} =

View File

@ -157,16 +157,13 @@ store_packet(From, To, Packet) ->
#jid{lnode = LUser, ldomain = LServer} = To, #jid{lnode = LUser, ldomain = LServer} = To,
TimeStamp = now(), TimeStamp = now(),
Expire = find_x_expire(TimeStamp, Packet#xmlel.children), 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) ! gen_mod:get_module_proc(To#jid.ldomain, ?PROCNAME) !
#offline_msg{us = {LUser, LServer}, #offline_msg{us = {LUser, LServer},
timestamp = TimeStamp, timestamp = TimeStamp,
expire = Expire, expire = Expire,
from = From, from = From,
to = To, to = To,
packet = PacketOld}, packet = Packet},
stop; stop;
_ -> _ ->
ok ok
@ -233,6 +230,7 @@ find_x_expire(TimeStamp, [_ | Els]) ->
resend_offline_messages(User, Server) -> resend_offline_messages(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},
@ -245,18 +243,11 @@ resend_offline_messages(User, Server) ->
{atomic, Rs} -> {atomic, Rs} ->
lists:foreach( lists:foreach(
fun(R) -> fun(R) ->
Packet = case R#offline_msg.packet of Packet = R#offline_msg.packet,
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
% XXX OLD FORMAT: Convert From & To.
ejabberd_sm ! ejabberd_sm !
{route, {route,
jlib:from_old_jid(R#offline_msg.from), R#offline_msg.from,
jlib:from_old_jid(R#offline_msg.to), R#offline_msg.to,
exmpp_xml:append_child(Packet, exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml( jlib:timestamp_to_xml(
calendar:now_to_universal_time( calendar:now_to_universal_time(
@ -265,9 +256,14 @@ resend_offline_messages(User, Server) ->
lists:keysort(#offline_msg.timestamp, Rs)); lists:keysort(#offline_msg.timestamp, Rs));
_ -> _ ->
ok ok
end
catch
_ ->
ok
end. end.
pop_offline_messages(Ls, User, Server) -> pop_offline_messages(Ls, User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},
@ -281,17 +277,10 @@ pop_offline_messages(Ls, User, Server) ->
TS = now(), TS = now(),
Ls ++ lists:map( Ls ++ lists:map(
fun(R) -> fun(R) ->
Packet = case R#offline_msg.packet of Packet = R#offline_msg.packet,
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
% XXX OLD FORMAT: Convert From & To.
{route, {route,
jlib:from_old_jid(R#offline_msg.from), R#offline_msg.from,
jlib:from_old_jid(R#offline_msg.to), R#offline_msg.to,
exmpp_xml:append_child(Packet, exmpp_xml:append_child(Packet,
jlib:timestamp_to_xml( jlib:timestamp_to_xml(
calendar:now_to_universal_time( calendar:now_to_universal_time(
@ -309,6 +298,10 @@ pop_offline_messages(Ls, User, Server) ->
lists:keysort(#offline_msg.timestamp, Rs))); lists:keysort(#offline_msg.timestamp, Rs)));
_ -> _ ->
Ls Ls
end
catch
_ ->
Ls
end. end.
remove_expired_messages() -> remove_expired_messages() ->
@ -350,19 +343,24 @@ remove_old_messages(Days) ->
mnesia:transaction(F). mnesia:transaction(F).
remove_user(User, Server) -> remove_user(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User), LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server), LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer}, US = {LUser, LServer},
F = fun() -> F = fun() ->
mnesia:delete({offline_msg, US}) mnesia:delete({offline_msg, US})
end, end,
mnesia:transaction(F). mnesia:transaction(F)
catch
_ ->
ok
end.
update_table() -> update_table() ->
Fields = record_info(fields, offline_msg), Fields = record_info(fields, offline_msg),
case mnesia:table_info(offline_msg, attributes) of case mnesia:table_info(offline_msg, attributes) of
Fields -> Fields ->
ok; convert_to_exmpp();
[user, timestamp, expire, from, to, packet] -> [user, timestamp, expire, from, to, packet] ->
?INFO_MSG("Converting offline_msg table from " ?INFO_MSG("Converting offline_msg table from "
"{user, timestamp, expire, from, to, packet} format", []), "{user, timestamp, expire, from, to, packet} format", []),
@ -378,11 +376,19 @@ update_table() ->
F1 = fun() -> F1 = fun() ->
mnesia:write_lock_table(mod_offline_tmp_table), mnesia:write_lock_table(mod_offline_tmp_table),
mnesia:foldl( 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{ New_R = R#offline_msg{
us = {U, Host}, us = {U1, Host},
packet = exmpp_xml:xmlelement_to_xmlel(P, from = F1,
[?DEFAULT_NS], ?PREFIXED_NS) to = T1,
packet = P1
}, },
mnesia:dirty_write( mnesia:dirty_write(
mod_offline_tmp_table, mod_offline_tmp_table,
@ -415,12 +421,19 @@ update_table() ->
offline_msg, offline_msg,
fun({_, U, TS, F, T, P}) -> fun({_, U, TS, F, T, P}) ->
Expire = find_x_expire(TS, P#xmlelement.children), 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, timestamp = TS,
expire = Expire, expire = Expire,
from = F, from = F1,
to = T, to = T1,
packet = P} packet = P1}
end, Fields), end, Fields),
F1 = fun() -> F1 = fun() ->
mnesia:write_lock_table(mod_offline_tmp_table), mnesia:write_lock_table(mod_offline_tmp_table),
@ -447,27 +460,64 @@ update_table() ->
mnesia:transform_table(offline_msg, ignore, Fields) mnesia:transform_table(offline_msg, ignore, Fields)
end. 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: %% Helper functions:
%% Warn senders that their messages have been discarded: %% Warn senders that their messages have been discarded:
discard_warn_sender(Msgs) -> discard_warn_sender(Msgs) ->
lists:foreach( lists:foreach(
fun(#offline_msg{from=From, to=To, packet=Packet0}) -> fun(#offline_msg{from=From, to=To, packet=Packet}) ->
Packet = case Packet0 of
#xmlelement{} = P ->
exmpp_xml:xmlelement_to_xmlel(P,
[?DEFAULT_NS], ?PREFIXED_NS);
#xmlel{} = P ->
P
end,
ErrText = "Your contact offline message queue is full. The message has been discarded.", ErrText = "Your contact offline message queue is full. The message has been discarded.",
Error = exmpp_stanza:error('resource-constraint', Error = exmpp_stanza:error('resource-constraint',
{"en", ErrText}), {"en", ErrText}),
Err = exmpp_stanza:reply_with_error(Packet, Error), Err = exmpp_stanza:reply_with_error(Packet, Error),
ejabberd_router:route( ejabberd_router:route(
jlib:from_old_jid(To), To,
jlib:from_old_jid(From), Err) From, Err)
end, Msgs). end, Msgs).
@ -482,10 +532,21 @@ webadmin_page(_, Host,
webadmin_page(Acc, _, _) -> Acc. webadmin_page(Acc, _, _) -> Acc.
user_queue(User, Server, Query, Lang) -> user_queue(User, Server, Query, Lang) ->
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)}, {US, Msgs, Res} = try
Res = user_queue_parse_query(US, Query), US0 = {
Msgs = lists:keysort(#offline_msg.timestamp, exmpp_stringprep:nodeprep(User),
mnesia:dirty_read({offline_msg, US})), 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 = FMsgs =
lists:map( lists:map(
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To, fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
@ -497,11 +558,9 @@ user_queue(User, Server, Query, Lang) ->
io_lib:format( io_lib:format(
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", "~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
[Year, Month, Day, Hour, Minute, Second])), [Year, Month, Day, Hour, Minute, Second])),
SFrom = exmpp_jid:jid_to_list(jlib:from_old_jid(From)), SFrom = exmpp_jid:jid_to_list(From),
STo = exmpp_jid:jid_to_list(jlib:from_old_jid(To)), STo = exmpp_jid:jid_to_list(To),
Packet0 = exmpp_xml:xmlelement_to_xmlel(Packet, Packet1 = exmpp_stanza:set_jids(Packet, SFrom, STo),
[?DEFAULT_NS], ?PREFIXED_NS),
Packet1 = exmpp_stanza:set_jids(Packet0, SFrom, STo),
FPacket = exmpp_xml:node_to_list( FPacket = exmpp_xml:node_to_list(
exmpp_xml:indent_document(Packet1, <<" ">>), exmpp_xml:indent_document(Packet1, <<" ">>),
[?DEFAULT_NS], ?PREFIXED_NS), [?DEFAULT_NS], ?PREFIXED_NS),
@ -571,8 +630,16 @@ us_to_list({User, Server}) ->
exmpp_jid:jid_to_list(User, Server). exmpp_jid:jid_to_list(User, Server).
webadmin_user(Acc, User, Server, Lang) -> webadmin_user(Acc, User, Server, Lang) ->
US = {exmpp_stringprep:nodeprep(User), exmpp_stringprep:nameprep(Server)}, FQueueLen = try
US = {
exmpp_stringprep:nodeprep(User),
exmpp_stringprep:nameprep(Server)
},
QueueLen = length(mnesia:dirty_read({offline_msg, US})), QueueLen = length(mnesia:dirty_read({offline_msg, US})),
FQueueLen = [?AC("queue/", [?AC("queue/",
integer_to_list(QueueLen))], integer_to_list(QueueLen))]
catch
_ ->
[?C("?")]
end,
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen. Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen.