* src/mod_roster.erl: The subscribe request are now resend at

login as long as they have not been answered. mod_roster do no more
depends on mod_offline.
* src/ejabberd_sm.erl: Likewise.
* src/ejabberd_c2s.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise (The ODBC/relational support
has not yet been tested).
* src/mod_roster.hrl: Likewise.
* src/mod_offline.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* odbc/pg.sql: Likewise.
* odbc/mysql.sql: Likewise.

SVN Revision: 569
This commit is contained in:
Mickaël Rémond 2006-05-23 20:19:37 +00:00
parent 753e768090
commit 42cdf80cd4
10 changed files with 215 additions and 112 deletions

View File

@ -1,3 +1,18 @@
2006-05-23 Mickael Remond <mickael.remond@process-one.net>
* src/mod_roster.erl: The subscribe request are now resend at login as
long as they have not been answered. mod_roster do no more depends on
mod_offline.
* src/ejabberd_sm.erl: Likewise.
* src/ejabberd_c2s.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise (The ODBC/relational support has
not yet been tested).
* src/mod_roster.hrl: Likewise.
* src/mod_offline.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* odbc/pg.sql: Likewise.
* odbc/mysql.sql: Likewise.
2006-05-22 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_sm.erl: The max_user_sessions has been moved to

View File

@ -1364,6 +1364,7 @@ presence_update(From, Packet, StateData) ->
StateData#state.server,
[StateData#state.jid]),
resend_offline_messages(StateData),
resend_subscription_requests(StateData),
presence_broadcast_first(
From, StateData#state{pres_last = Packet,
pres_invis = false
@ -1727,6 +1728,19 @@ resend_offline_messages(#state{user = User,
end, Rs)
end.
resend_subscription_requests(#state{user = User,
server = Server} = StateData) ->
PendingSubscriptions = ejabberd_hooks:run_fold(
resend_subscription_requests_hook,
Server,
[],
[User, Server]),
lists:foreach(fun(XMLPacket) ->
send_element(StateData,
XMLPacket)
end,
PendingSubscriptions).
get_showtag(undefined) ->
"unavailable";
get_showtag(Presence) ->

View File

@ -306,32 +306,34 @@ do_route(From, To, Packet) ->
{Pass, Subsc} =
case xml:get_attr_s("type", Attrs) of
"subscribe" ->
Reason = xml:get_tag_cdata(
xml:get_subtag(Packet, "status")),
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, subscribe]),
[User, Server, From, subscribe, Reason]),
true};
"subscribed" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, subscribed]),
[User, Server, From, subscribed, ""]),
true};
"unsubscribe" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, unsubscribe]),
[User, Server, From, unsubscribe, ""]),
true};
"unsubscribed" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, unsubscribed]),
[User, Server, From, unsubscribed, ""]),
true};
_ ->
{true, false}
@ -340,39 +342,18 @@ do_route(From, To, Packet) ->
LFrom = jlib:jid_tolower(From),
PResources = get_user_present_resources(
LUser, LServer),
if
PResources /= [] ->
lists:foreach(
fun({_, R}) ->
if LFrom /=
{LUser, LServer, R} ->
do_route(
From,
jlib:jid_replace_resource(To, R),
Packet);
true ->
ok
end
end, PResources);
true ->
if
Subsc ->
case ejabberd_auth:is_user_exists(
LUser, LServer) of
true ->
ejabberd_hooks:run(
offline_subscription_hook,
LServer,
[From, To, Packet]);
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err)
end;
true ->
ok
end
end;
lists:foreach(
fun({_, R}) ->
if LFrom /=
{LUser, LServer, R} ->
do_route(
From,
jlib:jid_replace_resource(To, R),
Packet);
true ->
ok
end
end, PResources);
true ->
ok
end;

View File

@ -37,8 +37,6 @@ start(Host, _Opts) ->
update_table(),
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host,
@ -83,8 +81,6 @@ receive_all(Msgs) ->
stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host,

View File

@ -28,8 +28,6 @@
start(Host, _Opts) ->
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host,
@ -97,8 +95,6 @@ receive_all(Msgs) ->
stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host,

View File

@ -17,7 +17,8 @@
process_local_iq/3,
get_user_roster/2,
get_subscription_lists/3,
in_subscription/5,
get_in_pending_subscriptions/3,
in_subscription/6,
out_subscription/4,
set_items/3,
remove_user/2,
@ -46,6 +47,8 @@ start(Host, Opts) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc).
@ -62,6 +65,8 @@ stop(Host) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
@ -130,8 +135,6 @@ get_user_roster(Acc, US) ->
end.
item_to_xml(Item) ->
Attrs1 = [{"jid", jlib:jid_to_string(Item#roster.jid)}],
Attrs2 = case Item#roster.name of
@ -160,12 +163,11 @@ item_to_xml(Item) ->
_ ->
Attrs3
end,
Attrs = Attrs4 ++ Item#roster.xattrs,
SubEls1 = lists:map(fun(G) ->
{xmlelement, "group", [], [{xmlcdata, G}]}
end, Item#roster.groups),
SubEls = SubEls1 ++ Item#roster.xs,
{xmlelement, "item", Attrs, SubEls}.
{xmlelement, "item", Attrs4, SubEls}.
process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
@ -193,7 +195,6 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
I#roster{jid = JID,
name = "",
groups = [],
xattrs = [],
xs = []}
end,
Item1 = process_item_attrs(Item, Attrs),
@ -274,9 +275,7 @@ process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
"ask" ->
process_item_attrs(Item, Attrs);
_ ->
XAttrs = Item#roster.xattrs,
process_item_attrs(Item#roster{xattrs = [{Attr, Val} | XAttrs]},
Attrs)
process_item_attrs(Item, Attrs)
end;
process_item_attrs(Item, []) ->
Item.
@ -374,13 +373,13 @@ ask_to_pending(Ask) -> Ask.
in_subscription(_, User, Server, JID, Type) ->
process_subscription(in, User, Server, JID, Type).
in_subscription(_, User, Server, JID, Type, Reason) ->
process_subscription(in, User, Server, JID, Type, Reason).
out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type).
process_subscription(out, User, Server, JID, Type, []).
process_subscription(Direction, User, Server, JID1, Type) ->
process_subscription(Direction, User, Server, JID1, Type, Reason) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
@ -415,12 +414,18 @@ process_subscription(Direction, User, Server, JID1, Type) ->
Item#roster.ask,
Type)
end,
AskMessage = case NewState of
{_, both} -> Reason;
{_, in} -> Reason;
{_, _} -> []
end,
case NewState of
none ->
{none, AutoReply};
{Subscription, Pending} ->
NewItem = Item#roster{subscription = Subscription,
ask = Pending},
ask = Pending,
askmessage = list_to_binary(AskMessage)},
mnesia:write(NewItem),
{{push, NewItem}, AutoReply}
end
@ -630,13 +635,42 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
"ask" ->
process_item_attrs_ws(Item, Attrs);
_ ->
XAttrs = Item#roster.xattrs,
process_item_attrs_ws(Item#roster{xattrs = [{Attr, Val} | XAttrs]},
Attrs)
process_item_attrs_ws(Item, Attrs)
end;
process_item_attrs_ws(Item, []) ->
Item.
get_in_pending_subscriptions(Ls, User, Server) ->
JID = jlib:make_jid(User, Server,""),
case mnesia:dirty_index_read(roster, {User,Server}, #roster.us) of
Result when list(Result) ->
Ls ++ lists:map(
fun(R) ->
Message = R#roster.askmessage,
Status = if is_binary(Message) ->
binary_to_list(Message);
true ->
[]
end,
{xmlelement, "presence", [{"from", jlib:jid_to_string(R#roster.jid)},
{"to", jlib:jid_to_string(JID)},
{"type", "subscribe"}],
[{xmlelement, "status", [],
[{xmlcdata, Status}]}]}
end,
lists:filter(
fun(R) ->
case R#roster.ask of
in -> true;
both -> true;
_ -> false
end
end,
Result));
_ -> []
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -673,42 +707,54 @@ update_table() ->
Fields ->
ok;
[uj, user, jid, name, subscription, ask, groups, xattrs, xs] ->
?INFO_MSG("Converting roster table from "
"{uj, user, jid, name, subscription, ask, groups, xattrs, xs} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
mod_roster_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, roster},
{attributes, record_info(fields, roster)}]),
mnesia:del_table_index(roster, user),
mnesia:transform_table(roster, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(mod_roster_tmp_table),
mnesia:foldl(
fun(#roster{usj = {U, JID}, us = U} = R, _) ->
mnesia:dirty_write(
mod_roster_tmp_table,
R#roster{usj = {U, Host, JID},
us = {U, Host}})
end, ok, roster)
end,
mnesia:transaction(F1),
mnesia:clear_table(roster),
F2 = fun() ->
mnesia:write_lock_table(roster),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, mod_roster_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(mod_roster_tmp_table);
convert_table1(Fields);
[usj, us, jid, name, subscription, ask, groups, xattrs, xs] ->
convert_table2(Fields);
_ ->
?INFO_MSG("Recreating roster table", []),
mnesia:transform_table(roster, ignore, Fields)
end.
%% Convert roster table to support virtual host
convert_table1(Fields) ->
?INFO_MSG("Virtual host support: converting roster table from "
"{uj, user, jid, name, subscription, ask, groups, xattrs, xs} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
mod_roster_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, roster},
{attributes, record_info(fields, roster)}]),
mnesia:del_table_index(roster, user),
mnesia:transform_table(roster, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(mod_roster_tmp_table),
mnesia:foldl(
fun(#roster{usj = {U, JID}, us = U} = R, _) ->
mnesia:dirty_write(
mod_roster_tmp_table,
R#roster{usj = {U, Host, JID},
us = {U, Host}})
end, ok, roster)
end,
mnesia:transaction(F1),
mnesia:clear_table(roster),
F2 = fun() ->
mnesia:write_lock_table(roster),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, mod_roster_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(mod_roster_tmp_table).
%% Convert roster table: xattrs fields become
convert_table2(Fields) ->
?INFO_MSG("Converting roster table from "
"{usj, us, jid, name, subscription, ask, groups, xattrs, xs} format", []),
mnesia:transform_table(roster, ignore, Fields).

View File

@ -13,6 +13,6 @@
subscription = none,
ask = none,
groups = [],
xattrs = [],
askmessage = [],
xs = []}).

View File

@ -17,7 +17,8 @@
process_local_iq/3,
get_user_roster/2,
get_subscription_lists/3,
in_subscription/5,
get_in_pending_subscriptions/3,
in_subscription/6,
out_subscription/4,
set_items/3,
remove_user/2,
@ -41,6 +42,8 @@ start(Host, Opts) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc).
@ -57,6 +60,8 @@ stop(Host) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
@ -253,7 +258,8 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" askmessage, server, "
" subscribe, type) "
" values ", ItemVals, ";"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
@ -436,13 +442,13 @@ ask_to_pending(Ask) -> Ask.
in_subscription(_, User, Server, JID, Type) ->
process_subscription(in, User, Server, JID, Type).
in_subscription(_, User, Server, JID, Type, Reason) ->
process_subscription(in, User, Server, JID, Type, Reason).
out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type).
process_subscription(out, User, Server, JID, Type, []).
process_subscription(Direction, User, Server, JID1, Type) ->
process_subscription(Direction, User, Server, JID1, Type, Reason) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
LJID = jlib:jid_tolower(JID1),
@ -497,12 +503,18 @@ process_subscription(Direction, User, Server, JID1, Type) ->
Item#roster.ask,
Type)
end,
AskMessage = case NewState of
{_, both} -> Reason;
{_, in} -> Reason;
{_, _} -> []
end,
case NewState of
none ->
{none, AutoReply};
{Subscription, Pending} ->
NewItem = Item#roster{subscription = Subscription,
ask = Pending},
ask = Pending,
askmessage = AskMessage},
ItemVals = record_to_string(NewItem),
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
@ -512,7 +524,8 @@ process_subscription(Direction, User, Server, JID1, Type) ->
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" askmessage, server, subscribe, "
" type) "
" values ", ItemVals, ";"]),
{{push, NewItem}, AutoReply}
end
@ -700,7 +713,8 @@ process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" askmessage, server, subscribe, "
" type) "
" values ", ItemVals, ";"],
["delete from rostergroups "
" where username='", Username, "' "
@ -755,6 +769,37 @@ process_item_attrs_ws(Item, []) ->
Item.
get_in_pending_subscriptions(Ls, User, Server) ->
JID = jlib:make_jid(User, Server,""),
case mnesia:dirty_index_read(roster, {User,Server}, #roster.us) of
Result when list(Result) ->
Ls ++ lists:map(
fun(R) ->
Message = R#roster.askmessage,
Status = if is_binary(Message) ->
binary_to_list(Message);
true ->
[]
end,
{xmlelement, "presence", [{"from", jlib:jid_to_string(R#roster.jid)},
{"to", jlib:jid_to_string(JID)},
{"type", "subscribe"}],
[{xmlelement, "status", [],
[{xmlcdata, Status}]}]}
end,
lists:filter(
fun(R) ->
case R#roster.ask of
in -> true;
both -> true;
_ -> false
end
end,
Result));
_ -> []
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_jid_info(_, User, Server, JID) ->
@ -857,7 +902,8 @@ record_to_string(#roster{us = {User, _Server},
jid = JID,
name = Name,
subscription = Subscription,
ask = Ask}) ->
ask = Ask,
askmessage = AskMessage}) ->
Username = ejabberd_odbc:escape(User),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))),
Nick = ejabberd_odbc:escape(Name),
@ -881,6 +927,7 @@ record_to_string(#roster{us = {User, _Server},
"'", Nick, "',"
"'", SSubscription, "',"
"'", SAsk, "',"
"'", AskMessage, "',"
"'N', '', 'item')"].
groups_to_string(#roster{us = {User, _Server},

View File

@ -19,6 +19,7 @@ CREATE TABLE rosterusers (
nick text,
subscription character(1) NOT NULL,
ask character(1) NOT NULL,
askmessage text,
server character(1) NOT NULL,
subscribe text,
type text
@ -91,3 +92,5 @@ CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
--- To update from 1.x:
-- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask;

View File

@ -18,6 +18,7 @@ CREATE TABLE rosterusers (
nick text,
subscription character(1) NOT NULL,
ask character(1) NOT NULL,
askmessage text,
server character(1) NOT NULL,
subscribe text,
"type" text
@ -36,12 +37,6 @@ CREATE TABLE rostergroups (
CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
--- To update from previous table definition:
-- CREATE SEQUENCE spool_seq_seq;
-- ALTER TABLE spool ADD COLUMN seq integer;
-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
-- UPDATE spool SET seq = DEFAULT;
-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
CREATE TABLE spool (
username text NOT NULL,
@ -95,3 +90,13 @@ CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
--- To update from 0.9.8:
-- CREATE SEQUENCE spool_seq_seq;
-- ALTER TABLE spool ADD COLUMN seq integer;
-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
-- UPDATE spool SET seq = DEFAULT;
-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
--- To update from 1.x:
-- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask;