diff --git a/big_tests/tests/bosh_SUITE.erl b/big_tests/tests/bosh_SUITE.erl index 71e891e420d..abebaf23381 100644 --- a/big_tests/tests/bosh_SUITE.erl +++ b/big_tests/tests/bosh_SUITE.erl @@ -691,7 +691,7 @@ reply_in_time(ConfigIn) -> server_acks(Config) -> escalus:story(Config, [{carol, 1}, {geralt, 1}], fun(Carol, Geralt) -> bosh_set_active(Carol, false), - ExpectedRid = list_to_binary(integer_to_list(get_bosh_rid(Carol))), + ExpectedRid = integer_to_binary(get_bosh_rid(Carol)), escalus_client:send(Carol, escalus_stanza:chat_to(Geralt, <<"1st!">>)), escalus_client:send(Carol, escalus_stanza:chat_to(Geralt, <<"2nd!">>)), timer:sleep(200), @@ -897,7 +897,7 @@ wait_for_stanza(Client) -> ack_body(Body, Rid) -> Attrs = Body#xmlel.attrs, - Ack = {<<"ack">>, list_to_binary(integer_to_list(Rid))}, + Ack = {<<"ack">>, integer_to_binary(Rid)}, NewAttrs = lists:keystore(<<"ack">>, 1, Attrs, Ack), Body#xmlel{attrs = NewAttrs}. diff --git a/big_tests/tests/common_helper.erl b/big_tests/tests/common_helper.erl index 6cfb55112e6..17498a06de2 100644 --- a/big_tests/tests/common_helper.erl +++ b/big_tests/tests/common_helper.erl @@ -7,4 +7,4 @@ get_bjid(UserSpec) -> <>. unprep(Bin) when is_binary(Bin) -> - list_to_binary(string:titlecase(binary_to_list(Bin))). + string:titlecase(Bin). diff --git a/big_tests/tests/gdpr_SUITE.erl b/big_tests/tests/gdpr_SUITE.erl index 1705e62e7e8..4c315a502a6 100644 --- a/big_tests/tests/gdpr_SUITE.erl +++ b/big_tests/tests/gdpr_SUITE.erl @@ -1534,15 +1534,14 @@ retrieve_inbox_for_multiple_messages(Config) -> retrieve_logs(Config) -> escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> - User = string:to_lower(binary_to_list(escalus_client:username(Alice))), - Domain = string:to_lower(binary_to_list(escalus_client:server(Alice))), - JID = string:to_upper(binary_to_list(escalus_client:short_jid(Alice))), + User = string:lowercase(escalus_client:username(Alice)), + Domain = string:lowercase(escalus_client:server(Alice)), + JID = string:uppercase(binary_to_list(escalus_client:short_jid(Alice))), #{node := MIM2NodeName} = MIM2Node = distributed_helper:mim2(), mongoose_helper:successful_rpc(net_kernel, connect_node, [MIM2NodeName]), mongoose_helper:successful_rpc(MIM2Node, error_logger, error_msg, ["event=disturbance_in_the_force, jid=~s", [JID]]), - Dir = request_and_unzip_personal_data(list_to_binary(User), list_to_binary(Domain), - Config), + Dir = request_and_unzip_personal_data(User, Domain, Config), Filename = filename:join(Dir, "logs-" ++ atom_to_list(MIM2NodeName) ++ ".txt"), {ok, Content} = file:read_file(Filename), {match, _} = re:run(Content, "disturbance_in_the_force") diff --git a/big_tests/tests/graphql_muc_SUITE.erl b/big_tests/tests/graphql_muc_SUITE.erl index 6cb78107084..cdb41a82de4 100644 --- a/big_tests/tests/graphql_muc_SUITE.erl +++ b/big_tests/tests/graphql_muc_SUITE.erl @@ -1925,7 +1925,7 @@ assert_default_room_config(Response) -> <<"logging">> := false}, get_ok_value(?GET_ROOM_CONFIG_PATH, Response)). atom_to_enum_item(null) -> null; -atom_to_enum_item(Atom) -> list_to_binary(string:to_upper(atom_to_list(Atom))). +atom_to_enum_item(Atom) -> string:uppercase(atom_to_binary(Atom)). get_room_name() -> Domain = domain_helper:domain(), diff --git a/big_tests/tests/mam_send_message_SUITE_data/mam_send_message_example.erl b/big_tests/tests/mam_send_message_SUITE_data/mam_send_message_example.erl index fcdfe959fd4..e2995c09def 100644 --- a/big_tests/tests/mam_send_message_SUITE_data/mam_send_message_example.erl +++ b/big_tests/tests/mam_send_message_SUITE_data/mam_send_message_example.erl @@ -43,9 +43,9 @@ extend_message(_HostType, _ArcJID, Row = #{}) -> Row#{some_hash => erlang:phash2(Row, 32)}. send_message(Row, From, To, Mess) -> - Res = xml:get_subtag(Mess, <<"result">>), - Res2 = xml:append_subtags(Res, [new_subelem(Row)]), - Mess2 = xml:replace_subelement(Mess, Res2), + Res = exml_query:subelement(Mess, <<"result">>), + Res2 = jlib:append_subtags(Res, [new_subelem(Row)]), + Mess2 = jlib:replace_subelement(Mess, Res2), mod_mam_utils:send_message(Row, From, To, Mess2). new_subelem(#{some_hash := SomeHash}) -> diff --git a/big_tests/tests/muc_SUITE.erl b/big_tests/tests/muc_SUITE.erl index c97b2557dbb..73f9f3c23b6 100644 --- a/big_tests/tests/muc_SUITE.erl +++ b/big_tests/tests/muc_SUITE.erl @@ -4678,7 +4678,7 @@ skip_undefined(Xs) -> [X || X <- Xs, X =/= undefined]. i2b(X) when is_integer(X) -> - list_to_binary(integer_to_list(X)). + integer_to_binary(X). wait_room_range(Client, FromN, ToN) -> wait_room_range(Client, 15, FromN-1, FromN, ToN). diff --git a/big_tests/tests/muc_light_helper.erl b/big_tests/tests/muc_light_helper.erl index 151498a0356..7e1517fa640 100644 --- a/big_tests/tests/muc_light_helper.erl +++ b/big_tests/tests/muc_light_helper.erl @@ -211,12 +211,12 @@ aff_msg_verify_fun(AffUsersChanges) -> end. -spec lbin(Bin :: binary()) -> binary(). -lbin(Bin) -> list_to_binary(string:to_lower(binary_to_list(Bin))). - +lbin(Bin) -> + string:lowercase(Bin). -spec bin_aff_users(AffUsers :: ct_aff_users()) -> [{LBinJID :: binary(), AffBin :: binary()}]. bin_aff_users(AffUsers) -> - [ {lbin(escalus_client:short_jid(User)), list_to_binary(atom_to_list(Aff))} + [ {lbin(escalus_client:short_jid(User)), atom_to_binary(Aff)} || {User, Aff} <- AffUsers ]. -spec verify_aff_users(Items :: [exml:element()], BinAffUsers :: [{binary(), binary()}]) -> []. @@ -288,7 +288,7 @@ clear_db(HostType) -> -spec ver(Int :: integer()) -> binary(). ver(Int) -> - <<"ver-", (list_to_binary(integer_to_list(Int)))/binary>>. + <<"ver-", (integer_to_binary(Int))/binary>>. assert_no_aff_duplicates(AffUsers) -> Users = [US || {US, _} <- AffUsers], @@ -302,8 +302,8 @@ assert_no_aff_duplicates(AffUsers) -> -spec stanza_blocking_set(BlocklistChanges :: [ct_block_item()]) -> exml:element(). stanza_blocking_set(BlocklistChanges) -> - Items = [#xmlel{ name = list_to_binary(atom_to_list(What)), - attrs = [{<<"action">>, list_to_binary(atom_to_list(Action))}], + Items = [#xmlel{ name = atom_to_binary(What), + attrs = [{<<"action">>, atom_to_binary(Action)}], children = [#xmlcdata{ content = Who }] } || {What, Action, Who} <- BlocklistChanges], escalus_stanza:to(escalus_stanza:iq_set(?NS_MUC_LIGHT_BLOCKING, Items), muc_host()). diff --git a/big_tests/tests/oauth_SUITE.erl b/big_tests/tests/oauth_SUITE.erl index 8e3dc854d17..0c83a966ccf 100644 --- a/big_tests/tests/oauth_SUITE.erl +++ b/big_tests/tests/oauth_SUITE.erl @@ -435,7 +435,7 @@ serialize(ServerSideToken) -> end. to_lower(B) when is_binary(B) -> - list_to_binary(string:to_lower(binary_to_list(B))). + string:lowercase(B). required_modules() -> KeyOpts = #{backend => ct_helper:get_internal_database(), diff --git a/big_tests/tests/offline_SUITE.erl b/big_tests/tests/offline_SUITE.erl index b7e4d8bae5c..ad57603a7fb 100644 --- a/big_tests/tests/offline_SUITE.erl +++ b/big_tests/tests/offline_SUITE.erl @@ -406,7 +406,7 @@ make_chat_text(I) -> <<"Hi, Offline ", Number/binary>>. make_message_with_expiry(Target, Expiry, Text) -> - ExpiryBin = list_to_binary(integer_to_list(Expiry)), + ExpiryBin = integer_to_binary(Expiry), Stanza = escalus_stanza:chat_to(Target, Text), #xmlel{children = Children} = Stanza, ExpiryElem = #xmlel{name = <<"x">>, diff --git a/big_tests/tests/push_SUITE.erl b/big_tests/tests/push_SUITE.erl index e7cd6bccb9c..22e1e01b1ba 100644 --- a/big_tests/tests/push_SUITE.erl +++ b/big_tests/tests/push_SUITE.erl @@ -774,7 +774,7 @@ push_notification(PubsubJID, Payload, PublishOpts) -> bare_jid(JIDOrClient) -> ShortJID = escalus_client:short_jid(JIDOrClient), - list_to_binary(string:to_lower(binary_to_list(ShortJID))). + string:lowercase(ShortJID). add_pubsub_jid(Config) -> CaseName = proplists:get_value(case_name, Config), diff --git a/big_tests/tests/push_http_SUITE.erl b/big_tests/tests/push_http_SUITE.erl index bb3aa8a1412..1a96b5e87ca 100644 --- a/big_tests/tests/push_http_SUITE.erl +++ b/big_tests/tests/push_http_SUITE.erl @@ -161,8 +161,10 @@ process_notification(Req) -> check_default_format(From, To, Body, Msg) -> Attrs = lists:map(fun(P) -> list_to_tuple(binary:split(P, <<$=>>)) end, binary:split(Msg, <<$&>>, [global])), - ?assertEqual(to_lower(escalus_client:username(From)), proplists:get_value(<<"author">>, Attrs)), - ?assertEqual(to_lower(escalus_client:username(To)), proplists:get_value(<<"receiver">>, Attrs)), + ?assertEqual(string:lowercase(escalus_client:username(From)), + proplists:get_value(<<"author">>, Attrs)), + ?assertEqual(string:lowercase(escalus_client:username(To)), + proplists:get_value(<<"receiver">>, Attrs)), ?assertEqual(Body, proplists:get_value(<<"message">>, Attrs)), ?assertEqual(<<"localhost">>, proplists:get_value(<<"server">>, Attrs)), ok. @@ -221,15 +223,6 @@ custom_module_code_2() -> " . -to_lower(B) -> - list_to_binary( - string:to_lower( - binary_to_list( - B - ) - ) - ). - send(Alice, Bob, Body) -> Stanza = escalus_stanza:chat_to(Bob, Body), escalus_client:send(Alice, Stanza). diff --git a/big_tests/tests/push_integration_SUITE.erl b/big_tests/tests/push_integration_SUITE.erl index 907faf41d45..88946c27d55 100644 --- a/big_tests/tests/push_integration_SUITE.erl +++ b/big_tests/tests/push_integration_SUITE.erl @@ -983,7 +983,7 @@ gen_token() -> integer_to_binary(binary:decode_unsigned(crypto:strong_rand_bytes(16)), 24). lower(Bin) when is_binary(Bin) -> - list_to_binary(string:to_lower(binary_to_list(Bin))). + string:lowercase(Bin). pubsub_node_from_host(Config) -> case ?config(pubsub_host, Config) of diff --git a/big_tests/tests/push_pubsub_SUITE.erl b/big_tests/tests/push_pubsub_SUITE.erl index ffc2c020a50..e5ff372a7dd 100644 --- a/big_tests/tests/push_pubsub_SUITE.erl +++ b/big_tests/tests/push_pubsub_SUITE.erl @@ -396,7 +396,7 @@ rpc(M, F, A) -> bare_jid(JIDOrClient) -> ShortJID = escalus_client:short_jid(JIDOrClient), - list_to_binary(string:to_lower(binary_to_list(ShortJID))). + string:lowercase(ShortJID). %% ---------------------------------------------- %% REST mock handler diff --git a/big_tests/tests/vcard_SUITE.erl b/big_tests/tests/vcard_SUITE.erl index 110f734d7c2..9b58715328a 100644 --- a/big_tests/tests/vcard_SUITE.erl +++ b/big_tests/tests/vcard_SUITE.erl @@ -38,7 +38,7 @@ -define(EL_CD(Element, Name), exml_query:path(Element, [{element, Name}, cdata])). -define(PHOTO_BIN, <<130, 192, 33, 159, 204, 86, 12, 63, 132, 164>>). --define(PHOTO_BASE_64, <<"gsAhn8xWDD+EpA==">>). %% jlib:encode_base64(?PHOTO_BIN) +-define(PHOTO_BASE_64, <<"gsAhn8xWDD+EpA==">>). %% base64:encode(?PHOTO_BIN) -import(distributed_helper, [mim/0, require_rpc_nodes/1, diff --git a/rel/files/scripts/bootstrap20-template.escript b/rel/files/scripts/bootstrap20-template.escript index f5ae179cb9a..f128e1d1a8f 100755 --- a/rel/files/scripts/bootstrap20-template.escript +++ b/rel/files/scripts/bootstrap20-template.escript @@ -111,15 +111,5 @@ parse_template_config(TemplateConfigPath, TemplateConfigBin) -> end. % Produce LowerEnvVars depending on the version --ifdef(OTP_RELEASE). --if(?OTP_RELEASE >= 24). get_env_vars() -> - [{string:to_lower(K), V} || {K, V} <- os:env()]. --else. -get_env_vars() -> - [{string:to_lower(K), V} || {K, V} <- os:list_env_vars()]. --endif. --else. -get_env_vars() -> - [{string:to_lower(K), V} || {K, V} <- os:list_env_vars()]. --endif. + [{string:lowercase(K), V} || {K, V} <- os:env()]. diff --git a/src/adhoc.erl b/src/adhoc.erl index e1ce8a326fc..11a61de1414 100644 --- a/src/adhoc.erl +++ b/src/adhoc.erl @@ -47,9 +47,9 @@ parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS} ?LOG_DEBUG(#{what => adhoc_parse_request, text => <<"entering parse_request...">>, sub_el => SubEl}), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), - SessionID = xml:get_tag_attr_s(<<"sessionid">>, SubEl), - Action = xml:get_tag_attr_s(<<"action">>, SubEl), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), + SessionID = exml_query:attr(SubEl, <<"sessionid">>, <<>>), + Action = exml_query:attr(SubEl, <<"action">>, <<>>), XData = mongoose_data_forms:find_form(SubEl, false), #xmlel{children = AllEls} = SubEl, Others = case XData of @@ -112,7 +112,7 @@ produce_response(#adhoc_response{lang = _Lang, attrs = [{<<"xmlns">>, ?NS_COMMANDS}, {<<"sessionid">>, SessionID}, {<<"node">>, Node}, - {<<"status">>, list_to_binary(atom_to_list(Status))}], + {<<"status">>, atom_to_binary(Status)}], children = ActionsEls ++ NotesEls ++ Elements}. -spec ensure_correct_session_id(binary()) -> binary(). diff --git a/src/c2s/mongoose_c2s_stanzas.erl b/src/c2s/mongoose_c2s_stanzas.erl index 88ca4d38efb..6b13d89c923 100644 --- a/src/c2s/mongoose_c2s_stanzas.erl +++ b/src/c2s/mongoose_c2s_stanzas.erl @@ -125,7 +125,7 @@ hook_enabled_features(StateData) -> sasl_success_stanza(ServerOut) -> C = case ServerOut of undefined -> []; - _ -> [#xmlcdata{content = jlib:encode_base64(ServerOut)}] + _ -> [#xmlcdata{content = base64:encode(ServerOut)}] end, #xmlel{name = <<"success">>, attrs = [{<<"xmlns">>, ?NS_SASL}], @@ -148,7 +148,7 @@ maybe_text_tag(Text) -> sasl_challenge_stanza(ServerOut) -> #xmlel{name = <<"challenge">>, attrs = [{<<"xmlns">>, ?NS_SASL}], - children = [#xmlcdata{content = jlib:encode_base64(ServerOut)}]}. + children = [#xmlcdata{content = base64:encode(ServerOut)}]}. -spec successful_resource_binding(jlib:iq(), jid:jid()) -> exml:element(). successful_resource_binding(IQ, Jid) -> diff --git a/src/ejabberd.erl b/src/ejabberd.erl index 284943661c3..58f65b71c25 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -35,7 +35,7 @@ | {'xmlstreamelement', exml:element()} | {'xmlstreamend', _} | {'xmlstreamerror', _} - | {'xmlstreamstart', Name :: any(), Attrs :: list()}. + | {'xmlstreamstart', Name :: binary(), Attrs :: [exml:attr()]}. -export_type([lang/0, xml_stream_item/0]). diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index ea6374853fb..80e73b3ebc1 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -276,10 +276,9 @@ stream_start_error(StateData, Info, Error) -> -spec wait_for_feature_request(ejabberd:xml_stream_item(), state() ) -> fsm_return(). wait_for_feature_request({xmlstreamelement, El}, StateData) -> - #xmlel{name = Name, attrs = Attrs, children = Els} = El, TLS = StateData#state.tls, TLSEnabled = StateData#state.tls_enabled, - case {xml:get_attr_s(<<"xmlns">>, Attrs), Name} of + case {exml_query:attr(El, <<"xmlns">>), El#xmlel.name} of {?NS_TLS, <<"starttls">>} when TLS == true, TLSEnabled == false -> ?LOG_DEBUG(#{what => s2s_starttls}), @@ -295,10 +294,9 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> tls_options = TLSOpts }}; {?NS_SASL, <<"auth">>} when TLSEnabled -> - Mech = xml:get_attr_s(<<"mechanism">>, Attrs), - case Mech of + case exml_query:attr(El, <<"mechanism">>) of <<"EXTERNAL">> -> - Auth = jlib:decode_base64(xml:get_cdata(Els)), + Auth = base64:mime_decode(exml_query:cdata(El)), AuthDomain = jid:nameprep(Auth), CertData = mongoose_transport:get_peer_certificate( StateData#state.socket), diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index f13103ee329..ae6229d5028 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -312,12 +312,13 @@ open_socket2(HostType, Type, Addr, Port) -> %%---------------------------------------------------------------------- -spec wait_for_stream(ejabberd:xml_stream_item(), state()) -> fsm_return(). -wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData0) -> - RemoteStreamID = xml:get_attr_s(<<"id">>, Attrs), +wait_for_stream({xmlstreamstart, Name, Attrs}, StateData0) -> + StreamStart = #xmlel{name = Name, attrs = Attrs}, + RemoteStreamID = exml_query:attr(StreamStart, <<"id">>, <<>>), StateData = StateData0#state{remote_streamid = RemoteStreamID}, - case {xml:get_attr_s(<<"xmlns">>, Attrs), - xml:get_attr_s(<<"xmlns:db">>, Attrs), - xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} of + case {exml_query:attr(StreamStart, <<"xmlns">>, <<>>), + exml_query:attr(StreamStart, <<"xmlns:db">>, <<>>), + exml_query:attr(StreamStart, <<"version">>, <<>>) =:= <<"1.0">>} of {<<"jabber:server">>, <<"jabber:server:dialback">>, false} -> send_dialback_request(StateData); {<<"jabber:server">>, <<"jabber:server:dialback">>, true} when @@ -424,12 +425,11 @@ wait_for_features({xmlstreamelement, El}, StateData) -> #xmlel{name = <<"stream:features">>, children = Els} -> {SASLEXT, StartTLS, StartTLSRequired} = lists:foldl( - fun(#xmlel{name = <<"mechanisms">>, attrs = Attrs1, - children = Els1} = _El1, Acc) -> - Attr = xml:get_attr_s(<<"xmlns">>, Attrs1), + fun(#xmlel{name = <<"mechanisms">>, children = Els1} = El1, Acc) -> + Attr = exml_query:attr(El1, <<"xmlns">>, <<>>), get_acc_with_new_sext(Attr, Els1, Acc); - (#xmlel{name = <<"starttls">>, attrs = Attrs1} = El1, Acc) -> - Attr = xml:get_attr_s(<<"xmlns">>, Attrs1), + (#xmlel{name = <<"starttls">>} = El1, Acc) -> + Attr = exml_query:attr(El1, <<"xmlns">>, <<>>), get_acc_with_new_tls(Attr, El1, Acc); (_, Acc) -> Acc @@ -455,8 +455,8 @@ wait_for_features(closed, StateData) -> -spec wait_for_auth_result(ejabberd:xml_stream_item(), state()) -> fsm_return(). wait_for_auth_result({xmlstreamelement, El}, StateData) -> case El of - #xmlel{name = <<"success">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + #xmlel{name = <<"success">>} -> + case exml_query:attr(El, <<"xmlns">>) of ?NS_SASL -> ?LOG_DEBUG(#{what => s2s_auth_success, myname => StateData#state.myname, @@ -473,8 +473,8 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) -> send_text(StateData, ?STREAM_TRAILER), ?CLOSE_GENERIC(wait_for_auth_result, bad_format, El, StateData) end; - #xmlel{name = <<"failure">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + #xmlel{name = <<"failure">>} -> + case exml_query:attr(El, <<"xmlns">>) of ?NS_SASL -> ?LOG_WARNING(#{what => s2s_auth_failure, text => <<"Received failure result in ejabberd_s2s_out. Restarting">>, @@ -508,8 +508,8 @@ wait_for_auth_result(closed, StateData) -> -spec wait_for_starttls_proceed(ejabberd:xml_stream_item(), state()) -> fsm_return(). wait_for_starttls_proceed({xmlstreamelement, El}, StateData) -> case El of - #xmlel{name = <<"proceed">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + #xmlel{name = <<"proceed">>} -> + case exml_query:attr(El, <<"xmlns">>) of ?NS_TLS -> ?LOG_DEBUG(#{what => s2s_starttls, myname => StateData#state.myname, @@ -1083,24 +1083,18 @@ addr_type(Addr) when tuple_size(Addr) =:= 8 -> inet6. get_acc_with_new_sext(?NS_SASL, Els1, {_SEXT, STLS, STLSReq}) -> NewSEXT = lists:any( - fun(#xmlel{name = <<"mechanism">>, - children = Els2}) -> - case xml:get_cdata(Els2) of - <<"EXTERNAL">> -> true; - _ -> false - end; - (_) -> false + fun(El) -> + is_record(El, xmlel) + andalso <<"mechanism">> =:= El#xmlel.name + andalso <<"EXTERNAL">> =:= exml_query:cdata(El) end, Els1), + {NewSEXT, STLS, STLSReq}; get_acc_with_new_sext(_, _, Acc) -> Acc. get_acc_with_new_tls(?NS_TLS, El1, {SEXT, _STLS, _STLSReq}) -> - Req = case xml:get_subtag(El1, <<"required">>) of - #xmlel{} -> true; - false -> false - end, - {SEXT, true, Req}; + {SEXT, true, undefined =/= exml_query:subelement(El1, <<"required">>)}; get_acc_with_new_tls(_, _, Acc) -> Acc. @@ -1132,7 +1126,7 @@ handle_parsed_features({true, _, _, StateData = #state{try_auth = true, is_regis attrs = [{<<"xmlns">>, ?NS_SASL}, {<<"mechanism">>, <<"EXTERNAL">>}], children = - [#xmlcdata{content = jlib:encode_base64( + [#xmlcdata{content = base64:encode( StateData#state.myname)}]}), {next_state, wait_for_auth_result, StateData#state{try_auth = false}, ?FSMTIMEOUT}; diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index f4a9fc8ad08..9a31fc10223 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -201,16 +201,17 @@ init([Socket, Opts]) -> %%---------------------------------------------------------------------- -spec wait_for_stream(ejabberd:xml_stream_item(), state()) -> fsm_return(). -wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of +wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> + StreamStart = #xmlel{name = Name, attrs = Attrs}, + case exml_query:attr(StreamStart, <<"xmlns">>) of <<"jabber:component:accept">> -> %% Note: XEP-0114 requires to check that destination is a Jabber %% component served by this Jabber server. %% However several transports don't respect that, %% so ejabberd doesn't check 'to' attribute (EJAB-717) - To = xml:get_attr_s(<<"to">>, Attrs), + To = exml_query:attr(StreamStart, <<"to">>, <<>>), Header = io_lib:format(?STREAM_HEADER, [StateData#state.streamid, To]), - IsSubdomain = case xml:get_attr_s(<<"is_subdomain">>, Attrs) of + IsSubdomain = case exml_query:attr(StreamStart, <<"is_subdomain">>) of <<"true">> -> true; _ -> false end, @@ -237,8 +238,7 @@ wait_for_stream(replaced, StateData) -> -spec wait_for_handshake(ejabberd:xml_stream_item(), state()) -> fsm_return(). wait_for_handshake({xmlstreamelement, El}, StateData) -> - #xmlel{name = Name, children = Els} = El, - case {Name, xml:get_cdata(Els)} of + case {El#xmlel.name, exml_query:cdata(El)} of {<<"handshake">>, Digest} -> case mongoose_bin:encode_crypto([StateData#state.streamid, StateData#state.password]) of @@ -266,8 +266,8 @@ wait_for_handshake(closed, StateData) -> -spec stream_established(ejabberd:xml_stream_item(), state()) -> fsm_return(). stream_established({xmlstreamelement, El}, StateData) -> NewEl = jlib:remove_attr(<<"xmlns">>, El), - #xmlel{name = Name, attrs = Attrs} = NewEl, - From = xml:get_attr_s(<<"from">>, Attrs), + #xmlel{name = Name} = NewEl, + From = exml_query:attr(El, <<"from">>, <<>>), FromJID = case StateData#state.check_from of %% If the admin does not want to check the from field %% when accept packets from any address. @@ -286,7 +286,7 @@ stream_established({xmlstreamelement, El}, StateData) -> _ -> error end end, - To = xml:get_attr_s(<<"to">>, Attrs), + To = exml_query:attr(El, <<"to">>, <<>>), ToJID = case To of <<>> -> error; _ -> jid:from_binary(To) diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index bdecab80698..2bbaa86a6ee 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -664,7 +664,7 @@ execute_subscription_instrumentation(_HostType, _From, _To, _Type) -> Acc :: mongoose_acc:t(), Packet :: exml:element(). do_route_no_resource_presence(<<"subscribe">>, From, To, Acc, Packet) -> - Reason = xml:get_path_s(Packet, [{elem, <<"status">>}, cdata]), + Reason = exml_query:path(Packet, [{element, <<"status">>}, cdata], <<>>), do_route_no_resource_presence_prv(From, To, Acc, Packet, subscribe, Reason); do_route_no_resource_presence(<<"subscribed">>, From, To, Acc, Packet) -> do_route_no_resource_presence_prv(From, To, Acc, Packet, subscribed, <<>>); diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index 9a8b2b96ba1..659390ae0a4 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -199,14 +199,10 @@ match_filter_name(_, _) -> []. -spec case_insensitive_match(binary(), binary()) -> boolean(). -case_insensitive_match(X, Y) -> - X1 = string:to_lower(maybe_b2list(X)), - Y1 = string:to_lower(maybe_b2list(Y)), - case X1 == Y1 of - true -> true; - _-> false - end. - +case_insensitive_match(X, Y) when is_binary(X), is_binary(Y) -> + X1 = string:casefold(X), + Y1 = string:casefold(Y), + X1 =:= Y1. -spec get_state(mongooseim:host_type(), atom()) -> any(). get_state(HostType, Module) -> diff --git a/src/graphql/mongoose_graphql_enum.erl b/src/graphql/mongoose_graphql_enum.erl index 8251207928d..545b7c0483a 100644 --- a/src/graphql/mongoose_graphql_enum.erl +++ b/src/graphql/mongoose_graphql_enum.erl @@ -5,9 +5,9 @@ -ignore_xref([input/2, output/2]). input(<<"PresenceShow">>, Show) -> - {ok, list_to_binary(string:to_lower(binary_to_list(Show)))}; + {ok, string:lowercase(Show)}; input(<<"PresenceType">>, Type) -> - {ok, list_to_binary(string:to_lower(binary_to_list(Type)))}; + {ok, string:lowercase(Type)}; input(<<"Affiliation">>, <<"OWNER">>) -> {ok, owner}; input(<<"Affiliation">>, <<"MEMBER">>) -> {ok, member}; input(<<"Affiliation">>, <<"NONE">>) -> {ok, none}; @@ -33,45 +33,45 @@ input(<<"MUCAffiliation">>, <<"ADMIN">>) -> {ok, admin}; input(<<"MUCAffiliation">>, <<"OWNER">>) -> {ok, owner}; input(<<"PrivacyClassificationTags">>, Name) -> {ok, Name}; input(<<"TelephoneTags">>, Name) -> {ok, Name}; -input(<<"LogLevel">>, Name) -> {ok, list_to_atom(string:to_lower(binary_to_list(Name)))}; +input(<<"LogLevel">>, Name) -> {ok, binary_to_atom(string:lowercase(Name))}; input(<<"MetricType">>, Name) -> {ok, Name}. output(<<"DomainStatus">>, Type) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Type)))}; + {ok, string:uppercase(atom_to_binary(Type))}; output(<<"PresenceShow">>, Show) -> - {ok, list_to_binary(string:to_upper(binary_to_list(Show)))}; + {ok, string:uppercase(Show)}; output(<<"PresenceType">>, Type) -> - {ok, list_to_binary(string:to_upper(binary_to_list(Type)))}; + {ok, string:uppercase(Type)}; output(<<"AuthStatus">>, Status) -> {ok, atom_to_binary(Status, utf8)}; output(<<"AuthType">>, Type) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Type)))}; + {ok, string:uppercase(atom_to_binary(Type))}; output(<<"Affiliation">>, Aff) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Aff)))}; + {ok, string:uppercase(atom_to_binary(Aff))}; output(<<"BlockingAction">>, Action) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Action)))}; + {ok, string:uppercase(atom_to_binary(Action))}; output(<<"BlockedEntityType">>, What) -> - {ok, list_to_binary(string:to_upper(atom_to_list(What)))}; + {ok, string:uppercase(atom_to_binary(What))}; output(<<"ContactSub">>, Type) when Type =:= both; Type =:= from; Type =:= to; Type =:= none -> - {ok, list_to_binary(string:to_upper(atom_to_list(Type)))}; + {ok, string:uppercase(atom_to_binary(Type))}; output(<<"ContactAsk">>, Type) when Type =:= subscrube; Type =:= unsubscribe; Type =:= in; Type =:= out; Type =:= both; Type =:= none -> - {ok, list_to_binary(string:to_upper(atom_to_list(Type)))}; + {ok, string:uppercase(atom_to_binary(Type))}; output(<<"MUCRole">>, Role) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Role)))}; + {ok, string:uppercase(atom_to_binary(Role))}; output(<<"MUCAffiliation">>, Aff) -> - {ok, list_to_binary(string:to_upper(atom_to_list(Aff)))}; + {ok, string:uppercase(atom_to_binary(Aff))}; output(<<"AddressTags">>, Name) -> {ok, Name}; output(<<"EmailTags">>, Name) -> {ok, Name}; output(<<"PrivacyClassificationTags">>, Name) -> {ok, Name}; -output(<<"LogLevel">>, Name) -> {ok, list_to_binary(string:to_upper(atom_to_list(Name)))}; +output(<<"LogLevel">>, Name) -> {ok, string:uppercase(atom_to_binary(Name))}; output(<<"TelephoneTags">>, Name) -> {ok, Name}; output(<<"MetricType">>, Type) -> {ok, Type}; output(<<"StatusCode">>, Code) -> {ok, Code}. diff --git a/src/http_upload/mod_http_upload.erl b/src/http_upload/mod_http_upload.erl index 389daa8a49f..27dd61e5f3a 100644 --- a/src/http_upload/mod_http_upload.erl +++ b/src/http_upload/mod_http_upload.erl @@ -164,8 +164,7 @@ process_disco_iq(Acc, _From, _To, #iq{type = set, lang = Lang, sub_el = SubEl} = Error = mongoose_xmpp_errors:not_allowed(Lang, ErrorMsg), {Acc, IQ#iq{type = error, sub_el = [SubEl, Error]}}; process_disco_iq(Acc, _From, _To, #iq{type = get, lang = Lang, sub_el = SubEl} = IQ, _Extra) -> - Node = xml:get_tag_attr_s(<<"node">>, SubEl), - case Node of + case exml_query:attr(SubEl, <<"node">>, <<>>) of <<>> -> Identity = mongoose_disco:identities_to_xml(disco_identity(Lang)), Info = disco_info(mongoose_acc:host_type(Acc)), diff --git a/src/jlib.erl b/src/jlib.erl index fa56fab7f00..f6389079e33 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -39,8 +39,6 @@ iq_query_or_response_info/1, iq_to_xml/1, timestamp_to_xml/3, - decode_base64/1, - encode_base64/1, rsm_encode/1, rsm_decode/1, stanza_error/3, @@ -51,6 +49,11 @@ maybe_append_delay/4, remove_delay_tags/1]). +-export([remove_cdata/1, + append_subtags/2, + replace_tag_attr/3, + replace_subelement/2]). + -ignore_xref([make_result_iq_reply/1]). -include_lib("exml/include/exml.hrl"). @@ -68,8 +71,6 @@ -type xmlch() :: exml:element() | xmlcdata(). % (XML ch)ild --type binary_pair() :: {binary(), binary()}. - -type iq() :: #iq{}. -type rsm_in() :: #rsm_in{}. @@ -79,7 +80,6 @@ -type rfc3339_string() :: [byte(), ...]. -export_type([xmlstreamstart/0, xmlstreamend/0, xmlstreamel/0, - binary_pair/0, rsm_in/0, rsm_out/0, xmlcdata/0, xmlch/0, @@ -88,30 +88,30 @@ -spec make_result_iq_reply(exml:element()) -> exml:element(); (iq()) -> iq(). -make_result_iq_reply(XE = #xmlel{attrs = Attrs}) -> - NewAttrs = make_result_iq_reply_attrs(Attrs), +make_result_iq_reply(XE = #xmlel{}) -> + NewAttrs = make_result_iq_reply_attrs(XE), XE#xmlel{attrs = NewAttrs}; make_result_iq_reply(IQ = #iq{}) -> - IQ#iq{ type = result }. + IQ#iq{type = result}. --spec make_result_iq_reply_attrs([binary_pair()]) -> [binary_pair(), ...]. -make_result_iq_reply_attrs(Attrs) -> - To = xml:get_attr(<<"to">>, Attrs), - From = xml:get_attr(<<"from">>, Attrs), +-spec make_result_iq_reply_attrs(exml:element()) -> [exml:attr(), ...]. +make_result_iq_reply_attrs(#xmlel{attrs = Attrs} = Element) -> + To = exml_query:attr(Element, <<"to">>), + From = exml_query:attr(Element, <<"from">>), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of - {value, ToVal} -> - [{<<"from">>, ToVal} | Attrs2]; - _ -> - Attrs2 + undefined -> + Attrs2; + ToVal -> + [{<<"from">>, ToVal} | Attrs2] end, Attrs4 = case From of - {value, FromVal} -> - [{<<"to">>, FromVal} | Attrs3]; - _ -> - Attrs3 + undefined -> + Attrs3; + FromVal -> + [{<<"to">>, FromVal} | Attrs3] end, Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4), [{<<"type">>, <<"result">>} | Attrs5]. @@ -140,33 +140,30 @@ make_error_reply(Acc, Packet, Error) -> make_error_reply_from_element(Packet, Error)} end. -make_error_reply_from_element(#xmlel{name = Name, attrs = Attrs, - children = SubTags}, Error) -> - NewAttrs = make_error_reply_attrs(Attrs), - #xmlel{name = Name, attrs = NewAttrs, children = SubTags ++ [Error]}. +make_error_reply_from_element(#xmlel{name = Name, children = SubTags} = Element, Error) -> + NewAttrs = make_error_reply_attrs(Element), + #xmlel{name = Name, attrs = NewAttrs, children = [Error | SubTags]}. --spec make_error_reply_attrs([binary_pair()]) -> [binary_pair(), ...]. -make_error_reply_attrs(Attrs) -> - To = xml:get_attr(<<"to">>, Attrs), - From = xml:get_attr(<<"from">>, Attrs), +-spec make_error_reply_attrs(exml:element()) -> [exml:attr(), ...]. +make_error_reply_attrs(#xmlel{attrs = Attrs} = Element) -> + To = exml_query:attr(Element, <<"to">>), + From = exml_query:attr(Element, <<"from">>), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of - {value, ToVal} -> - [{<<"from">>, ToVal} | Attrs2]; - _ -> - Attrs2 + undefined -> + Attrs2; + ToVal -> + [{<<"from">>, ToVal} | Attrs2] end, Attrs4 = case From of - {value, FromVal} -> - [{<<"to">>, FromVal} | Attrs3]; - _ -> - Attrs3 + undefined -> + Attrs3; + FromVal -> + [{<<"to">>, FromVal} | Attrs3] end, Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4), - Attrs6 = [{<<"type">>, <<"error">>} | Attrs5], - Attrs6. - + [{<<"type">>, <<"error">>} | Attrs5]. -spec make_config_change_message(binary()) -> exml:element(). make_config_change_message(Status) -> @@ -202,7 +199,7 @@ make_invitation(From, Password, Reason) -> -spec replace_from_to_attrs(From :: binary(), To :: binary() | undefined, - [binary_pair()]) -> [binary_pair()]. + [exml:attr()]) -> [exml:attr()]. replace_from_to_attrs(From, To, Attrs) -> Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), @@ -253,19 +250,18 @@ make_reply_from_type(_) -> -spec extract_xmlns([exml:element()]) -> binary(). extract_xmlns([Element]) -> - xml:get_tag_attr_s(<<"xmlns">>, Element); + exml_query:attr(Element, <<"xmlns">>, <<>>); extract_xmlns(_) -> <<>>. -spec iq_info_internal(exml:element(), Filter :: 'any' | 'request') -> 'invalid' | 'not_iq' | 'reply' | iq(). -iq_info_internal(#xmlel{name = Name, attrs = Attrs, - children = Els}, Filter) when Name == <<"iq">> -> +iq_info_internal(#xmlel{name = Name, children = Els} = Element, Filter) when Name == <<"iq">> -> %% Filter is either request or any. If it is request, any replies %% are converted to the atom reply. - ID = xml:get_attr_s(<<"id">>, Attrs), - Type = xml:get_attr_s(<<"type">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + ID = exml_query:attr(Element, <<"id">>, <<>>), + Type = exml_query:attr(Element, <<"type">>, <<>>), + Lang = exml_query:attr(Element, <<"xml:lang">>, <<>>), {Type1, Class} = make_reply_from_type(Type), case {Type1, Class, Filter} of {invalid, _, _} -> @@ -274,18 +270,16 @@ iq_info_internal(#xmlel{name = Name, attrs = Attrs, %% The iq record is a bit strange. The sub_el field is an %% XML tuple for requests, but a list of XML tuples for %% responses. - FilteredEls = xml:remove_cdata(Els), + FilteredEls = remove_cdata(Els), {XMLNS, SubEl} = case {Class, FilteredEls} of - {request, [#xmlel{attrs = Attrs2}]} -> - {xml:get_attr_s(<<"xmlns">>, Attrs2), - hd(FilteredEls)}; + {request, [El2]} -> + {exml_query:attr(El2, <<"xmlns">>, <<>>), hd(FilteredEls)}; {reply, _} -> %% Find the namespace of the first non-error %% element, if there is one. NonErrorEls = [El || - #xmlel{name = SubName} = El - <- FilteredEls, + #xmlel{name = SubName} = El <- FilteredEls, SubName /= <<"error">>], {extract_xmlns(NonErrorEls), FilteredEls}; _ -> @@ -335,9 +329,9 @@ sub_el_to_els(Es) when is_list(Es) -> Es. -spec rsm_decode(exml:element() | iq()) -> none | #rsm_in{}. rsm_decode(#iq{sub_el = SubEl})-> rsm_decode(SubEl); -rsm_decode(#xmlel{}=SubEl) -> - case xml:get_subtag(SubEl, <<"set">>) of - false -> +rsm_decode(#xmlel{} = SubEl) -> + case exml_query:subelement(SubEl, <<"set">>) of + undefined -> none; #xmlel{name = <<"set">>, children = SubEls} -> lists:foldl(fun rsm_parse_element/2, #rsm_in{}, SubEls) @@ -345,17 +339,17 @@ rsm_decode(#xmlel{}=SubEl) -> -spec rsm_parse_element(exml:element(), rsm_in()) -> rsm_in(). rsm_parse_element(#xmlel{name = <<"max">>, attrs = []} = Elem, RsmIn) -> - CountStr = xml:get_tag_cdata(Elem), + CountStr = exml_query:cdata(Elem), {Count, _} = string:to_integer(binary_to_list(CountStr)), RsmIn#rsm_in{max = Count}; rsm_parse_element(#xmlel{name = <<"before">>, attrs = []} = Elem, RsmIn) -> - UID = xml:get_tag_cdata(Elem), + UID = exml_query:cdata(Elem), RsmIn#rsm_in{direction = before, id = UID}; rsm_parse_element(#xmlel{name = <<"after">>, attrs = []} = Elem, RsmIn) -> - UID = xml:get_tag_cdata(Elem), + UID = exml_query:cdata(Elem), RsmIn#rsm_in{direction = aft, id = UID}; rsm_parse_element(#xmlel{name = <<"index">>, attrs = []} = Elem, RsmIn) -> - IndexStr = xml:get_tag_cdata(Elem), + IndexStr = exml_query:cdata(Elem), {Index, _} = string:to_integer(binary_to_list(IndexStr)), RsmIn#rsm_in{index = Index}; rsm_parse_element(_, RsmIn)-> @@ -397,7 +391,8 @@ rsm_encode_count(Count, Arr) -> [#xmlel{name = <<"count">>, children = [#xmlcdata{content = i2b(Count)}]} | Arr]. -spec i2b(integer()) -> binary(). -i2b(I) when is_integer(I) -> list_to_binary(integer_to_list(I)). +i2b(I) when is_integer(I) -> + integer_to_binary(I). -spec timestamp_to_xml(TimestampString :: rfc3339_string(), FromJID :: jid:simple_jid() | jid:jid() | undefined, @@ -416,14 +411,6 @@ timestamp_to_xml(TimestampString, FromJID, Desc) -> {<<"stamp">>, list_to_binary(TimestampString)} | From], children = Text}. --spec decode_base64(binary() | string()) -> binary(). -decode_base64(S) -> - base64:mime_decode(S). - --spec encode_base64(binary() | string()) -> binary(). -encode_base64(B) -> - base64:encode(B). - -spec stanza_error( Code :: binary() , Type :: binary() , Condition :: binary() @@ -506,21 +493,48 @@ maybe_append_delay(Packet = #xmlel{children = Children}, From, TS, Desc) -> remove_delay_tags(#xmlel{children = Els} = Packet) -> NEl = lists:foldl( - fun(#xmlel{name= <<"delay">>, attrs = Attrs} = R, El)-> - case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_DELAY -> - El; - _ -> - El ++ [R] - end; - (#xmlel{name= <<"x">>, attrs = Attrs } = R, El) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_DELAY91 -> - El; - _ -> - El ++ [R] - end; - (R, El) -> - El ++ [R] - end, [], Els), - Packet#xmlel{children=NEl}. + fun(#xmlel{name= <<"delay">>} = R, El) -> + case exml_query:attr(R, <<"xmlns">>) of + ?NS_DELAY -> + El; + _ -> + El ++ [R] + end; + (#xmlel{name= <<"x">>} = R, El) -> + case exml_query:attr(R, <<"xmlns">>) of + ?NS_DELAY91 -> + El; + _ -> + El ++ [R] + end; + (R, El) -> + El ++ [R] + end, [], Els), + Packet#xmlel{children = NEl}. + +-spec remove_cdata([xmlch()]) -> [xmlch()]. +remove_cdata(L) -> + [E || E <- L, remove_cdata_p(E)]. + +-spec remove_cdata_p(xmlch()) -> boolean(). +remove_cdata_p(#xmlel{}) -> true; +remove_cdata_p(_) -> false. + +-spec append_subtags(exml:element(), [xmlch()]) -> exml:element(). +append_subtags(XE = #xmlel{children = SubTags1}, SubTags2) -> + XE#xmlel{children = SubTags1 ++ SubTags2}. + +-spec replace_tag_attr(Attr :: binary(), Value :: binary(), exml:element() + ) -> exml:element(). +replace_tag_attr(Attr, Value, XE = #xmlel{attrs = Attrs}) -> + Attrs1 = lists:keydelete(Attr, 1, Attrs), + Attrs2 = [{Attr, Value} | Attrs1], + XE#xmlel{attrs = Attrs2}. + +%% @doc Given an element and a new subelement, +%% replace the instance of the subelement in element with the new subelement. +-spec replace_subelement(exml:element(), exml:element()) -> exml:element(). +replace_subelement(XE = #xmlel{children = SubEls}, NewSubEl) -> + {_, NameNewSubEl, _, _} = NewSubEl, + SubEls2 = lists:keyreplace(NameNewSubEl, 2, SubEls, NewSubEl), + XE#xmlel{children = SubEls2}. diff --git a/src/mam/mod_mam_utils.erl b/src/mam/mod_mam_utils.erl index 56b2240ea70..6993a7f32b9 100644 --- a/src/mam/mod_mam_utils.erl +++ b/src/mam/mod_mam_utils.erl @@ -263,12 +263,12 @@ append_arcid_elem(<<"stanza-id">>, By, Id, Packet) -> Archived = #xmlel{ name = <<"stanza-id">>, attrs=[{<<"by">>, By}, {<<"id">>, Id}, {<<"xmlns">>, ?NS_STANZAID}]}, - xml:append_subtags(Packet, [Archived]); + jlib:append_subtags(Packet, [Archived]); append_arcid_elem(ElemName, By, Id, Packet) -> Archived = #xmlel{ name = ElemName, attrs=[{<<"by">>, By}, {<<"id">>, Id}]}, - xml:append_subtags(Packet, [Archived]). + jlib:append_subtags(Packet, [Archived]). -spec delete_arcid_elem(ElemName :: binary(), By :: binary(), exml:element()) -> exml:element(). delete_arcid_elem(ElemName, By, Packet=#xmlel{children=Cs}) -> @@ -292,7 +292,7 @@ append_x_user_element(FromJID, Role, Affiliation, Packet) -> name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [ItemElem]}, - xml:append_subtags(Packet, [X]). + jlib:append_subtags(Packet, [X]). x_user_item(FromJID, Role, Affiliation) -> #xmlel{ @@ -826,7 +826,7 @@ normalize_search_text(undefined, _WordSeparator) -> undefined; normalize_search_text(Text, WordSeparator) -> BodyString = unicode:characters_to_list(Text), - LowerBody = string:to_lower(BodyString), + LowerBody = string:lowercase(BodyString), ReOpts = [{return, list}, global, unicode, ucp], Re0 = re:replace(LowerBody, "[, .:;-?!]+", " ", ReOpts), Re1 = re:replace(Re0, "([^\\w ]+)|(^\\s+)|(\\s+$)", "", ReOpts), @@ -1114,7 +1114,7 @@ is_most_recent_page(_PageSize, _TotalCount, _Offset, _MessageRows) -> -spec maybe_set_client_xmlns(boolean(), exml:element()) -> exml:element(). maybe_set_client_xmlns(true, Packet) -> - xml:replace_tag_attr(<<"xmlns">>, <<"jabber:client">>, Packet); + jlib:replace_tag_attr(<<"xmlns">>, <<"jabber:client">>, Packet); maybe_set_client_xmlns(false, Packet) -> Packet. diff --git a/src/mod_auth_token.erl b/src/mod_auth_token.erl index edf9280c9a1..4a0bb0a3605 100644 --- a/src/mod_auth_token.erl +++ b/src/mod_auth_token.erl @@ -357,7 +357,7 @@ token_to_xmlel(#token{type = Type} = T) -> refresh -> <<"refresh_token">> end, attrs = [{<<"xmlns">>, ?NS_ESL_TOKEN_AUTH}], - children = [#xmlcdata{content = jlib:encode_base64(serialize(T))}]}. + children = [#xmlcdata{content = base64:encode(serialize(T))}]}. %% args: Token with Mac decoded from transport, #token %% is shared between tokens. Introduce other container types if diff --git a/src/mod_bosh_socket.erl b/src/mod_bosh_socket.erl index a0a57cfb08e..7334914df06 100644 --- a/src/mod_bosh_socket.erl +++ b/src/mod_bosh_socket.erl @@ -1032,9 +1032,9 @@ maybe_add_default_ns_to_children(Children) -> lists:map(fun maybe_add_default_ns/1, Children). maybe_add_default_ns(#xmlel{name = Name, attrs = Attrs} = El) - when Name =:= <<"message">>; Name =:= <<"presence">>; Name =:= <<"iq">> -> - case xml:get_attr(<<"xmlns">>, Attrs) of - false -> + when Name =:= <<"message">>; Name =:= <<"presence">>; Name =:= <<"iq">> -> + case exml_query:attr(El, <<"xmlns">>) of + undefined -> El#xmlel{attrs = [{<<"xmlns">>, ?NS_CLIENT} | Attrs]}; _ -> El diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 1b789d8408b..ca973e317cf 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -150,18 +150,18 @@ get_features(HostType, #caps{node = Node, version = Version, exts = Exts}) -> -spec read_caps([exml:element()]) -> nothing | caps(). read_caps(Els) -> read_caps(Els, nothing). -read_caps([#xmlel{name = <<"c">>, attrs = Attrs} | Tail], Result) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of +read_caps([#xmlel{name = <<"c">>} = Element | Tail], Result) -> + case exml_query:attr(Element, <<"xmlns">>, <<>>) of ?NS_CAPS -> - Node = xml:get_attr_s(<<"node">>, Attrs), - Version = xml:get_attr_s(<<"ver">>, Attrs), - Hash = xml:get_attr_s(<<"hash">>, Attrs), - Exts = mongoose_bin:tokens(xml:get_attr_s(<<"ext">>, Attrs), <<" ">>), + Node = exml_query:attr(Element, <<"node">>, <<>>), + Version = exml_query:attr(Element, <<"ver">>, <<>>), + Hash = exml_query:attr(Element, <<"hash">>, <<>>), + Exts = mongoose_bin:tokens(exml_query:attr(Element, <<"ext">>, <<>>), <<" ">>), read_caps(Tail, #caps{node = Node, hash = Hash, version = Version, exts = Exts}); _ -> read_caps(Tail, Result) end; -read_caps([#xmlel{name = <<"x">>, attrs = Attrs} | Tail], Result) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of +read_caps([#xmlel{name = <<"x">>} = Element | Tail], Result) -> + case exml_query:attr(Element, <<"xmlns">>, <<>>) of ?NS_MUC_USER -> nothing; _ -> read_caps(Tail, Result) end; @@ -181,8 +181,8 @@ user_send_presence(Acc, _, _) -> user_send_presence(Acc, #jid{luser = User, lserver = LServer} = From, #jid{luser = User, lserver = LServer, lresource = <<>>}, - #xmlel{attrs = Attrs, children = Elements}) -> - Type = xml:get_attr_s(<<"type">>, Attrs), + #xmlel{children = Elements} = Element) -> + Type = exml_query:attr(Element, <<"type">>, <<>>), handle_presence(Acc, LServer, From, Type, Elements); user_send_presence(Acc, _, _, _) -> Acc. @@ -252,11 +252,11 @@ handle_presence(Acc, _LServer, _From, _Type, _Elements) -> -spec user_receive_presence(mongoose_acc:t(), mongoose_c2s_hooks:params(), gen_hook:extra()) -> mongoose_c2s_hooks:result(). user_receive_presence(Acc0, #{c2s_data := C2SData}, _Extra) -> - {From, To, #xmlel{attrs = Attrs, children = Els} = Packet} = mongoose_acc:packet(Acc0), + {From, To, #xmlel{children = Els} = Packet} = mongoose_acc:packet(Acc0), ?LOG_DEBUG(#{what => user_receive_presence, to => jid:to_binary(To), from => jid:to_binary(From), exml_packet => Packet, c2s_state => C2SData}), - Type = xml:get_attr_s(<<"type">>, Attrs), + Type = exml_query:attr(Packet, <<"type">>, <<>>), #jid{lserver = LServer} = mongoose_c2s:get_jid(C2SData), Acc = case mongoose_domain_api:get_host_type(From#jid.lserver) of {error, not_found} -> @@ -457,9 +457,8 @@ feature_response(Acc, #iq{type = result, sub_el = [#xmlel{children = Els}]}, NodePair = {Caps#caps.node, SubNode}, case check_hash(Caps, Els) of true -> - Features = lists:flatmap(fun (#xmlel{name = <<"feature">>, - attrs = FAttrs}) -> - [xml:get_attr_s(<<"var">>, FAttrs)]; + Features = lists:flatmap(fun (#xmlel{name = <<"feature">>} = El) -> + [exml_query:attr(El, <<"var">>, <<>>)]; (_) -> [] end, Els), @@ -512,14 +511,14 @@ make_my_disco_hash(HostType, LServer) -> make_disco_hash(DiscoEls, Algo) -> Concat = list_to_binary([concat_identities(DiscoEls), concat_features(DiscoEls), concat_info(DiscoEls)]), - jlib:encode_base64(case Algo of - md5 -> erlang:md5(Concat); - sha1 -> crypto:hash(sha, Concat); - sha224 -> crypto:hash(sha224, Concat); - sha256 -> crypto:hash(sha256, Concat); - sha384 -> crypto:hash(sha384, Concat); - sha512 -> crypto:hash(sha512, Concat) - end). + base64:encode(case Algo of + md5 -> erlang:md5(Concat); + sha1 -> crypto:hash(sha, Concat); + sha224 -> crypto:hash(sha224, Concat); + sha256 -> crypto:hash(sha256, Concat); + sha384 -> crypto:hash(sha384, Concat); + sha512 -> crypto:hash(sha512, Concat) + end). check_hash(Caps, Els) -> case Caps#caps.hash of @@ -539,23 +538,19 @@ check_hash(Caps, Els) -> end. concat_features(Els) -> - lists:usort(lists:flatmap(fun (#xmlel{name = - <<"feature">>, - attrs = Attrs}) -> - [[xml:get_attr_s(<<"var">>, Attrs), $<]]; + lists:usort(lists:flatmap(fun (#xmlel{name = <<"feature">>} = Element) -> + [[exml_query:attr(Element, <<"var">>, <<>>), $<]]; (_) -> [] end, Els)). concat_identities(Els) -> - lists:sort(lists:flatmap(fun (#xmlel{name = - <<"identity">>, - attrs = Attrs}) -> - [[xml:get_attr_s(<<"category">>, Attrs), - $/, xml:get_attr_s(<<"type">>, Attrs), + lists:sort(lists:flatmap(fun (#xmlel{name = <<"identity">>} = Element) -> + [[exml_query:attr(Element, <<"category">>, <<>>), + $/, exml_query:attr(Element, <<"type">>, <<>>), $/, - xml:get_attr_s(<<"xml:lang">>, Attrs), - $/, xml:get_attr_s(<<"name">>, Attrs), + exml_query:attr(Element, <<"xml:lang">>, <<>>), + $/, exml_query:attr(Element, <<"name">>, <<>>), $<]]; (_) -> [] end, diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 528b3275456..f5b55d33afb 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -64,16 +64,10 @@ supported_features() -> [dynamic_domains]. +-spec is_carbon_copy(exml:element()) -> boolean(). is_carbon_copy(Packet) -> - case xml:get_subtag(Packet, <<"sent">>) of - #xmlel{name = <<"sent">>, attrs = AAttrs} -> - case xml:get_attr_s(<<"xmlns">>, AAttrs) of - ?NS_CC_2 -> true; - ?NS_CC_1 -> true; - _ -> false - end; - _ -> false - end. + XmlNs = exml_query:path(Packet, [{element, <<"sent">>}, {attr, <<"xmlns">>}]), + ?NS_CC_2 =:= XmlNs orelse ?NS_CC_1 =:= XmlNs. %% Default IQDisc is no_queue: %% executes disable/enable actions in the c2s process itself diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 1aaf7aaeb71..af833801273 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -129,7 +129,7 @@ process_local_iq_items(Acc, _From, _To, #iq{type = set, sub_el = SubEl} = IQ, _E {Acc, IQ#iq{type = error, sub_el = [SubEl, mongoose_xmpp_errors:not_allowed()]}}; process_local_iq_items(Acc, From, To, #iq{type = get, lang = Lang, sub_el = SubEl} = IQ, _Extra) -> HostType = mongoose_acc:host_type(Acc), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), case mongoose_disco:get_local_items(HostType, From, To, Node, Lang) of empty -> Error = mongoose_xmpp_errors:item_not_found(), @@ -144,7 +144,7 @@ process_local_iq_info(Acc, _From, _To, #iq{type = set, sub_el = SubEl} = IQ, _Ex {Acc, IQ#iq{type = error, sub_el = [SubEl, mongoose_xmpp_errors:not_allowed()]}}; process_local_iq_info(Acc, From, To, #iq{type = get, lang = Lang, sub_el = SubEl} = IQ, _Extra) -> HostType = mongoose_acc:host_type(Acc), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), case mongoose_disco:get_local_features(HostType, From, To, Node, Lang) of empty -> Error = mongoose_xmpp_errors:item_not_found(), @@ -163,7 +163,7 @@ process_sm_iq_items(Acc, From, To, #iq{type = get, lang = Lang, sub_el = SubEl} case is_presence_subscribed(From, To) of true -> HostType = mongoose_acc:host_type(Acc), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), case mongoose_disco:get_sm_items(HostType, From, To, Node, Lang) of empty -> Error = sm_error(From, To), @@ -183,7 +183,7 @@ process_sm_iq_info(Acc, From, To, #iq{type = get, lang = Lang, sub_el = SubEl} = case is_presence_subscribed(From, To) of true -> HostType = mongoose_acc:host_type(Acc), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), case mongoose_disco:get_sm_features(HostType, From, To, Node, Lang) of empty -> Error = sm_error(From, To), diff --git a/src/mod_presence.erl b/src/mod_presence.erl index 9da95035247..d81fb9d2f5a 100644 --- a/src/mod_presence.erl +++ b/src/mod_presence.erl @@ -203,7 +203,7 @@ foreign_event(Acc, _Params, _Extra) -> get_showtag(undefined) -> <<"unavailable">>; get_showtag(Presence) -> - case xml:get_path_s(Presence, [{elem, <<"show">>}, cdata]) of + case exml_query:path(Presence, [{element, <<"show">>}, cdata], <<>>) of <<>> -> <<"available">>; ShowTag -> ShowTag end. @@ -213,7 +213,7 @@ get_showtag(Presence) -> get_statustag(undefined) -> <<>>; get_statustag(Presence) -> - xml:get_path_s(Presence, [{elem, <<"status">>}, cdata]). + exml_query:path(Presence, [{element, <<"status">>}, cdata], <<>>). -spec handle_subscription_change( mongoose_acc:t(), mongoose_c2s:data(), mod_roster:contact(), term(), state()) -> diff --git a/src/mod_private.erl b/src/mod_private.erl index 11f879a8f74..7748bb768e5 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -163,8 +163,8 @@ choose_strategy(true, get) -> get; choose_strategy(true, set) -> set; choose_strategy(_, _ ) -> forbidden. -element_to_namespace(#xmlel{attrs = Attrs}) -> - xml:get_attr_s(<<"xmlns">>, Attrs); +element_to_namespace(#xmlel{} = El) -> + exml_query:attr(El, <<"xmlns">>, <<>>); element_to_namespace(_) -> <<>>. diff --git a/src/mongoose_admin_api/mongoose_admin_api_messages.erl b/src/mongoose_admin_api/mongoose_admin_api_messages.erl index 729b8d98629..8d9d9b4680b 100644 --- a/src/mongoose_admin_api/mongoose_admin_api_messages.erl +++ b/src/mongoose_admin_api/mongoose_admin_api_messages.erl @@ -93,10 +93,7 @@ handle_post(Req, State) -> row_to_map(#{id := Id, jid := From, packet := Msg}) -> Jbin = jid:to_binary(From), {Msec, _} = mod_mam_utils:decode_compact_uuid(Id), - MsgId = case xml:get_tag_attr(<<"id">>, Msg) of - {value, MId} -> MId; - false -> <<"">> - end, + MsgId = exml_query:attr(Msg, <<"id">>, <<>>), Body = exml_query:path(Msg, [{element, <<"body">>}, cdata]), #{sender => Jbin, timestamp => round(Msec / 1000000), message_id => MsgId, body => Body}. diff --git a/src/muc/mod_muc.erl b/src/muc/mod_muc.erl index b4ff05f0c4b..24de1a94b7a 100644 --- a/src/muc/mod_muc.erl +++ b/src/muc/mod_muc.erl @@ -630,8 +630,7 @@ process_packet(Acc, From, To, El, #{state := State}) -> route_to_room(MucHost, Room, {From, To, Acc, El}, State), Acc; _ -> - #xmlel{attrs = Attrs} = El, - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = exml_query:attr(El, <<"xml:lang">>, <<>>), ErrText = <<"Access denied by service policy">>, ejabberd_router:route_error_reply(To, From, Acc, mongoose_xmpp_errors:forbidden(Lang, ErrText)) @@ -663,9 +662,7 @@ route_to_online_room(Pid, {From, To, Acc, Packet}) -> -spec get_registered_room_or_route_error(muc_host(), room(), from_to_packet(), state()) -> {ok, pid()} | {route_error, binary()}. get_registered_room_or_route_error(MucHost, Room, {From, To, Acc, Packet}, State) -> - #xmlel{name = Name, attrs = Attrs} = Packet, - Type = xml:get_attr_s(<<"type">>, Attrs), - case {Name, Type} of + case {Packet#xmlel.name, exml_query:attr(Packet, <<"type">>, <<>>)} of {<<"presence">>, <<>>} -> get_registered_room_or_route_error_from_presence(MucHost, Room, From, To, Acc, Packet, State); _ -> @@ -753,8 +750,7 @@ route_by_nick(<<>>, {_, _, _, Packet} = Routed, State) -> #xmlel{name = Name} = Packet, route_by_type(Name, Routed, State); route_by_nick(_Nick, {From, To, Acc, Packet}, _State) -> - #xmlel{attrs = Attrs} = Packet, - case xml:get_attr_s(<<"type">>, Attrs) of + case exml_query:attr(Packet, <<"type">>) of <<"error">> -> Acc; <<"result">> -> @@ -829,17 +825,16 @@ route_by_type(<<"message">>, {From, To, Acc, Packet}, access = {_, _, AccessAdmin, _}} = State) -> MucHost = To#jid.lserver, ServerHost = make_server_host(To, State), - #xmlel{attrs = Attrs} = Packet, - case xml:get_attr_s(<<"type">>, Attrs) of + case exml_query:attr(Packet, <<"type">>) of <<"error">> -> ok; _ -> case acl:match_rule(HostType, ServerHost, AccessAdmin, From) of allow -> - Msg = xml:get_path_s(Packet, [{elem, <<"body">>}, cdata]), + Msg = exml_query:path(Packet, [{element, <<"body">>}, cdata], <<>>), broadcast_service_message(MucHost, Msg); _ -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), ErrTxt = <<"Only service administrators are allowed to send service messages">>, Err = mongoose_xmpp_errors:forbidden(Lang, ErrTxt), {Acc1, ErrorReply} = jlib:make_error_reply(Acc, Packet, Err), @@ -1113,8 +1108,8 @@ iq_set_unregister_info(HostType, MucHost, From, _Lang) -> jid:jid(), exml:element(), ejabberd:lang()) -> {'error', exml:element()} | {'result', []}. process_iq_register_set(HostType, MucHost, From, SubEl, Lang) -> - case xml:get_subtag(SubEl, <<"remove">>) of - false -> + case exml_query:subelement(SubEl, <<"remove">>) of + undefined -> case mongoose_data_forms:find_and_parse_form(SubEl) of #{type := <<"cancel">>} -> {result, []}; diff --git a/src/muc/mod_muc_api.erl b/src/muc/mod_muc_api.erl index ec5b334ba5f..4a2a0ba37f9 100644 --- a/src/muc/mod_muc_api.erl +++ b/src/muc/mod_muc_api.erl @@ -420,7 +420,7 @@ filter_affs_by_type(Type, Affs) -> [Aff || Aff = {_, T} <- Affs, T =:= Type]. format_xml_error(#xmlel{name = <<"error">>} = E, Value) -> case unwrap_xml_error(E) of {<<"406">>, <<"modify">>, <<"not-acceptable">>} -> - Msg = xml:get_path_s(E, [{elem, <<"text">>}, cdata]), + Msg = exml_query:path(E, [{element, <<"text">>}, cdata], <<>>), {cannot_modify, Msg}; {<<"403">>, <<"auth">>, <<"forbidden">>} -> {not_allowed, no_permission_msg("affiliation", Value)}; diff --git a/src/muc/mod_muc_log.erl b/src/muc/mod_muc_log.erl index 6a866dbc993..b85f2757b34 100644 --- a/src/muc/mod_muc_log.erl +++ b/src/muc/mod_muc_log.erl @@ -330,14 +330,14 @@ code_change(_OldVsn, State, _Extra) -> -spec add_to_log2(command(), {mod_muc:nick(), mod_muc:packet()}, mod_muc:room(), list(), logstate()) -> 'ok'. add_to_log2(text, {Nick, Packet}, Room, Opts, State) -> - case {xml:get_subtag(Packet, <<"subject">>), xml:get_subtag(Packet, <<"body">>)} of - {false, false} -> + case {exml_query:subelement(Packet, <<"subject">>), exml_query:subelement(Packet, <<"body">>)} of + {undefined, undefined} -> ok; - {false, SubEl} -> - Message = {body, xml:get_tag_cdata(SubEl)}, + {undefined, SubEl} -> + Message = {body, exml_query:cdata(SubEl)}, add_message_to_log(Nick, Message, Room, Opts, State); {SubEl, _} -> - Message = {subject, xml:get_tag_cdata(SubEl)}, + Message = {subject, exml_query:cdata(SubEl)}, add_message_to_log(Nick, Message, Room, Opts, State) end; add_to_log2(roomconfig_change, _Occupants, Room, Opts, State) -> @@ -650,7 +650,7 @@ make_dir_rec(Dir) -> %% {ok, F1}=file:open("valid-xhtml10.png", [read]). %% {ok, F1b}=file:read(F1, 1000000). %% c("../../ejabberd/src/jlib.erl"). -%% jlib:encode_base64(F1b). +%% base64:encode(F1b). image_base64(<<"powered-by-erlang.png">>) -> <<"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAYAAAD+xQNoAAADN0lEQVRo3u1a" @@ -791,7 +791,7 @@ create_image_files(ImagesDir) -> fun(Filename) -> FilenameFull = filename:join([ImagesDir, Filename]), {ok, F} = file:open(FilenameFull, [write]), - Image = jlib:decode_base64(image_base64(Filename)), + Image = base64:mime_decode(image_base64(Filename)), io:format(F, "~s", [Image]), file:close(F) end, diff --git a/src/muc/mod_muc_room.erl b/src/muc/mod_muc_room.erl index bea7db92dad..e33db2a7bd8 100644 --- a/src/muc/mod_muc_room.erl +++ b/src/muc/mod_muc_room.erl @@ -367,11 +367,10 @@ init_restored(#{init_type := start_restored, %% configuration form from the creator. Responds with error to any other queries. -spec locked_error({'route', jid:jid(), _, mongoose_acc:t(), exml:element()}, statename(), state()) -> fsm_return(). -locked_error({route, From, ToNick, Acc, #xmlel{attrs = Attrs} = Packet}, - NextState, StateData) -> +locked_error({route, From, ToNick, Acc, Packet}, NextState, StateData) -> ?LOG_INFO(ls(#{what => muc_route_to_locked_room, acc => Acc}, StateData)), ErrText = <<"This room is locked">>, - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), {Acc1, Err} = jlib:make_error_reply(Acc, Packet, mongoose_xmpp_errors:item_not_found(Lang, ErrText)), ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), @@ -402,7 +401,7 @@ initial_state({route, From, ToNick, _Acc, % TOODOO -spec is_query_allowed(exml:element()) -> boolean(). is_query_allowed(#xmlel{children = Els}) -> - case xml:remove_cdata(Els) of + case jlib:remove_cdata(Els) of [#xmlel{name = <<"destroy">>}] -> true; [El] -> @@ -468,9 +467,9 @@ locked_state({route, From, _ToNick, Acc, end; %% Let owner leave. Destroy the room. locked_state({route, From, ToNick, _Acc, - #xmlel{name = <<"presence">>, attrs = Attrs} = Presence} = Call, + #xmlel{name = <<"presence">>} = Presence} = Call, StateData) -> - case xml:get_attr_s(<<"type">>, Attrs) =:= <<"unavailable">> + case exml_query:attr(Presence, <<"type">>) =:= <<"unavailable">> andalso get_affiliation(From, StateData) =:= owner of true -> %% Will let the owner leave and destroy the room if it's not persistant @@ -489,11 +488,9 @@ locked_state(Call, StateData) -> -spec normal_state({route, From :: jid:jid(), To :: mod_muc:nick(), Acc :: mongoose_acc:t(), Packet :: exml:element()}, state()) -> fsm_return(). -normal_state({route, From, <<>>, _Acc, - #xmlel{name = <<"message">>, attrs = Attrs} = Packet}, - StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - Type = xml:get_attr_s(<<"type">>, Attrs), +normal_state({route, From, <<>>, _Acc, #xmlel{name = <<"message">>} = Packet}, StateData) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), + Type = exml_query:attr(Packet, <<"type">>, <<>>), NewStateData = route_message(#routed_message{ allowed = can_send_to_conference(From, StateData), @@ -502,9 +499,7 @@ normal_state({route, From, <<>>, _Acc, packet = Packet, lang = Lang}, StateData), next_normal_state(NewStateData); -normal_state({route, From, <<>>, Acc0, - #xmlel{name = <<"iq">>} = Packet}, - StateData) -> +normal_state({route, From, <<>>, Acc0, #xmlel{name = <<"iq">>} = Packet}, StateData) -> {IQ, Acc} = mongoose_iq:info(Acc0), {RoutingEffect, NewStateData} = route_iq(Acc, #routed_iq{ iq = IQ, @@ -514,9 +509,7 @@ normal_state({route, From, <<>>, Acc0, ok -> next_normal_state(NewStateData); stop -> {stop, normal, NewStateData} end; -normal_state({route, From, Nick, _Acc, - #xmlel{name = <<"presence">>} = Packet}, - StateData) -> +normal_state({route, From, Nick, _Acc, #xmlel{name = <<"presence">>} = Packet}, StateData) -> % FIXME sessions do we need to route presences to all sessions Activity = get_user_activity(From, StateData), Now = os:system_time(microsecond), @@ -540,10 +533,8 @@ normal_state({route, From, Nick, _Acc, StateData1 = store_user_activity(From, NewActivity, StateData), next_normal_state(StateData1) end; -normal_state({route, From, ToNick, _Acc, - #xmlel{name = <<"message">>, attrs = Attrs} = Packet}, - StateData) -> - Type = xml:get_attr_s(<<"type">>, Attrs), +normal_state({route, From, ToNick, _Acc, #xmlel{name = <<"message">>} = Packet}, StateData) -> + Type = exml_query:attr(Packet, <<"type">>, <<>>), FunRouteNickMessage = fun(JID, StateDataAcc) -> route_nick_message(#routed_nick_message{ allow_pm = (StateDataAcc#state.config)#config.allow_private_messages, @@ -551,7 +542,7 @@ normal_state({route, From, ToNick, _Acc, type = Type, from = From, nick = ToNick, - lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), decide = decide_fate_message(Type, Packet, From, StateDataAcc), packet = Packet, jid = JID}, StateDataAcc) @@ -561,11 +552,9 @@ normal_state({route, From, ToNick, _Acc, JIDs -> lists:foldl(FunRouteNickMessage, StateData, JIDs) end, next_normal_state(NewStateData); -normal_state({route, From, ToNick, _Acc, - #xmlel{name = <<"iq">>, attrs = Attrs} = Packet}, - StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - StanzaId = xml:get_attr_s(<<"id">>, Attrs), +normal_state({route, From, ToNick, _Acc, #xmlel{name = <<"iq">>} = Packet}, StateData) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), + StanzaId = exml_query:attr(Packet, <<"id">>, <<>>), FunRouteNickIq = fun(JID) -> route_nick_iq(#routed_nick_iq{ allow_query = (StateData#state.config)#config.allow_query_users, @@ -823,10 +812,8 @@ route(Pid, From, ToNick, Acc, Packet) -> -spec process_groupchat_message(jid:simple_jid() | jid:jid(), exml:element(), state()) -> fsm_return(). -process_groupchat_message(From, #xmlel{name = <<"message">>, - attrs = Attrs} = Packet, - StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +process_groupchat_message(From, #xmlel{name = <<"message">>} = Packet, StateData) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), case can_send_to_conference(From, StateData) of true -> process_message_from_allowed_user(From, Packet, StateData); @@ -874,9 +861,8 @@ is_room_anonymous(#state{config = #config{anonymous = IsAnon}}) -> is_user_moderator(UserJID, StateData) -> get_role(UserJID, StateData) =:= moderator. -process_message_from_allowed_user(From, #xmlel{attrs = Attrs} = Packet, - StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +process_message_from_allowed_user(From, Packet, StateData) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), {FromNick, Role} = get_participant_data(From, StateData), CanSendBroadcasts = can_send_broadcasts(Role, StateData), case CanSendBroadcasts of @@ -951,7 +937,7 @@ change_subject_error(From, FromNick, Packet, Lang, StateData) -> change_subject_if_allowed(FromNick, Role, Packet, StateData) -> case check_subject(Packet) of - false -> + undefined -> {StateData, true}; Subject -> case can_change_subject(Role, StateData) of @@ -1052,10 +1038,9 @@ next_normal_state(#state{hibernate_timeout = Timeout} = StateData) -> From :: jid:jid(), Nick :: mod_muc:nick(), Packet :: exml:element(). -process_presence1(From, Nick, #xmlel{name = <<"presence">>, attrs = Attrs} = Packet, - StateData = #state{}) -> - Type = xml:get_attr_s(<<"type">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +process_presence1(From, Nick, #xmlel{name = <<"presence">>} = Packet, StateData = #state{}) -> + Type = exml_query:attr(Packet, <<"type">>, <<>>), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), case Type of <<"unavailable">> -> process_presence_unavailable(From, Packet, StateData); @@ -1071,7 +1056,7 @@ process_presence1(From, Nick, #xmlel{name = <<"presence">>, attrs = Attrs} = Pac %% at this point we know that the presence has no type %% (user wants to enter the room) %% and that the user is not alredy online - handle_new_user(From, Nick, Packet, StateData, Attrs) + handle_new_user(From, Nick, Packet, StateData, Packet) end; _NotOnline -> StateData @@ -1107,10 +1092,7 @@ process_presence_unavailable(From, Packet, StateData) -> NewPacket = check_and_strip_visitor_status(From, Packet, StateData), NewState = add_user_presence_un(From, NewPacket, StateData), send_new_presence_un(From, NewState), - Reason = case xml:get_subtag(NewPacket, <<"status">>) of - false -> <<>>; - StatusEl -> xml:get_tag_cdata(StatusEl) - end, + Reason = exml_query:path(NewPacket, [{element, <<"status">>}, cdata], <<>>), remove_online_user(From, NewState, Reason); _ -> StateData @@ -1168,10 +1150,10 @@ check_and_strip_visitor_status(From, Packet, StateData) -> end. --spec handle_new_user(jid:jid(), mod_muc:nick(), exml:element(), state(), - [{binary(), binary()}]) -> state(). -handle_new_user(From, Nick = <<>>, _Packet, StateData, Attrs) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +-spec handle_new_user(jid:jid(), mod_muc:nick(), exml:element(), state(), exml:element()) -> + state(). +handle_new_user(From, Nick = <<>>, _Packet, StateData, Packet) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), ErrText = <<"No nickname">>, Error =jlib:make_error_reply( #xmlel{name = <<"presence">>}, @@ -1179,10 +1161,10 @@ handle_new_user(From, Nick = <<>>, _Packet, StateData, Attrs) -> %ejabberd_route(From, To, Packet), ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Error), StateData; -handle_new_user(From, Nick, Packet, StateData, Attrs) -> +handle_new_user(From, Nick, Packet, StateData, Packet) -> case exml_query:path(Packet, [{element, <<"x">>}]) of undefined -> - Response = kick_stanza_for_old_protocol(Attrs), + Response = kick_stanza_for_old_protocol(Packet), ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Response), StateData; _ -> @@ -1374,7 +1356,7 @@ get_error_condition(Packet) -> -spec get_error_condition2(exml:element()) -> {condition, binary()}. get_error_condition2(Packet) -> - #xmlel{children = EEls} = xml:get_subtag(Packet, <<"error">>), + #xmlel{children = EEls} = exml_query:subelement(Packet, <<"error">>), [Condition] = [Name || #xmlel{name = Name, attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []} <- EEls], @@ -1730,9 +1712,8 @@ filter_presence(#xmlel{name = <<"presence">>, attrs = Attrs, children = Els}) -> FEls = lists:filter( fun(#xmlcdata{}) -> false; - (#xmlel{attrs = Attrs1}) -> - XMLNS = xml:get_attr_s(<<"xmlns">>, Attrs1), - case XMLNS of + (#xmlel{} = El) -> + case exml_query:attr(El, <<"xmlns">>, <<>>) of <> -> false; _ -> true end @@ -1832,9 +1813,9 @@ is_next_session_of_occupant(From, Nick, StateData) -> end. -spec choose_new_user_strategy(jid:jid(), mod_muc:nick(), - mod_muc:affiliation(), mod_muc:role(), [jlib:xmlcdata() | exml:element()], + mod_muc:affiliation(), mod_muc:role(), exml:element(), state()) -> new_user_strategy(). -choose_new_user_strategy(From, Nick, Affiliation, Role, Els, StateData) -> +choose_new_user_strategy(From, Nick, Affiliation, Role, Packet, StateData) -> case {is_user_limit_reached(From, Affiliation, StateData), is_nick_exists(Nick, StateData), is_next_session_of_occupant(From, Nick, StateData), @@ -1852,29 +1833,28 @@ choose_new_user_strategy(From, Nick, Affiliation, Role, Els, StateData) -> {_, _, _, false, _, _} -> conflict_registered; _ -> - choose_new_user_password_strategy(From, Els, StateData) + choose_new_user_password_strategy(From, Packet, StateData) end. --spec choose_new_user_password_strategy(jid:jid(), [jlib:xmlcdata() | exml:element()], - state()) -> new_user_strategy(). -choose_new_user_password_strategy(From, Els, StateData) -> +-spec choose_new_user_password_strategy( + jid:jid(), exml:element(), state()) -> new_user_strategy(). +choose_new_user_password_strategy(From, Packet, StateData) -> ServiceAffiliation = get_service_affiliation(From, StateData), Config = StateData#state.config, case is_password_required(ServiceAffiliation, Config) of false -> allowed; - true -> case extract_password(Els) of - false -> require_password; + true -> case extract_password(Packet) of + undefined -> require_password; Password -> check_password(StateData, Password) end end. --spec add_new_user(jid:jid(), mod_muc:nick(), exml:element(), state() - ) -> state(). -add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +-spec add_new_user(jid:jid(), mod_muc:nick(), exml:element(), state()) -> state(). +add_new_user(From, Nick, Packet, StateData) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), Affiliation = get_affiliation(From, StateData), Role = get_default_role(Affiliation, StateData), - case choose_new_user_strategy(From, Nick, Affiliation, Role, Els, StateData) of + case choose_new_user_strategy(From, Nick, Affiliation, Role, Packet, StateData) of limit_reached -> % max user reached and user is not admin or owner Err = jlib:make_error_reply(Packet, mongoose_xmpp_errors:service_unavailable_wait()), @@ -1907,7 +1887,7 @@ add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, StateDa Packet, mongoose_xmpp_errors:not_authorized(Lang, ErrText)), route_error(Nick, From, Err, StateData); http_auth -> - Password = extract_password(Els), + Password = extract_password(Packet), perform_http_auth(From, Nick, Packet, Role, Password, StateData); allowed -> do_add_new_user(From, Nick, Packet, Role, StateData) @@ -1969,18 +1949,18 @@ decode_json_auth_response(Body) -> {Code, Msg}. reply_not_authorized(From, Nick, Packet, StateData, ErrText) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Packet#xmlel.attrs), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), Err = jlib:make_error_reply(Packet, mongoose_xmpp_errors:not_authorized(Lang, ErrText)), route_error(Nick, From, Err, StateData). reply_service_unavailable(From, Nick, Packet, StateData, ErrText) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Packet#xmlel.attrs), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), Err = jlib:make_error_reply(Packet, mongoose_xmpp_errors:service_unavailable(Lang, ErrText)), route_error(Nick, From, Err, StateData). -do_add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, +do_add_new_user(From, Nick, #xmlel{children = Els} = Packet, Role, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), NewState = add_user_presence( From, Packet, @@ -2018,24 +1998,12 @@ check_password(#state{http_auth_pool = none}, _Password) -> check_password(#state{http_auth_pool = _Pool}, _Password) -> http_auth. --spec extract_password([jlib:xmlcdata() | exml:element()]) -> 'false' | binary(). -extract_password([]) -> - false; -extract_password([#xmlel{attrs = Attrs} = El | Els]) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_MUC -> - case xml:get_subtag(El, <<"password">>) of - false -> - false; - SubEl -> - xml:get_tag_cdata(SubEl) - end; - _ -> - extract_password(Els) - end; -extract_password([_ | Els]) -> - extract_password(Els). - +-spec extract_password(exml:element()) -> + undefined | binary(). +extract_password(Packet) -> + exml_query:path(Packet, [{element_with_ns, <<"x">>, ?NS_MUC}, + {element, <<"password">>}, + cdata]). -spec count_stanza_shift(mod_muc:nick(), [jlib:xmlcdata() | exml:element()], state()) -> any(). @@ -2123,10 +2091,11 @@ calc_shift(MaxSize, Size, Shift, [S | TSizes]) -> false | non_neg_integer(). extract_history([], _Type) -> false; -extract_history([#xmlel{attrs = Attrs} = El | Els], Type) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of +extract_history([#xmlel{} = El | Els], Type) -> + case exml_query:attr(El, <<"xmlns">>, <<>>) of ?NS_MUC -> - parse_history_val(xml:get_path_s(El, [{elem, <<"history">>}, {attr, Type}]), Type); + Path = [{element, <<"history">>}, {attr, Type}], + parse_history_val(exml_query:path(El, Path, <<>>), Type); _ -> extract_history(Els, Type) end; @@ -2342,7 +2311,7 @@ send_new_presence_to_single(NJID, #user{jid = RealJID, nick = Nick, last_presenc false -> Status end, - Packet = xml:append_subtags( + Packet = jlib:append_subtags( Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, @@ -2385,7 +2354,7 @@ send_existing_presence({_LJID, #user{jid = FromJID, nick = FromNick, affiliation_to_binary(FromAffiliation)}, {<<"role">>, role_to_binary(FromRole)}] end, - Packet = xml:append_subtags( + Packet = jlib:append_subtags( Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], @@ -2509,7 +2478,7 @@ nick_unavailable_presence(MaybeJID, Nick, Affiliation, Role, MaybeCode) -> MaybeCode :: 'undefined' | exml:element(). nick_available_presence(LastPresence, MaybeJID, Affiliation, Role, MaybeCode) -> Item = muc_user_item(MaybeJID, undefined, Affiliation, Role), - xml:append_subtags(LastPresence, + jlib:append_subtags(LastPresence, [muc_user_x([Item] ++ [MaybeCode || MaybeCode /= undefined])]). @@ -2579,12 +2548,7 @@ lqueue_to_list(#lqueue{queue = Q1}) -> -spec add_message_to_history(mod_muc:nick(), jid:jid(), exml:element(), state()) -> state(). add_message_to_history(FromNick, FromJID, Packet, StateData) -> - HaveSubject = case xml:get_subtag(Packet, <<"subject">>) of - false -> - false; - _ -> - true - end, + HaveSubject = undefined =/= exml_query:subelement(Packet, <<"subject">>), SystemTime = os:system_time(second), TimeStamp = calendar:system_time_to_rfc3339(SystemTime, [{offset, "Z"}]), %% Chatroom history is stored as XMPP packets, so @@ -2595,7 +2559,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> true -> StateData#state.jid; false -> FromJID end, - TSPacket = xml:append_subtags(Packet, [jlib:timestamp_to_xml(TimeStamp, SenderJid, <<>>)]), + TSPacket = jlib:append_subtags(Packet, [jlib:timestamp_to_xml(TimeStamp, SenderJid, <<>>)]), SPacket = jlib:replace_from_to( jid:replace_resource(StateData#state.jid, FromNick), StateData#state.jid, @@ -2646,15 +2610,9 @@ send_subject(JID, _Lang, StateData) -> ejabberd_router:route(RoomJID, JID, Packet). --spec check_subject(exml:element()) -> 'false' | binary(). +-spec check_subject(exml:element()) -> undefined | binary(). check_subject(Packet) -> - case xml:get_subtag(Packet, <<"subject">>) of - false -> - false; - SubjEl -> - xml:get_tag_cdata(SubjEl) - end. - + exml_query:path(Packet, [{element, <<"subject">>}, cdata]). -spec can_change_subject(mod_muc:role(), state()) -> boolean(). can_change_subject(Role, StateData) -> @@ -2674,8 +2632,8 @@ process_iq_admin(From, set, Lang, SubEl, StateData) -> #xmlel{children = Items} = SubEl, process_admin_items_set(From, Items, Lang, StateData); process_iq_admin(From, get, Lang, SubEl, StateData) -> - case xml:get_subtag(SubEl, <<"item">>) of - false -> + case exml_query:subelement(SubEl, <<"item">>) of + undefined -> {error, mongoose_xmpp_errors:bad_request()}; Item -> FAffiliation = get_affiliation(From, StateData), @@ -2703,15 +2661,15 @@ process_iq_admin(From, get, Lang, SubEl, StateData) -> -spec extract_role_or_affiliation(Item :: exml:element()) -> {role, mod_muc:role()} | {affiliation, mod_muc:affiliation()} | {error, exml:element()}. extract_role_or_affiliation(Item) -> - case {xml:get_tag_attr(<<"role">>, Item), xml:get_tag_attr(<<"affiliation">>, Item)} of - {false, false} -> + case {exml_query:attr(Item, <<"role">>), exml_query:attr(Item, <<"affiliation">>)} of + {undefined, undefined} -> {error, mongoose_xmpp_errors:bad_request()}; - {false, {value, BAffiliation}} -> + {undefined, BAffiliation} -> case catch binary_to_affiliation(BAffiliation) of {'EXIT', _} -> {error, mongoose_xmpp_errors:bad_request()}; Affiliation -> {affiliation, Affiliation} end; - {{value, BRole}, _} -> + {BRole, _} -> case catch binary_to_role(BRole) of {'EXIT', _} -> {error, mongoose_xmpp_errors:bad_request()}; Role -> {role, Role} @@ -2883,9 +2841,9 @@ find_changed_items(UJID, UAffiliation, URole, [#xmlcdata{} | Items], Lang, StateData, Res) -> find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); find_changed_items(UJID, UAffiliation, URole, - [#xmlel{name = <<"item">>, attrs = Attrs} = Item | Items], + [#xmlel{name = <<"item">>} = Item | Items], Lang, StateData, Res) -> - case get_affected_jid(Attrs, Lang, StateData) of + case get_affected_jid(Item, Lang, StateData) of {value, JID} -> check_changed_item(UJID, UAffiliation, URole, JID, Item, Items, Lang, StateData, Res); Err -> @@ -2894,13 +2852,13 @@ find_changed_items(UJID, UAffiliation, URole, find_changed_items(_UJID, _UAffiliation, _URole, _Items, _Lang, _StateData, _Res) -> {error, mongoose_xmpp_errors:bad_request()}. --spec get_affected_jid(Attrs :: [{binary(), binary()}], +-spec get_affected_jid(Item :: exml:element(), Lang :: ejabberd:lang(), StateData :: state()) -> {value,jid:jid()} | {error, exml:element()}. -get_affected_jid(Attrs, Lang, StateData) -> - case {xml:get_attr(<<"jid">>, Attrs), xml:get_attr(<<"nick">>, Attrs)} of - {{value, S}, _} -> +get_affected_jid(Item, Lang, StateData) -> + case {exml_query:attr(Item, <<"jid">>), exml_query:attr(Item, <<"nick">>)} of + {S, _} when undefined =/= S -> case jid:from_binary(S) of error -> ErrText = <<(translate:translate(Lang, <<"Jabber ID ">>))/binary, @@ -2909,7 +2867,7 @@ get_affected_jid(Attrs, Lang, StateData) -> J -> {value, J} end; - {_, {value, N}} -> + {_, N} when undefined =/= N -> case find_jids_by_nick(N, StateData) of [] -> ErrText @@ -2926,11 +2884,10 @@ get_affected_jid(Attrs, Lang, StateData) -> -spec check_changed_item(jid:jid(), mod_muc:affiliation(), mod_muc:role(),jid:jid(), exml:element(), [exml:element()], ejabberd:lang(), state(), [res_row()]) -> find_changed_items_res(). -check_changed_item(UJID, UAffiliation, URole, JID, #xmlel{ attrs = Attrs } = Item, Items, - Lang, StateData, Res) -> +check_changed_item(UJID, UAffiliation, URole, JID, Item, Items, Lang, StateData, Res) -> TAffiliation = get_affiliation(JID, StateData), TRole = get_role(JID, StateData), - case which_property_changed(Attrs, Lang) of + case which_property_changed(Item, Lang) of {role, Role} -> ServiceAf = get_service_affiliation(JID, StateData), CanChangeRA = @@ -2978,13 +2935,13 @@ is_owner(UJID, StateData) -> _ -> true end. --spec which_property_changed(Attrs :: [{binary(), binary()}], Lang :: ejabberd:lang()) -> +-spec which_property_changed(Item :: exml:element(), Lang :: ejabberd:lang()) -> {affiliation, mod_muc:affiliation()} | {role, mod_muc:role()} | {error, exml:element()}. -which_property_changed(Attrs, Lang) -> - case {xml:get_attr(<<"role">>, Attrs), xml:get_attr(<<"affiliation">>, Attrs)} of - {false, false} -> +which_property_changed(Item, Lang) -> + case {exml_query:attr(Item, <<"role">>), exml_query:attr(Item, <<"affiliation">>)} of + {undefined, undefined} -> {error, mongoose_xmpp_errors:bad_request()}; - {false, {value, BAffiliation}} -> + {undefined, BAffiliation} -> case catch binary_to_affiliation(BAffiliation) of {'EXIT', _} -> ErrText1 = <<(translate:translate(Lang, <<"Invalid affiliation ">>))/binary, @@ -2993,7 +2950,7 @@ which_property_changed(Attrs, Lang) -> Affiliation -> {affiliation, Affiliation} end; - {{value, BRole}, _} -> + {BRole, _} -> case catch binary_to_role(BRole) of {'EXIT', _} -> ErrText1 = <<(translate:translate(Lang, <<"Invalid role ">>))/binary, @@ -3184,7 +3141,7 @@ process_iq_owner(From, Type, Lang, SubEl, StateData, StateName) -> {error, exml:element()} | {result, [exml:element() | jlib:xmlcdata()], state() | stop}. process_authorized_iq_owner(From, set, Lang, SubEl, StateData, StateName) -> #xmlel{children = Els} = SubEl, - case xml:remove_cdata(Els) of + case jlib:remove_cdata(Els) of [#xmlel{name = <<"destroy">>} = SubEl1] -> ?LOG_INFO(ls(#{what => muc_room_destroy, text => <<"Destroyed MUC room by the owner">>, @@ -3890,7 +3847,7 @@ get_roomdesc_tail(StateData, Lang) -> translate:translate(Lang, <<"private, ">>) end, Count = count_users(StateData), - CountBin = list_to_binary(integer_to_list(Count)), + CountBin = integer_to_binary(Count), <<" (", Desc/binary, CountBin/binary, ")">>. @@ -3988,7 +3945,7 @@ create_invite(FromJID, InviteEl, Lang, StateData) -> %% Create an invitation message and send it to the user. Reason = decode_reason(InviteEl), ContinueEl = - case xml:get_path_s(InviteEl, [{elem, <<"continue">>}]) of + case exml_query:path(InviteEl, [{element, <<"continue">>}], <<>>) of <<>> -> []; Continue1 -> [Continue1] end, @@ -4007,7 +3964,7 @@ create_invite(FromJID, InviteEl, Lang, StateData) -> -spec decode_destination_jid(exml:element()) -> jid:jid(). decode_destination_jid(InviteEl) -> - case jid:from_binary(xml:get_tag_attr_s(<<"to">>, InviteEl)) of + case jid:from_binary(exml_query:attr(InviteEl, <<"to">>, <<>>)) of error -> throw({error, mongoose_xmpp_errors:jid_malformed()}); JID -> JID end. @@ -4015,9 +3972,9 @@ decode_destination_jid(InviteEl) -> -spec find_invite_elems([jlib:xmlcdata() | exml:element()]) -> [exml:element()]. find_invite_elems(Els) -> - case xml:remove_cdata(Els) of + case jlib:remove_cdata(Els) of [#xmlel{name = <<"x">>, children = Els1} = XEl] -> - case xml:get_tag_attr_s(<<"xmlns">>, XEl) of + case exml_query:attr(XEl, <<"xmlns">>, <<>>) of ?NS_MUC_USER -> ok; _ -> @@ -4117,13 +4074,15 @@ handle_roommessage_from_nonparticipant(Packet, Lang, StateData, From) -> %% packet. This function must be catched, because it crashes when the packet %% is not a decline message. -spec check_decline_invitation(exml:element()) -> - {'true', {exml:element(), exml:element(), exml:element(), 'error' | jid:jid()}}. + {true, {exml:element(), exml:element(), exml:element(), 'error' | jid:jid()}}. check_decline_invitation(Packet) -> #xmlel{name = <<"message">>} = Packet, - XEl = xml:get_subtag(Packet, <<"x">>), - ?NS_MUC_USER = xml:get_tag_attr_s(<<"xmlns">>, XEl), - DEl = xml:get_subtag(XEl, <<"decline">>), - ToString = xml:get_tag_attr_s(<<"to">>, DEl), + + XEl = exml_query:subelement(Packet, <<"x">>), + ?NS_MUC_USER = exml_query:attr(XEl, <<"xmlns">>), + + DEl = exml_query:subelement(XEl, <<"decline">>), + ToString = exml_query:attr(DEl, <<"to">>), ToJID = jid:from_binary(ToString), {true, {Packet, XEl, DEl, ToJID}}. @@ -4138,8 +4097,8 @@ send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) -> DAttrs2 = lists:keydelete(<<"to">>, 1, DAttrs), DAttrs3 = [{<<"from">>, FromString} | DAttrs2], DEl2 = #xmlel{name = <<"decline">>, attrs = DAttrs3, children = DEls}, - XEl2 = xml:replace_subelement(XEl, DEl2), - Packet2 = xml:replace_subelement(Packet, XEl2), + XEl2 = jlib:replace_subelement(XEl, DEl2), + Packet2 = jlib:replace_subelement(Packet, XEl2), ejabberd_router:route(RoomJID, ToJID, Packet2). -spec send_error_only_occupants(binary(), exml:element(), @@ -4290,8 +4249,7 @@ route_message(#routed_message{allowed = true, type = Type, from = From, children = Els} = Packet, lang = Lang}, StateData) when (Type == <<>> orelse Type == <<"normal">>) -> - Invite = xml:get_path_s(Packet, [{elem, <<"x">>}, {elem, <<"invite">>}]), - case Invite of + case exml_query:path(Packet, [{element, <<"x">>}, {element, <<"invite">>}], <<>>) of <<>> -> AppType = check_voice_approval(From, Packet, Lang, StateData), route_voice_approval(AppType, From, Packet, Lang, StateData); @@ -4555,7 +4513,7 @@ route_nick_iq(#routed_nick_iq{packet = Packet, lang = Lang, nick = ToNick, -spec decode_reason(exml:element()) -> binary(). decode_reason(Elem) -> - xml:get_path_s(Elem, [{elem, <<"reason">>}, cdata]). + exml_query:path(Elem, [{element, <<"reason">>}, cdata], <<>>). -spec make_voice_approval_form(From :: jid:simple_jid() | jid:jid(), Nick :: binary(), Role :: binary()) -> exml:element(). @@ -4623,15 +4581,15 @@ maybe_add_x_element(Msg) -> {xmlel, Type, InfoXML, NewChildren} end. -kick_stanza_for_old_protocol(Attrs) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), +kick_stanza_for_old_protocol(Packet) -> + Lang = exml_query:attr(Packet, <<"xml:lang">>, <<>>), ErrText = <<"You are not in the room.">>, ErrText2 = translate:translate(Lang, ErrText), Response = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}]}, ItemAttrs = [{<<"affiliation">>, <<"none">>}, {<<"role">>, <<"none">>}], ItemEls = [#xmlel{name = <<"reason">>, children = [#xmlcdata{content = ErrText2}]}], Status = [status_code(110), status_code(307), status_code(333)], - xml:append_subtags( + jlib:append_subtags( Response, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC}], children = [#xmlel{name = <<"item">>, attrs = ItemAttrs, diff --git a/src/muc_light/mod_muc_light.erl b/src/muc_light/mod_muc_light.erl index 96489d520a2..8b3b635bf9c 100644 --- a/src/muc_light/mod_muc_light.erl +++ b/src/muc_light/mod_muc_light.erl @@ -383,7 +383,7 @@ make_err(From, To, El, Acc, Reason) -> Params :: map(), Extra :: gen_hook:extra(). prevent_service_unavailable(Acc, #{packet := Packet}, _Extra) -> - case xml:get_tag_attr_s(<<"type">>, Packet) of + case exml_query:attr(Packet, <<"type">>) of <<"groupchat">> -> {stop, Acc}; _Type -> {ok, Acc} end. diff --git a/src/offline/mod_offline.erl b/src/offline/mod_offline.erl index 93736a4c5c2..7a91de901cc 100644 --- a/src/offline/mod_offline.erl +++ b/src/offline/mod_offline.erl @@ -542,7 +542,7 @@ add_timestamp(undefined, _LServer, Packet) -> Packet; add_timestamp(TimeStamp, LServer, Packet) -> TimeStampXML = timestamp_xml(LServer, TimeStamp), - xml:append_subtags(Packet, [TimeStampXML]). + jlib:append_subtags(Packet, [TimeStampXML]). timestamp_xml(LServer, Time) -> FromJID = jid:make_noprep(<<>>, LServer, <<>>), diff --git a/src/privacy/mod_privacy.erl b/src/privacy/mod_privacy.erl index 5fc14af6003..1e4a4fed5c8 100644 --- a/src/privacy/mod_privacy.erl +++ b/src/privacy/mod_privacy.erl @@ -295,7 +295,7 @@ process_privacy_iq(Acc, HostType, set, ToJid, StateData) -> -spec measure_privacy_set(jlib:iq()) -> mongoose_instrument:measurements(). measure_privacy_set(#iq{sub_el = SubEl}) -> - case xml:remove_cdata(SubEl#xmlel.children) of + case jlib:remove_cdata(SubEl#xmlel.children) of [#xmlel{name = <<"active">>}] -> #{count => 1, active_count => 1}; [#xmlel{name = <<"default">>}] -> #{count => 1, default_count => 1}; _ -> #{count => 1} @@ -402,13 +402,13 @@ process_iq_get(Acc, iq := #iq{xmlns = ?NS_PRIVACY, sub_el = #xmlel{children = Els}}, priv_list := #userlist{name = Active}}, #{host_type := HostType}) -> - Res = case xml:remove_cdata(Els) of + Res = case jlib:remove_cdata(Els) of [] -> process_lists_get(Acc, HostType, LUser, LServer, Active); - [#xmlel{name = Name, attrs = Attrs}] -> + [#xmlel{name = Name} = Packet] -> case Name of <<"list">> -> - ListName = xml:get_attr(<<"name">>, Attrs), + ListName = exml_query:attr(Packet, <<"name">>), process_list_get(Acc, HostType, LUser, LServer, ListName); _ -> {error, mongoose_xmpp_errors:bad_request()} @@ -432,7 +432,9 @@ process_lists_get(Acc, HostType, LUser, LServer, Active) -> {error, mongoose_xmpp_errors:internal_server_error()} end. -process_list_get(Acc, HostType, LUser, LServer, {value, Name}) -> +process_list_get(_Acc, _HostType, _LUser, _LServer, undefined) -> + {error, mongoose_xmpp_errors:bad_request(<<"en">>, <<"name attribute is missing">>)}; +process_list_get(Acc, HostType, LUser, LServer, Name) -> case mod_privacy_backend:get_privacy_list(HostType, LUser, LServer, Name) of {ok, List} -> LItems = lists:map(fun item_to_xml/1, List), @@ -443,9 +445,7 @@ process_list_get(Acc, HostType, LUser, LServer, {value, Name}) -> ?LOG_ERROR(#{what => privacy_get_privacy_list_failed, reason => Reason, acc => Acc}), {error, mongoose_xmpp_errors:internal_server_error()} - end; -process_list_get(_Acc, _HostType, _LUser, _LServer, false) -> - {error, mongoose_xmpp_errors:bad_request(<<"en">>, <<"name attribute is missing">>)}. + end. -spec process_iq_set(Acc, Params, Extra) -> {ok, Acc} when Acc :: mongoose_acc:t(), @@ -455,13 +455,13 @@ process_iq_set(Acc, #{from := From, iq := #iq{xmlns = ?NS_PRIVACY, sub_el = SubEl}}, #{host_type := HostType}) -> #xmlel{children = Els} = SubEl, - Res = case xml:remove_cdata(Els) of - [#xmlel{name = Name, attrs = Attrs, children = SubEls}] -> - ListName = xml:get_attr(<<"name">>, Attrs), + Res = case jlib:remove_cdata(Els) of + [#xmlel{name = Name, children = SubEls} = Packet] -> + ListName = exml_query:attr(Packet, <<"name">>), case Name of <<"list">> -> process_list_set(Acc, HostType, From, ListName, - xml:remove_cdata(SubEls)); + jlib:remove_cdata(SubEls)); <<"active">> -> process_active_set(Acc, HostType, From, ListName); <<"default">> -> @@ -476,28 +476,30 @@ process_iq_set(Acc, process_iq_set(Acc, _, _) -> {ok, Acc}. -process_default_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, {value, Name}) -> - case mod_privacy_backend:set_default_list(HostType, LUser, LServer, Name) of +process_default_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, undefined) -> + case mod_privacy_backend:forget_default_list(HostType, LUser, LServer) of ok -> {result, []}; - {error, not_found} -> - {error, mongoose_xmpp_errors:item_not_found()}; {error, Reason} -> ?LOG_ERROR(#{what => privacy_process_default_set_failed, reason => Reason, acc => Acc}), {error, mongoose_xmpp_errors:internal_server_error()} end; -process_default_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, false) -> - case mod_privacy_backend:forget_default_list(HostType, LUser, LServer) of +process_default_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, Name) -> + case mod_privacy_backend:set_default_list(HostType, LUser, LServer, Name) of ok -> {result, []}; + {error, not_found} -> + {error, mongoose_xmpp_errors:item_not_found()}; {error, Reason} -> ?LOG_ERROR(#{what => privacy_process_default_set_failed, reason => Reason, acc => Acc}), {error, mongoose_xmpp_errors:internal_server_error()} end. -process_active_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, {value, Name}) -> +process_active_set(_Acc, _HostType, _UserJID, undefined) -> + {result, [], #userlist{}}; +process_active_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, Name) -> case mod_privacy_backend:get_privacy_list(HostType, LUser, LServer, Name) of {ok, List} -> NeedDb = is_list_needdb(List), @@ -508,11 +510,11 @@ process_active_set(Acc, HostType, #jid{luser = LUser, lserver = LServer}, {value ?LOG_ERROR(#{what => privacy_process_active_set_failed, reason => Reason, acc => Acc}), {error, mongoose_xmpp_errors:internal_server_error()} - end; -process_active_set(_Acc, _HostType, _UserJID, false) -> - {result, [], #userlist{}}. + end. -process_list_set(Acc, HostType, UserJID, {value, Name}, Els) -> +process_list_set(_Acc, _HostType, _UserJID, undefined, _Els) -> + {error, mongoose_xmpp_errors:bad_request()}; +process_list_set(Acc, HostType, UserJID, Name, Els) -> case parse_items(Els) of false -> {error, mongoose_xmpp_errors:bad_request()}; @@ -520,9 +522,7 @@ process_list_set(Acc, HostType, UserJID, {value, Name}, Els) -> remove_privacy_list(Acc, HostType, UserJID, Name); List -> replace_privacy_list(Acc, HostType, UserJID, Name, List) - end; -process_list_set(_Acc, _HostType, _UserJID, false, _Els) -> - {error, mongoose_xmpp_errors:bad_request()}. + end. remove_privacy_list(Acc, HostType, #jid{luser = LUser, lserver = LServer} = UserJID, Name) -> case mod_privacy_backend:remove_privacy_list(HostType, LUser, LServer, Name) of @@ -744,12 +744,11 @@ parse_items(Els) -> parse_items([], Res) -> %% Sort the items by their 'order' attribute lists:keysort(#listitem.order, Res); -parse_items([#xmlel{name = <<"item">>, attrs = Attrs, - children = SubEls} | Els], Res) -> - Type = xml:get_attr_s(<<"type">>, Attrs), - Value = xml:get_attr_s(<<"value">>, Attrs), - SAction = xml:get_attr_s(<<"action">>, Attrs), - SOrder = xml:get_attr_s(<<"order">>, Attrs), +parse_items([#xmlel{name = <<"item">>, children = SubEls} = El | Els], Res) -> + Type = exml_query:attr(El, <<"type">>, <<>>), + Value = exml_query:attr(El, <<"value">>, <<>>), + SAction = exml_query:attr(El, <<"action">>, <<>>), + SOrder = exml_query:attr(El, <<"order">>, <<>>), Action = parse_action(SAction), Order = parse_order(SOrder), I1 = set_action_and_order(Action, Order), @@ -813,7 +812,7 @@ set_type_and_value(<<"subscription">>, Value, Item) -> set_matches(_SubEls, false) -> false; set_matches(SubEls, Item) -> - parse_matches(Item, xml:remove_cdata(SubEls)). + parse_matches(Item, jlib:remove_cdata(SubEls)). parse_matches(Item, []) -> Item#listitem{match_all = true}; diff --git a/src/pubsub/mod_pubsub.erl b/src/pubsub/mod_pubsub.erl index 84cddc64b57..b7f18d05e29 100644 --- a/src/pubsub/mod_pubsub.erl +++ b/src/pubsub/mod_pubsub.erl @@ -1029,7 +1029,7 @@ do_route(Acc, ServerHost, Access, Plugins, Host, From, case jlib:iq_query_info(Packet) of #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, lang = Lang} = IQ -> #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), InfoXML = mongoose_disco:get_info(ServerHost, ?MODULE, <<>>, <<>>), Res = case iq_disco_info(ServerHost, Host, Node, From, Lang) of {result, IQRes} -> @@ -1044,7 +1044,7 @@ do_route(Acc, ServerHost, Access, Plugins, Host, From, ejabberd_router:route(To, From, Acc, Res); #iq{type = get, xmlns = ?NS_DISCO_ITEMS, sub_el = SubEl} = IQ -> #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), + Node = exml_query:attr(SubEl, <<"node">>, <<>>), Res = case iq_disco_items(Host, Node, From, jlib:rsm_decode(IQ)) of {result, IQRes} -> jlib:iq_to_xml(IQ#iq{type = result, @@ -1310,7 +1310,7 @@ iq_pubsub(Host, ServerHost, From, IQType, QueryEl, Lang) -> Plugins :: [binary(), ...]) -> {result, [exml:element()]} | {error, exml:element()}. iq_pubsub(Host, ServerHost, From, IQType, #xmlel{children = SubEls} = QueryEl, Lang, Access, Plugins) -> - case xml:remove_cdata(SubEls) of + case jlib:remove_cdata(SubEls) of [#xmlel{name = Name} = ActionEl | _] -> Node = exml_query:attr(ActionEl, <<"node">>, <<>>), ActionExtraArgs = #{server_host => ServerHost, @@ -1452,9 +1452,9 @@ iq_pubsub_set_publish(_Host, <<>>, _From, _ExtraArgs) -> {error, extended_error(mongoose_xmpp_errors:bad_request(), <<"nodeid-required">>)}; iq_pubsub_set_publish(Host, Node, From, #{server_host := ServerHost, access := Access, action_el := ActionEl, query_el := QueryEl}) -> - case xml:remove_cdata(ActionEl#xmlel.children) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = Payload}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + case jlib:remove_cdata(ActionEl#xmlel.children) of + [#xmlel{name = <<"item">>, children = Payload} = Element] -> + ItemId = exml_query:attr(Element, <<"id">>, <<>>), PublishOptions = exml_query:subelement(QueryEl, <<"publish-options">>), publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access, PublishOptions); @@ -1465,15 +1465,15 @@ iq_pubsub_set_publish(Host, Node, From, #{server_host := ServerHost, access := A end. iq_pubsub_set_retract(Host, Node, From, - #{action_el := #xmlel{attrs = RetractAttrs, children = RetractSubEls}}) -> - ForceNotify = case xml:get_attr_s(<<"notify">>, RetractAttrs) of + #{action_el := #xmlel{children = RetractSubEls} = Element}) -> + ForceNotify = case exml_query:attr(Element, <<"notify">>) of <<"1">> -> true; <<"true">> -> true; _ -> false end, - case xml:remove_cdata(RetractSubEls) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + case jlib:remove_cdata(RetractSubEls) of + [#xmlel{name = <<"item">>} = Element1] -> + ItemId = exml_query:attr(Element1, <<"id">>, <<>>), delete_item(Host, Node, From, ItemId, ForceNotify); _ -> {error, @@ -1481,24 +1481,24 @@ iq_pubsub_set_retract(Host, Node, From, end. iq_pubsub_set_subscribe(Host, Node, From, #{query_el := QueryEl, - action_el := #xmlel{attrs = SubscribeAttrs}}) -> + action_el := #xmlel{} = El}) -> ConfigXForm = case exml_query:subelement(QueryEl, <<"options">>) of undefined -> undefined; Options -> mongoose_data_forms:find_form(Options) end, - JID = xml:get_attr_s(<<"jid">>, SubscribeAttrs), + JID = exml_query:attr(El, <<"jid">>, <<>>), subscribe_node(Host, Node, From, JID, ConfigXForm). -iq_pubsub_set_unsubscribe(Host, Node, From, #{action_el := #xmlel{attrs = UnsubscribeAttrs}}) -> - JID = xml:get_attr_s(<<"jid">>, UnsubscribeAttrs), - SubId = xml:get_attr_s(<<"subid">>, UnsubscribeAttrs), +iq_pubsub_set_unsubscribe(Host, Node, From, #{action_el := #xmlel{} = El}) -> + JID = exml_query:attr(El, <<"jid">>, <<>>), + SubId = exml_query:attr(El, <<"subid">>, <<>>), unsubscribe_node(Host, Node, From, JID, SubId). iq_pubsub_get_items(Host, Node, From, #{query_el := QueryEl, - action_el := #xmlel{attrs = GetItemsAttrs, children = GetItemsSubEls}}) -> - MaxItems = xml:get_attr_s(<<"max_items">>, GetItemsAttrs), - SubId = xml:get_attr_s(<<"subid">>, GetItemsAttrs), + action_el := #xmlel{children = GetItemsSubEls}= El}) -> + MaxItems = exml_query:attr(El, <<"max_items">>, <<>>), + SubId = exml_query:attr(El, <<"subid">>, <<>>), ItemIds = extract_item_ids(GetItemsSubEls), get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(QueryEl)). @@ -1518,15 +1518,15 @@ extract_item_id(#xmlel{name = <<"item">>} = Item, Acc) -> extract_item_id(_, Acc) -> Acc. -iq_pubsub_get_options(Host, Node, Lang, #{action_el := #xmlel{attrs = GetOptionsAttrs}}) -> - SubId = xml:get_attr_s(<<"subid">>, GetOptionsAttrs), - JID = xml:get_attr_s(<<"jid">>, GetOptionsAttrs), +iq_pubsub_get_options(Host, Node, Lang, #{action_el := #xmlel{} = El}) -> + SubId = exml_query:attr(El, <<"subid">>, <<>>), + JID = exml_query:attr(El, <<"jid">>, <<>>), get_options(Host, Node, JID, SubId, Lang). -iq_pubsub_set_options(Host, Node, #{action_el := #xmlel{attrs = SetOptionsAttrs} = ActionEl}) -> +iq_pubsub_set_options(Host, Node, #{action_el := #xmlel{} = ActionEl}) -> XForm = mongoose_data_forms:find_form(ActionEl), - SubId = xml:get_attr_s(<<"subid">>, SetOptionsAttrs), - JID = xml:get_attr_s(<<"jid">>, SetOptionsAttrs), + SubId = exml_query:attr(ActionEl, <<"subid">>, <<>>), + JID = exml_query:attr(ActionEl, <<"jid">>, <<>>), set_options(Host, Node, JID, SubId, XForm). -spec iq_pubsub_owner( @@ -1540,7 +1540,7 @@ iq_pubsub_set_options(Host, Node, #{action_el := #xmlel{attrs = SetOptionsAttrs} | {error, exml:element() | [exml:element()] | {exml:element(), [exml:element()]}}. iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> #xmlel{children = SubEls} = SubEl, - Action = xml:remove_cdata(SubEls), + Action = jlib:remove_cdata(SubEls), case Action of [#xmlel{name = Name} = ActionEl] -> Node = exml_query:attr(ActionEl, <<"node">>, <<>>), @@ -2737,15 +2737,15 @@ get_affiliations_transaction(JID, #pubsub_node{type = Type, id = Nidx}) -> EntitiesEls :: #{action_el := exml:element()}) -> {result, []} | {error, exml:element() | {exml:element(), [exml:element()]}} | {error, exml:element()}. set_affiliations(Host, Node, From, #{action_el := ActionEl} ) -> - EntitiesEls = xml:remove_cdata(ActionEl#xmlel.children), + EntitiesEls = jlib:remove_cdata(ActionEl#xmlel.children), Owner = jid:to_lower(jid:to_bare(From)), Entities = lists:foldl(fun (_, error) -> error; - (#xmlel{name = <<"affiliation">>, attrs = Attrs}, Acc) -> - JID = jid:from_binary(xml:get_attr_s(<<"jid">>, Attrs)), + (#xmlel{name = <<"affiliation">>} = El, Acc) -> + JID = jid:from_binary(exml_query:attr(El, <<"jid">>, <<>>)), Affiliation = string_to_affiliation( - xml:get_attr_s(<<"affiliation">>, Attrs)), + exml_query:attr(El, <<"affiliation">>, <<>>)), case (JID == error) or (Affiliation == false) of true -> error; false -> [{jid:to_lower(JID), Affiliation} | Acc] @@ -3072,15 +3072,15 @@ get_subscriptions_for_send_last(_Host, _PType, _JIDs) -> []. set_subscriptions(Host, Node, From, #{action_el := ActionEl} ) -> - EntitiesEls = xml:remove_cdata(ActionEl#xmlel.children), + EntitiesEls = jlib:remove_cdata(ActionEl#xmlel.children), Owner = jid:to_lower(jid:to_bare(From)), Entities = lists:foldl(fun(_, error) -> error; - (#xmlel{name = <<"subscription">>, attrs = Attrs}, Acc) -> - JID = jid:from_binary(xml:get_attr_s(<<"jid">>, Attrs)), - Sub = string_to_subscription(xml:get_attr_s(<<"subscription">>, - Attrs)), - SubId = xml:get_attr_s(<<"subid">>, Attrs), + (#xmlel{name = <<"subscription">>} = El, Acc) -> + JID = jid:from_binary(exml_query:attr(El, <<"jid">>, <<>>)), + Sub = string_to_subscription( + exml_query:attr(El, <<"subscription">>, <<>>)), + SubId = exml_query:attr(El, <<"subid">>, <<>>), case (JID == error) or (Sub == false) of true -> error; false -> [{jid:to_lower(JID), Sub, SubId} | Acc] diff --git a/src/sasl/cyrsasl_digest.erl b/src/sasl/cyrsasl_digest.erl index da17c13c6cc..020dbea7ec8 100644 --- a/src/sasl/cyrsasl_digest.erl +++ b/src/sasl/cyrsasl_digest.erl @@ -97,8 +97,8 @@ mech_step(State, Msg) -> authorize_if_uri_valid(State, KeyVals, Nonce) -> - UserName = xml:get_attr_s(<<"username">>, KeyVals), - DigestURI = xml:get_attr_s(<<"digest-uri">>, KeyVals), + UserName = get_attr_s(KeyVals, <<"username">>), + DigestURI = get_attr_s(KeyVals, <<"digest-uri">>), case is_digesturi_valid(DigestURI, State#state.host) of false -> ?LOG_DEBUG(#{what => unauthorized_login, reason => invalid_digest_uri, @@ -109,7 +109,7 @@ authorize_if_uri_valid(State, KeyVals, Nonce) -> end. maybe_authorize(UserName, KeyVals, Nonce, State) -> - AuthzId = xml:get_attr_s(<<"authzid">>, KeyVals), + AuthzId = get_attr_s(KeyVals, <<"authzid">>), LServer = mongoose_credentials:lserver(State#state.creds), HostType = mongoose_credentials:host_type(State#state.creds), JID = jid:make_bare(UserName, LServer), @@ -122,7 +122,7 @@ maybe_authorize(UserName, KeyVals, Nonce, State) -> end, ExtraCreds = [{username, UserName}, {password, <<>>}, - {digest, xml:get_attr_s(<<"response">>, KeyVals)}, + {digest, get_attr_s(KeyVals, <<"response">>)}, {digest_gen, DigestGen}], Request = mongoose_credentials:extend(State#state.creds, ExtraCreds), do_authorize(UserName, KeyVals, Nonce, Passwd, Request, AuthzId, AuthModule, State) @@ -243,11 +243,11 @@ hex(<>, Res) -> AuthzId :: binary(), A2Prefix :: <<_:_*96>>) -> binary(). response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) -> - Realm = xml:get_attr_s(<<"realm">>, KeyVals), - CNonce = xml:get_attr_s(<<"cnonce">>, KeyVals), - DigestURI = xml:get_attr_s(<<"digest-uri">>, KeyVals), - NC = xml:get_attr_s(<<"nc">>, KeyVals), - QOP = xml:get_attr_s(<<"qop">>, KeyVals), + Realm = get_attr_s(KeyVals, <<"realm">>), + CNonce = get_attr_s(KeyVals, <<"cnonce">>), + DigestURI = get_attr_s(KeyVals, <<"digest-uri">>), + NC = get_attr_s(KeyVals, <<"nc">>), + QOP = get_attr_s(KeyVals, <<"qop">>), A1 = case AuthzId of <<>> -> list_to_binary( @@ -269,3 +269,12 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) -> NC, <<":">>, CNonce, <<":">>, QOP, <<":">>, hex(crypto:hash(md5, A2))], hex(crypto:hash(md5, T)). + +-spec get_attr_s([{binary(), binary()}], binary()) -> binary(). +get_attr_s(Attrs, Name) -> + case lists:keyfind(Name, 1, Attrs) of + {Name, Value} -> + Value; + false -> + <<>> + end. diff --git a/src/translate.erl b/src/translate.erl index 35cc9993cee..29a516bde63 100644 --- a/src/translate.erl +++ b/src/translate.erl @@ -87,7 +87,7 @@ load_translation_files(Dir, MsgFiles) -> -spec lang_from_file_name(file:filename()) -> string(). lang_from_file_name(Filename) -> - string:to_lower(filename:rootname(Filename)). + string:lowercase(filename:rootname(Filename)). -spec has_msg_extension(file:filename()) -> boolean(). has_msg_extension(FileName) -> @@ -150,5 +150,5 @@ short_lang(LLang) -> end. -spec to_lower(binary()) -> binary(). -to_lower(Bin) -> - list_to_binary(string:to_lower(binary_to_list(Bin))). +to_lower(Bin) when is_binary(Bin) -> + string:lowercase(Bin). diff --git a/src/vcard/mod_vcard.erl b/src/vcard/mod_vcard.erl index c5c3979afe2..3c6b9bb9b2d 100644 --- a/src/vcard/mod_vcard.erl +++ b/src/vcard/mod_vcard.erl @@ -701,26 +701,26 @@ search_result_get_jid(Fields) -> [JID || #{var := <<"jid">>, values := [JID]} <- Fields]. parse_vcard(LUser, VHost, VCARD) -> - FN = xml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), - Family = xml:get_path_s(VCARD, [{elem, <<"N">>}, - {elem, <<"FAMILY">>}, cdata]), - Given = xml:get_path_s(VCARD, [{elem, <<"N">>}, - {elem, <<"GIVEN">>}, cdata]), - Middle = xml:get_path_s(VCARD, [{elem, <<"N">>}, - {elem, <<"MIDDLE">>}, cdata]), - Nickname = xml:get_path_s(VCARD, [{elem, <<"NICKNAME">>}, cdata]), - BDay = xml:get_path_s(VCARD, [{elem, <<"BDAY">>}, cdata]), - CTRY = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, - {elem, <<"CTRY">>}, cdata]), - Locality = xml:get_path_s(VCARD, [{elem, <<"ADR">>}, - {elem, <<"LOCALITY">>}, cdata]), - EMail1 = xml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, - {elem, <<"USERID">>}, cdata]), - EMail2 = xml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, cdata]), - OrgName = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, - {elem, <<"ORGNAME">>}, cdata]), - OrgUnit = xml:get_path_s(VCARD, [{elem, <<"ORG">>}, - {elem, <<"ORGUNIT">>}, cdata]), + FN = exml_query:path(VCARD, [{element, <<"FN">>}, cdata], <<>>), + Family = exml_query:path(VCARD, [{element, <<"N">>}, + {element, <<"FAMILY">>}, cdata], <<>>), + Given = exml_query:path(VCARD, [{element, <<"N">>}, + {element, <<"GIVEN">>}, cdata], <<>>), + Middle = exml_query:path(VCARD, [{element, <<"N">>}, + {element, <<"MIDDLE">>}, cdata], <<>>), + Nickname = exml_query:path(VCARD, [{element, <<"NICKNAME">>}, cdata], <<>>), + BDay = exml_query:path(VCARD, [{element, <<"BDAY">>}, cdata], <<>>), + CTRY = exml_query:path(VCARD, [{element, <<"ADR">>}, + {element, <<"CTRY">>}, cdata], <<>>), + Locality = exml_query:path(VCARD, [{element, <<"ADR">>}, + {element, <<"LOCALITY">>}, cdata], <<>>), + EMail1 = exml_query:path(VCARD, [{element, <<"EMAIL">>}, + {element, <<"USERID">>}, cdata], <<>>), + EMail2 = exml_query:path(VCARD, [{element, <<"EMAIL">>}, cdata], <<>>), + OrgName = exml_query:path(VCARD, [{element, <<"ORG">>}, + {element, <<"ORGNAME">>}, cdata], <<>>), + OrgUnit = exml_query:path(VCARD, [{element, <<"ORG">>}, + {element, <<"ORGUNIT">>}, cdata], <<>>), EMail = case EMail1 of <<"">> -> EMail2; _ -> EMail1 diff --git a/src/vcard/mod_vcard_api.erl b/src/vcard/mod_vcard_api.erl index 53453b85f57..8da35d21d05 100644 --- a/src/vcard/mod_vcard_api.erl +++ b/src/vcard/mod_vcard_api.erl @@ -127,7 +127,7 @@ from_map_to_xml(<<"credential">>) -> <<"CRED">>; from_map_to_xml(<<"country">>) -> <<"CTRY">>; from_map_to_xml(<<"binValue">>) -> <<"BINVAL">>; from_map_to_xml(<<"extValue">>) -> <<"EXTVAL">>; -from_map_to_xml(Name) -> list_to_binary(string:to_upper(binary_to_list(Name))). +from_map_to_xml(Name) -> string:uppercase(Name). to_map_format(Vcard) -> lists:foldl(fun(#xmlel{name = Name, children = Value}, Acc) -> diff --git a/src/vcard/mod_vcard_ldap.erl b/src/vcard/mod_vcard_ldap.erl index ed31cab3a86..1cbb8ef492f 100644 --- a/src/vcard/mod_vcard_ldap.erl +++ b/src/vcard/mod_vcard_ldap.erl @@ -288,7 +288,7 @@ ldap_attribute_to_vcard(vCard, {<<"photo">>, Value}) -> [#xmlel{name = <<"TYPE">>, attrs = [], children = [{xmlcdata, <<"image/jpeg">>}]}, #xmlel{name = <<"BINVAL">>, attrs = [], - children = [{xmlcdata, jlib:encode_base64(Value)}]}]}; + children = [{xmlcdata, base64:encode(Value)}]}]}; ldap_attribute_to_vcard(vCardN, {<<"family">>, Value}) -> #xmlel{name = <<"FAMILY">>, attrs = [], @@ -392,7 +392,7 @@ make_user_item_if_exists(Username, Attrs, %%%----------------------- search_item_value(Name, Value, BinaryFields) -> case lists:member(Name, BinaryFields) of - true -> jlib:encode_base64(Value); + true -> base64:encode(Value); false -> Value end. diff --git a/src/xml.erl b/src/xml.erl deleted file mode 100644 index c1093d9d81c..00000000000 --- a/src/xml.erl +++ /dev/null @@ -1,159 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : xml.erl -%%% Author : Alexey Shchepin -%%% Purpose : XML utils -%%% Created : 20 Nov 2002 by Alexey Shchepin -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2011 ProcessOne -%%% -%%% This program is free software; you can redistribute it and/or -%%% modify it under the terms of the GNU General Public License as -%%% published by the Free Software Foundation; either version 2 of the -%%% License, or (at your option) any later version. -%%% -%%% This program is distributed in the hope that it will be useful, -%%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -%%% General Public License for more details. -%%% -%%% You should have received a copy of the GNU General Public License -%%% along with this program; if not, write to the Free Software -%%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -%%% -%%%---------------------------------------------------------------------- - --module(xml). --author('alexey@process-one.net'). - --export([remove_cdata/1, - get_cdata/1, get_tag_cdata/1, - get_attr/2, get_attr_s/2, - get_tag_attr/2, get_tag_attr_s/2, - get_subtag/2, - append_subtags/2, - get_path_s/2, - replace_tag_attr/3, - replace_subelement/2]). - --include("jlib.hrl"). - --type xmlel_or_cdata() :: jlib:xmlch(). - --spec remove_cdata_p(xmlel_or_cdata()) -> boolean(). -remove_cdata_p(#xmlel{}) -> true; -remove_cdata_p(_) -> false. - - --spec remove_cdata([xmlel_or_cdata()]) -> [xmlel_or_cdata()]. -remove_cdata(L) -> [E || E <- L, remove_cdata_p(E)]. - - --spec get_cdata([xmlel_or_cdata()]) -> binary(). -get_cdata(L) -> - list_to_binary(get_cdata(L, "")). - - --spec get_cdata([xmlel_or_cdata()], [iolist()]) -> [iolist()]. -get_cdata([#xmlcdata{content = CData} | L], S) -> - get_cdata(L, [S, CData]); -get_cdata([_ | L], S) -> - get_cdata(L, S); -get_cdata([], S) -> - S. - - --spec get_tag_cdata(exml:element()) -> binary(). -get_tag_cdata(#xmlel{children = Els}) -> - get_cdata(Els). - - --spec get_attr(binary() | string(), - [jlib:binary_pair()]) -> 'false' | {'value', binary() | string()}. -get_attr(AttrName, Attrs) -> - case lists:keysearch(AttrName, 1, Attrs) of - {value, {_, Val}} -> - {value, Val}; - _ -> - false - end. - - --spec get_attr_s(binary(), list()) -> binary(). -get_attr_s(AttrName, Attrs) -> - case lists:keysearch(AttrName, 1, Attrs) of - {value, {_, Val}} -> - Val; - _ -> - context_default(AttrName) - end. - --spec get_tag_attr(binary(), exml:element()) -> 'false' | {'value', binary()}. -get_tag_attr(AttrName, #xmlel{attrs = Attrs}) -> - get_attr(AttrName, Attrs). - - --spec get_tag_attr_s(binary(), exml:element()) -> binary(). -get_tag_attr_s(AttrName, #xmlel{attrs = Attrs}) -> - get_attr_s(AttrName, Attrs). - - --spec get_subtag(exml:element(), binary()) -> 'false' | exml:element(). -get_subtag(#xmlel{children = Els}, Name) -> - get_subtag1(Els, Name). - - --spec get_subtag1([xmlel_or_cdata()], binary()) -> 'false' | exml:element(). -get_subtag1([El | Els], Name) -> - case El of - #xmlel{name = Name} -> - El; - _ -> - get_subtag1(Els, Name) - end; -get_subtag1([], _) -> - false. - - --spec append_subtags(exml:element(), [xmlel_or_cdata()]) -> exml:element(). -append_subtags(XE = #xmlel{children = SubTags1}, SubTags2) -> - XE#xmlel{children = SubTags1 ++ SubTags2}. - - --spec get_path_s(exml:element(), [{elem, binary()} | {attr, binary()} | cdata]) -> - iodata() | exml:element(). -get_path_s(El, []) -> - El; -get_path_s(El, [{elem, Name} | Path]) -> - case get_subtag(El, Name) of - false -> - context_default(Name); - SubEl -> - get_path_s(SubEl, Path) - end; -get_path_s(El, [{attr, Name}]) -> - get_tag_attr_s(Name, El); -get_path_s(El, [cdata]) -> - get_tag_cdata(El). - - --spec replace_tag_attr(Attr :: binary(), Value :: binary(), exml:element() - ) -> exml:element(). -replace_tag_attr(Attr, Value, XE = #xmlel{attrs = Attrs}) -> - Attrs1 = lists:keydelete(Attr, 1, Attrs), - Attrs2 = [{Attr, Value} | Attrs1], - XE#xmlel{attrs = Attrs2}. - -%% @doc Given an element and a new subelement, -%% replace the instance of the subelement in element with the new subelement. --spec replace_subelement(exml:element(), exml:element()) -> exml:element(). -replace_subelement(XE = #xmlel{children = SubEls}, NewSubEl) -> - {_, NameNewSubEl, _, _} = NewSubEl, - SubEls2 = lists:keyreplace(NameNewSubEl, 2, SubEls, NewSubEl), - XE#xmlel{children = SubEls2}. - --spec context_default(binary() | string()) -> <<>> | []. -context_default(Attr) when is_list(Attr) -> - ""; -context_default(_Attr) -> - <<>>. diff --git a/test/mim_ct_rest_handler.erl b/test/mim_ct_rest_handler.erl index 8375f889545..c68a381e2c9 100644 --- a/test/mim_ct_rest_handler.erl +++ b/test/mim_ct_rest_handler.erl @@ -47,7 +47,7 @@ handle(Req, {_, _, _, _, true, _} = State) -> reply(Req, State, 404, ""); handle(Req, {<<"GET">>, <<"/auth/", _/binary>>, <<"check_password">>, {U, S, P}, _, _} = State) -> Result = mim_ct_rest:check_password(U, S, P), - reply(Req, State, 200, list_to_binary(atom_to_list(Result))); + reply(Req, State, 200, atom_to_binary(Result)); handle(Req, {<<"GET">>, <<"/auth/", _/binary>>, <<"get_password">>, {U, S, _P}, _, _} = State) -> {RetCode,Password} = get_password_or_certs(U, S), reply(Req, State, RetCode, Password); @@ -56,7 +56,7 @@ handle(Req, {<<"GET">>, <<"/auth/", _/binary>>, <<"get_certs">>, {U, S, _P}, _, reply(Req, State, RetCode, PemCerts); handle(Req, {<<"GET">>, <<"/auth/", _/binary>>, <<"user_exists">>, {U, S, _P}, _, _} = State) -> Result = mim_ct_rest:user_exists(U, S), - reply(Req, State, 200, list_to_binary(atom_to_list(Result))); + reply(Req, State, 200, atom_to_binary(Result)); handle(Req, {<<"POST">>, <<"/auth/", _/binary>>, <<"set_password">>, {U, S, P}, _, _} = State) -> ok = mim_ct_rest:set_password(U, S, P), reply(Req, State, 204, <<>>);