From 16ca8d178d823be50492c9977f2988a54ee01a79 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 30 Jun 2009 16:55:26 +0000 Subject: [PATCH] Add XEP82 Date Time, update XEP202 Entity Time and XEP203 Delayed Delivery (EJAB-234) SVN Revision: 2347 --- doc/guide.html | 4 ++-- doc/guide.tex | 6 +++--- src/ejd2odbc.erl | 9 ++++++++- src/jlib.erl | 33 +++++++++++++++++++++++++++++-- src/mod_muc/mod_muc_room.erl | 18 ++++++++++++++--- src/mod_offline.erl | 38 ++++++++++++++++++++++++++---------- src/mod_offline_odbc.erl | 20 +++++++++++++------ src/mod_time.erl | 37 +++++++++++++++++++++++++++++------ 8 files changed, 132 insertions(+), 33 deletions(-) diff --git a/doc/guide.html b/doc/guide.html index 4efcc7a17..d40ff02b9 100644 --- a/doc/guide.html +++ b/doc/guide.html @@ -1796,7 +1796,7 @@ all entries end with a comma: mod_shared_rosterShared roster managementmod_roster or   mod_roster_odbc mod_statsStatistics Gathering (XEP-0039)  -mod_timeEntity Time (XEP-0090)  +mod_timeEntity Time (XEP-0202mod_vcardvcard-temp (XEP-0054mod_vcard_ldapvcard-temp (XEP-0054)LDAP server mod_vcard_odbcvcard-temp (XEP-0054)supported DB (*) @@ -2845,7 +2845,7 @@ by sending: </iq>

3.3.21  mod_time

-

This module features support for Entity Time (XEP-0090). By using this XEP, +

This module features support for Entity Time (XEP-0202). By using this XEP, you are able to discover the time at another entity’s location.

Options:

iqdisc
This specifies diff --git a/doc/guide.tex b/doc/guide.tex index 9a00a964b..6bf2be289 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -2385,7 +2385,7 @@ The following table lists all modules included in \ejabberd{}. \hline \ahrefloc{modsharedroster}{\modsharedroster{}} & Shared roster management & \modroster{} or \\ & & \modrosterodbc\\ \hline \ahrefloc{modstats}{\modstats{}} & Statistics Gathering (\xepref{0039}) & \\ - \hline \ahrefloc{modtime}{\modtime{}} & Entity Time (\xepref{0090}) & \\ + \hline \ahrefloc{modtime}{\modtime{}} & Entity Time (\xepref{0202}) & \\ \hline \ahrefloc{modvcard}{\modvcard{}} & vcard-temp (\xepref{0054}) & \\ \hline \ahrefloc{modvcardldap}{\modvcardldap{}} & vcard-temp (\xepref{0054}) & LDAP server \\ \hline \ahrefloc{modvcard}{\modvcardodbc{}} & vcard-temp (\xepref{0054}) & supported DB (*) \\ @@ -3670,9 +3670,9 @@ in order to get the statistics. Here they are: \end{itemize} \makesubsection{modtime}{\modtime{}} -\ind{modules!\modtime{}}\ind{protocols!XEP-0090: Entity Time} +\ind{modules!\modtime{}}\ind{protocols!XEP-0202: Entity Time} -This module features support for Entity Time (\xepref{0090}). By using this XEP, +This module features support for Entity Time (\xepref{0202}). By using this XEP, you are able to discover the time at another entity's location. Options: diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index f46b45eba..ed1292d09 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -127,7 +127,14 @@ export_offline(Server, Output) -> Packet0 = exmpp_stanza:set_jids(Packet, exmpp_jid:to_list(From), exmpp_jid:to_list(To)), - Packet1 = exmpp_xml:append_child(Packet0, + Packet0b = exmpp_xml:append_child(Packet0, + jlib:timestamp_to_xml( + calendar:now_to_universal_time(TimeStamp), + utc, + exmpp_jid:make("", Server, ""), + "Offline Storage")), + %% TODO: Delete the next three lines once XEP-0091 is Obsolete + Packet1 = exmpp_xml:append_child(Packet0b, jlib:timestamp_to_xml( calendar:now_to_universal_time(TimeStamp))), XML = diff --git a/src/jlib.erl b/src/jlib.erl index cf3dc5e8d..4729cd067 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -28,8 +28,10 @@ -author('alexey@process-one.net'). -export([parse_xdata_submit/1, - timestamp_to_iso/1, - timestamp_to_xml/1, + timestamp_to_iso/1, % TODO: Remove once XEP-0091 is Obsolete + timestamp_to_iso/2, + timestamp_to_xml/4, + timestamp_to_xml/1, % TODO: Remove once XEP-0091 is Obsolete now_to_utc_string/1, now_to_local_string/1, datetime_string_to_timestamp/1, @@ -149,11 +151,38 @@ rsm_encode_count(Count, Arr)-> i2b(I) when is_integer(I) -> list_to_binary(integer_to_list(I)); i2b(L) when is_list(L) -> list_to_binary(L). +%% Timezone = utc | {Hours, Minutes} +%% Hours = integer() +%% Minutes = integer() +timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}, Timezone) -> + Timestamp_string = lists:flatten( + io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w", + [Year, Month, Day, Hour, Minute, Second])), + Timezone_string = case Timezone of + utc -> "Z"; + {TZh, TZm} -> + Sign = case TZh >= 0 of + true -> "+"; + false -> "-" + end, + io_lib:format("~s~2..0w:~2..0w", [Sign, abs(TZh),TZm]) + end, + {Timestamp_string, Timezone_string}. + timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}) -> lists:flatten( io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w", [Year, Month, Day, Hour, Minute, Second])). +timestamp_to_xml(DateTime, Timezone, FromJID, Desc) -> + {T_string, Tz_string} = timestamp_to_iso(DateTime, Timezone), + From = exmpp_jid:to_list(FromJID), + P1 = exmpp_xml:set_attributes(#xmlel{ns = ?NS_DELAY, name = 'delay'}, + [{'from', From}, + {'stamp', T_string ++ Tz_string}]), + exmpp_xml:set_cdata(P1, Desc). + +%% TODO: Remove this function once XEP-0091 is Obsolete timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) -> Timestamp = lists:flatten( io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w", diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 11d029ed2..7265950b6 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -570,6 +570,7 @@ handle_event({service_message, Msg}, _StateName, StateData) -> end, ?DICT:to_list(StateData#state.users)), NSD = add_message_to_history("", + StateData#state.jid, MessagePkt, StateData), {next_state, normal_state, NSD}; @@ -810,6 +811,7 @@ process_groupchat_message(From, #xmlel{name = 'message'} = Packet, ?DICT:to_list(StateData#state.users)), NewStateData2 = add_message_to_history(FromNick, + From, Packet, NewStateData1), {next_state, normal_state, NewStateData2}; @@ -2025,11 +2027,21 @@ lqueue_to_list(#lqueue{queue = Q1}) -> queue:to_list(Q1). -add_message_to_history(FromNick, Packet, StateData) -> +add_message_to_history(FromNick, FromJID, Packet, StateData) -> HaveSubject = exmpp_xml:has_element(Packet, 'subject'), TimeStamp = calendar:now_to_universal_time(now()), - TSPacket = exmpp_xml:append_child(Packet, - jlib:timestamp_to_xml(TimeStamp)), + %% Chatroom history is stored as XMPP packets, so + %% the decision to include the original sender's JID or not is based on the + %% chatroom configuration when the message was originally sent. + %% Also, if the chatroom is anonymous, even moderators will not get the real JID + SenderJid = case ((StateData#state.config)#config.anonymous) of + true -> StateData#state.jid; + false -> FromJID + end, + TSPacket = exmpp_xml:append_children(Packet, + [jlib:timestamp_to_xml(TimeStamp, utc, SenderJid, ""), + %% TODO: Delete the next line once XEP-0091 is Obsolete + jlib:timestamp_to_xml(TimeStamp)]), SPacket = exmpp_stanza:set_recipient( exmpp_stanza:set_sender(TSPacket, jid_replace_resource(StateData#state.jid, FromNick)), diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 8085d348a..483575fa7 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -174,9 +174,9 @@ get_sm_features(Acc, _From, _To, "", _Lang) -> {result, I} -> I; _ -> [] end, - {result, Feats ++ [?NS_FEATURE_MSGOFFLINE]}; + {result, Feats ++ [?NS_MSGOFFLINE]}; -get_sm_features(_Acc, _From, _To, ?NS_FEATURE_MSGOFFLINE, _Lang) -> +get_sm_features(_Acc, _From, _To, ?NS_MSGOFFLINE, _Lang) -> %% override all lesser features... {result, []}; @@ -286,10 +286,19 @@ resend_offline_messages(User, Server) -> {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)))} + exmpp_xml:append_children( + Packet, + [jlib:timestamp_to_xml( + calendar:now_to_universal_time(R#offline_msg.timestamp), + utc, + exmpp_jid:make("", Server, ""), + "Offline Storage"), + %% TODO: Delete the next three lines once XEP-0091 is Obsolete + jlib:timestamp_to_xml( + calendar:now_to_universal_time( + R#offline_msg.timestamp)) + ] + )} end, lists:keysort(#offline_msg.timestamp, Rs)); _ -> @@ -320,10 +329,19 @@ pop_offline_messages(Ls, User, Server) {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)))} + exmpp_xml:append_children( + Packet, + [jlib:timestamp_to_xml( + calendar:now_to_universal_time( + R#offline_msg.timestamp), + utc, + exmpp_jid:make("", Server, ""), + "Offline Storage"), + %% TODO: Delete the next three lines once XEP-0091 is Obsolete + jlib:timestamp_to_xml( + calendar:now_to_universal_time( + R#offline_msg.timestamp))] + )} end, lists:filter( fun(R) -> diff --git a/src/mod_offline_odbc.erl b/src/mod_offline_odbc.erl index 92de5548a..62e60ac26 100644 --- a/src/mod_offline_odbc.erl +++ b/src/mod_offline_odbc.erl @@ -113,10 +113,18 @@ loop(Host, AccessMaxOfflineMsgs) -> M#offline_msg.packet, From, To), - Packet1 = exmpp_xml:append_child(Packet0, - jlib:timestamp_to_xml( - calendar:now_to_universal_time( - M#offline_msg.timestamp))), + Packet1 = exmpp_xml:append_children( + Packet0, + [jlib:timestamp_to_xml( + calendar:now_to_universal_time( + M#offline_msg.timestamp), + utc, + jlib:make_jid("", Host, ""), + "Offline Storage"), + %% TODO: Delete the next three lines once XEP-0091 is Obsolete + jlib:timestamp_to_xml( + calendar:now_to_universal_time( + M#offline_msg.timestamp))]), XML = ejabberd_odbc:escape( exmpp_xml:document_to_list(Packet1)), @@ -181,9 +189,9 @@ get_sm_features(Acc, _From, _To, "", _Lang) -> {result, I} -> I; _ -> [] end, - {result, Feats ++ [?NS_FEATURE_MSGOFFLINE]}; + {result, Feats ++ [?NS_MSGOFFLINE]}; -get_sm_features(_Acc, _From, _To, ?NS_FEATURE_MSGOFFLINE, _Lang) -> +get_sm_features(_Acc, _From, _To, ?NS_MSGOFFLINE, _Lang) -> %% override all lesser features... {result, []}; diff --git a/src/mod_time.erl b/src/mod_time.erl index 4e12ac528..84efda45e 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -31,6 +31,7 @@ -export([start/2, stop/1, + process_local_iq90/3, % TODO: Remove once XEP-0090 is Obsolete process_local_iq/3]). -include_lib("exmpp/include/exmpp.hrl"). @@ -40,21 +41,45 @@ start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), + %% TODO: Remove the next two lines once XEP-0090 is Obsolete + gen_iq_handler:add_iq_handler(ejabberd_local, list_to_binary(Host), ?NS_TIME_OLD, + ?MODULE, process_local_iq90, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, list_to_binary(Host), ?NS_TIME, ?MODULE, process_local_iq, IQDisc). stop(Host) -> + %% TODO: Remove the next two lines once XEP-0090 is Obsolete + gen_iq_handler:remove_iq_handler(ejabberd_local, list_to_binary(Host), ?NS_TIME_OLD), gen_iq_handler:remove_iq_handler(ejabberd_local, list_to_binary(Host), ?NS_TIME). process_local_iq(_From, _To, #iq{type = get} = IQ_Rec) -> - UTC = jlib:timestamp_to_iso(calendar:universal_time()), - Result = #xmlel{ns = ?NS_TIME, name = 'query', children = [ - #xmlel{ns = ?NS_TIME, name = 'utc', children = [ - #xmlcdata{cdata = list_to_binary(UTC)} - ]} + Now = now(), + Now_universal = calendar:now_to_universal_time(Now), + Now_local = calendar:now_to_local_time(Now), + {UTC, UTC_diff} = jlib:timestamp_to_iso(Now_universal, utc), + Seconds_diff = calendar:datetime_to_gregorian_seconds(Now_local) + - calendar:datetime_to_gregorian_seconds(Now_universal), + {Hd, Md, _} = calendar:seconds_to_time(Seconds_diff), + {_, TZO_diff} = jlib:timestamp_to_iso({{0, 0, 0}, {0, 0, 0}}, {Hd, Md}), + Result = #xmlel{ns = ?NS_TIME, name = 'time', children = [ + #xmlel{ns = ?NS_TIME, name = 'tzo', children = [ + #xmlcdata{cdata = list_to_binary(TZO_diff)}]}, + #xmlel{ns = ?NS_TIME, name = 'utc', children = [ + #xmlcdata{cdata = list_to_binary(UTC ++ UTC_diff)}]} ]}, exmpp_iq:result(IQ_Rec, Result); process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) -> exmpp_iq:error(IQ_Rec, 'not-allowed'). - +%% TODO: Remove this function once XEP-0090 is Obsolete +process_local_iq90(_From, _To, #iq{type = get} = IQ_Rec) -> + UTC = jlib:timestamp_to_iso(calendar:universal_time()), + Result = #xmlel{ns = ?NS_TIME_OLD, name = 'query', + children = [#xmlel{ns = ?NS_TIME_OLD, name = 'utc', + children=[#xmlcdata{cdata = + list_to_binary(UTC)} + ]} + ]}, + exmpp_iq:result(IQ_Rec, Result); +process_local_iq90(_From, _To, #iq{type = set} = IQ_Rec) -> + exmpp_iq:error(IQ_Rec, 'not-allowed').