diff --git a/ChangeLog b/ChangeLog index 457d50962..ef7caf102 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,13 @@ defaults to the atom "undefined", not an empty binary. Fix a bug where we expected an #xmlelement to have only one #xmlcdata child. + * src/mod_last_odbc.erl (start/2, stop/1): The IQ registration must + use a namespace as atom, not list. + (process_local_iq/3, process_sm_iq/3, get_last/3): These functions + receive an #iq, not an #xmlel. + (store_last_info/4, remove_user/2): Add try/catch block around + exmpp_stringprep:*prep/1 uses. + 2008-10-01 Jean-Sébastien Pédron * src/mod_offline_odbc.erl, src/mod_vcard_odbc.erl, diff --git a/src/mod_last_odbc.erl b/src/mod_last_odbc.erl index f2ac26114..077a6ee52 100644 --- a/src/mod_last_odbc.erl +++ b/src/mod_last_odbc.erl @@ -45,9 +45,9 @@ start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s, + gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY, ?MODULE, process_local_iq, IQDisc), - gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s, + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY, ?MODULE, process_sm_iq, IQDisc), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), @@ -59,60 +59,54 @@ stop(Host) -> ?MODULE, remove_user, 50), ejabberd_hooks:delete(unset_presence_hook, Host, ?MODULE, on_presence_update, 50), - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY_s), - gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY_s). + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST_ACTIVITY), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST_ACTIVITY). -process_local_iq(_From, _To, IQ) -> - case exmpp_iq:get_type(IQ) of - set -> - exmpp_iq:error(IQ, 'not-allowed'); - get -> - Sec = trunc(element(1, erlang:statistics(wall_clock))/1000), - Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query', attrs = - [#xmlattr{name = 'seconds', value = integer_to_list(Sec)}]}, - exmpp_iq:result(IQ, Response) - end. +process_local_iq(_From, _To, #iq{type = get} = IQ_Rec) -> + Sec = trunc(element(1, erlang:statistics(wall_clock))/1000), + Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query', attrs = + [#xmlattr{name = 'seconds', value = integer_to_list(Sec)}]}, + exmpp_iq:result(IQ_Rec, Response); +process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) -> + exmpp_iq:error(IQ_Rec, 'not-allowed'). -process_sm_iq(From, To, IQ) -> - case exmpp_iq:get_type(IQ) of - set -> - exmpp_iq:error(IQ, 'not-allowed'); - get -> - User = To#jid.lnode, - Server = To#jid.ldomain, - {Subscription, _Groups} = - ejabberd_hooks:run_fold( - roster_get_jid_info, Server, - {none, []}, [User, Server, From]), - if - (Subscription == both) or (Subscription == from) -> - UserListRecord = ejabberd_hooks:run_fold( - privacy_get_user_list, Server, - #userlist{}, - [User, Server]), - case ejabberd_hooks:run_fold( - privacy_check_packet, Server, - allow, - [User, Server, UserListRecord, - {From, To, - exmpp_presence:available()}, - out]) of - allow -> - get_last(IQ, User, Server); - deny -> - exmpp_iq:error(IQ, 'not-allowed') - end; - true -> - exmpp_iq:error(IQ, 'not-allowed') - end - end. +process_sm_iq(From, To, #iq{type = get} = IQ_Rec) -> + User = To#jid.lnode, + Server = To#jid.ldomain, + {Subscription, _Groups} = + ejabberd_hooks:run_fold( + roster_get_jid_info, Server, + {none, []}, [User, Server, From]), + if + (Subscription == both) or (Subscription == from) -> + UserListRecord = ejabberd_hooks:run_fold( + privacy_get_user_list, Server, + #userlist{}, + [User, Server]), + case ejabberd_hooks:run_fold( + privacy_check_packet, Server, + allow, + [User, Server, UserListRecord, + {From, To, + exmpp_presence:available()}, + out]) of + allow -> + get_last(IQ_Rec, User, Server); + deny -> + exmpp_iq:error(IQ_Rec, 'not-allowed') + end; + true -> + exmpp_iq:error(IQ_Rec, 'not-allowed') + end; +process_sm_iq(_From, _To, #iq{type = set} = IQ_Rec) -> + exmpp_iq:error(IQ_Rec, 'not-allowed'). %% TODO: This function could use get_last_info/2 -get_last(IQ, LUser, LServer) -> +get_last(IQ_Rec, LUser, LServer) -> Username = ejabberd_odbc:escape(LUser), case catch odbc_queries:get_last(LServer, Username) of {selected, ["seconds","state"], []} -> - exmpp_iq:error(IQ, 'service-unavailable'); + exmpp_iq:error(IQ_Rec, 'service-unavailable'); {selected, ["seconds","state"], [{STimeStamp, Status}]} -> case catch list_to_integer(STimeStamp) of TimeStamp when is_integer(TimeStamp) -> @@ -122,12 +116,12 @@ get_last(IQ, LUser, LServer) -> Response = #xmlel{ns = ?NS_LAST_ACTIVITY, name = 'query', attrs = [#xmlattr{name = 'seconds', value = integer_to_list(Sec)}], children = [#xmlcdata{cdata = list_to_binary(Status)}]}, - exmpp_iq:result(IQ, Response); + exmpp_iq:result(IQ_Rec, Response); _ -> - exmpp_iq:error(IQ, 'internal-server-error') + exmpp_iq:error(IQ_Rec, 'internal-server-error') end; _ -> - exmpp_iq:error(IQ, 'internal-server-error') + exmpp_iq:error(IQ_Rec, 'internal-server-error') end. on_presence_update(User, Server, _Resource, Status) -> @@ -136,12 +130,17 @@ on_presence_update(User, Server, _Resource, Status) -> store_last_info(User, Server, TimeStamp, Status). store_last_info(User, Server, TimeStamp, Status) -> - LUser = exmpp_stringprep:nodeprep(User), - LServer = exmpp_stringprep:nameprep(Server), - Username = ejabberd_odbc:escape(LUser), - Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)), - State = ejabberd_odbc:escape(Status), - odbc_queries:set_last_t(LServer, Username, Seconds, State). + try + LUser = exmpp_stringprep:nodeprep(User), + LServer = exmpp_stringprep:nameprep(Server), + Username = ejabberd_odbc:escape(LUser), + Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)), + State = ejabberd_odbc:escape(Status), + odbc_queries:set_last_t(LServer, Username, Seconds, State) + catch + _ -> + ok + end. %% Returns: {ok, Timestamp, Status} | not_found get_last_info(LUser, LServer) -> @@ -161,7 +160,12 @@ get_last_info(LUser, LServer) -> end. remove_user(User, Server) -> - LUser = exmpp_stringprep:nodeprep(User), - LServer = exmpp_stringprep:nameprep(Server), - Username = ejabberd_odbc:escape(LUser), - odbc_queries:del_last(LServer, Username). + try + LUser = exmpp_stringprep:nodeprep(User), + LServer = exmpp_stringprep:nameprep(Server), + Username = ejabberd_odbc:escape(LUser), + odbc_queries:del_last(LServer, Username) + catch + _ -> + ok + end.