./ct_report/coverage/jlib.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : jlib.erl
3 %%% Author : Alexey Shchepin <alexey@process-one.net>
4 %%% Purpose : General XMPP library.
5 %%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
6 %%%
7 %%%
8 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
9 %%%
10 %%% This program is free software; you can redistribute it and/or
11 %%% modify it under the terms of the GNU General Public License as
12 %%% published by the Free Software Foundation; either version 2 of the
13 %%% License, or (at your option) any later version.
14 %%%
15 %%% This program is distributed in the hope that it will be useful,
16 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
17 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 %%% General Public License for more details.
19 %%%
20 %%% You should have received a copy of the GNU General Public License
21 %%% along with this program; if not, write to the Free Software
22 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 %%%
24 %%%----------------------------------------------------------------------
25
26 -module(jlib).
27 -author('alexey@process-one.net').
28 -xep([{xep, 59}, {version, "1.0"}]).
29 -xep([{xep, 68}, {version, "1.2"}]).
30 -xep([{xep, 86}, {version, "1.0"}]).
31 -export([make_result_iq_reply/1,
32 make_error_reply/2,
33 make_error_reply/3,
34 make_invitation/3,
35 make_config_change_message/1,
36 make_voice_approval_form/3,
37 form_field/1,
38 replace_from_to_attrs/3,
39 replace_from_to/3,
40 remove_attr/2,
41 iq_query_info/1,
42 iq_query_or_response_info/1,
43 iq_to_xml/1,
44 parse_xdata_submit/1,
45 parse_xdata_fields/1,
46 timestamp_to_xml/3,
47 decode_base64/1,
48 encode_base64/1,
49 rsm_encode/1,
50 rsm_decode/1,
51 stanza_error/3,
52 stanza_error/5,
53 stanza_errort/5,
54 stream_error/1,
55 stream_errort/3,
56 remove_delay_tags/1]).
57
58 -include_lib("exml/include/exml.hrl").
59 -include_lib("exml/include/exml_stream.hrl"). % only used to define stream types
60 -include("jlib.hrl").
61 -include("mongoose.hrl").
62 -include("mongoose_rsm.hrl").
63
64 %% Stream types defined in exml/include/exml_stream.hrl
65 -type xmlstreamstart() :: #xmlstreamstart{}.
66 -type xmlstreamend() :: #xmlstreamend{}.
67 -type xmlstreamel() :: exml:element() | xmlstreamstart() | xmlstreamend().
68
69 -type xmlcdata() :: #xmlcdata{}.
70
71 -type xmlch() :: exml:element() | xmlcdata(). % (XML ch)ild
72
73 -type binary_pair() :: {binary(), binary()}.
74
75 -type iq() :: #iq{}.
76
77 -type rsm_in() :: #rsm_in{}.
78 -type rsm_out() :: #rsm_out{}.
79
80 -export_type([xmlstreamstart/0, xmlstreamend/0, xmlstreamel/0,
81 binary_pair/0,
82 rsm_in/0, rsm_out/0,
83 xmlcdata/0,
84 xmlch/0,
85 iq/0
86 ]).
87
88 -spec make_result_iq_reply(exml:element()) -> exml:element();
89 (iq()) -> iq().
90 make_result_iq_reply(XE = #xmlel{attrs = Attrs}) ->
91 4064 NewAttrs = make_result_iq_reply_attrs(Attrs),
92 4064 XE#xmlel{attrs = NewAttrs};
93 make_result_iq_reply(IQ = #iq{}) ->
94 1 IQ#iq{ type = result }.
95
96
97 -spec make_result_iq_reply_attrs([binary_pair()]) -> [binary_pair(), ...].
98 make_result_iq_reply_attrs(Attrs) ->
99 4064 To = xml:get_attr(<<"to">>, Attrs),
100 4064 From = xml:get_attr(<<"from">>, Attrs),
101 4064 Attrs1 = lists:keydelete(<<"to">>, 1, Attrs),
102 4064 Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1),
103 4064 Attrs3 = case To of
104 {value, ToVal} ->
105
:-(
[{<<"from">>, ToVal} | Attrs2];
106 _ ->
107 4064 Attrs2
108 end,
109 4064 Attrs4 = case From of
110 {value, FromVal} ->
111
:-(
[{<<"to">>, FromVal} | Attrs3];
112 _ ->
113 4064 Attrs3
114 end,
115 4064 Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4),
116 4064 [{<<"type">>, <<"result">>} | Attrs5].
117
118
119 -spec make_error_reply(exml:element() | mongoose_acc:t(),
120 xmlcdata() | exml:element()) ->
121 exml:element() | {mongoose_acc:t(), exml:element() | {error, {already_an_error, _, _}}}.
122 make_error_reply(#xmlel{name = Name, attrs = Attrs,
123 children = SubTags}, Error) ->
124 271 NewAttrs = make_error_reply_attrs(Attrs),
125 271 #xmlel{name = Name, attrs = NewAttrs, children = SubTags ++ [Error]};
126 make_error_reply(Acc, Error) ->
127 39 make_error_reply(Acc, mongoose_acc:element(Acc), Error).
128
129 make_error_reply(Acc, Packet, Error) ->
130 177 case mongoose_acc:get(flag, error, false, Acc) of
131 true ->
132
:-(
?LOG_ERROR(#{what => error_reply_to_error, exml_packet => Packet,
133
:-(
reason => Error}),
134
:-(
{Acc, {error, {already_an_error, Packet, Error}}};
135 _ ->
136 177 {mongoose_acc:set(flag, error, true, Acc),
137 make_error_reply(Packet, Error)}
138 end.
139
140 -spec make_error_reply_attrs([binary_pair()]) -> [binary_pair(), ...].
141 make_error_reply_attrs(Attrs) ->
142 271 To = xml:get_attr(<<"to">>, Attrs),
143 271 From = xml:get_attr(<<"from">>, Attrs),
144 271 Attrs1 = lists:keydelete(<<"to">>, 1, Attrs),
145 271 Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1),
146 271 Attrs3 = case To of
147 {value, ToVal} ->
148 257 [{<<"from">>, ToVal} | Attrs2];
149 _ ->
150 14 Attrs2
151 end,
152 271 Attrs4 = case From of
153 {value, FromVal} ->
154 44 [{<<"to">>, FromVal} | Attrs3];
155 _ ->
156 227 Attrs3
157 end,
158 271 Attrs5 = lists:keydelete(<<"type">>, 1, Attrs4),
159 271 Attrs6 = [{<<"type">>, <<"error">>} | Attrs5],
160 271 Attrs6.
161
162
163 -spec make_config_change_message(binary()) -> exml:element().
164 make_config_change_message(Status) ->
165 4 #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}],
166 children = [#xmlel{name = <<"x">>,
167 attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
168 children = [#xmlel{name = <<"status">>,
169 attrs = [{<<"code">>, Status}]}]}]}.
170
171
172 -spec make_invitation(From :: jid:jid(), Password :: binary(),
173 Reason :: binary()) -> exml:element().
174 make_invitation(From, Password, Reason) ->
175 7 Children = case Reason of
176 6 <<>> -> [];
177 1 _ -> [#xmlel{name = <<"reason">>,
178 children = [#xmlcdata{content = Reason}]}]
179 end,
180 7 Elements = [#xmlel{name = <<"invite">>,
181 attrs = [{<<"from">>, jid:to_binary(From)}],
182 children = Children}],
183
184 7 Elements2 = case Password of
185 7 <<>> -> Elements;
186
:-(
_ -> [#xmlel{name = <<"password">>,
187 children = [#xmlcdata{content = Password}]} | Elements]
188 end,
189
190 7 #xmlel{name = <<"message">>,
191 children = [#xmlel{name = <<"x">>,
192 attrs = [{<<"xmlns">>, ?NS_MUC_USER}],
193 children = Elements2}]}.
194
195 -spec form_field({binary(), binary(), binary()}
196 | {binary(), binary()}
197 | {binary(), binary(), binary(), binary()}) -> exml:element().
198 form_field({Var, Type, Value, Label}) ->
199 26 Field = form_field({Var, Type, Value}),
200 26 Field#xmlel{attrs = [{<<"label">>, Label} | Field#xmlel.attrs]};
201 form_field({Var, Type, Value}) ->
202 45 Field = form_field({Var, Value}),
203 45 Field#xmlel{attrs = [{<<"type">>, Type} | Field#xmlel.attrs]};
204 form_field({Var, Value}) ->
205 47 #xmlel{name = <<"field">>,
206 attrs = [{<<"var">>, Var}],
207 children = [#xmlel{name = <<"value">>, children = [#xmlcdata{content = Value}]}]}.
208
209
210 -spec make_voice_approval_form(From :: jid:simple_jid() | jid:jid(),
211 Nick :: binary(), Role :: binary()) -> exml:element().
212 make_voice_approval_form(From, Nick, Role) ->
213 2 Fields = [{<<"FORM_TYPE">>, <<"hidden">>, ?NS_MUC_REQUEST},
214 {<<"muc#role">>, <<"text-single">>, Role, <<"Request role">>},
215 {<<"muc#jid">>, <<"jid-single">>, jid:to_binary(From), <<"User ID">>},
216 {<<"muc#roomnick">>, <<"text-single">>, Nick, <<"Room Nickname">>},
217 {<<"muc#request_allow">>, <<"boolean">>, <<"false">>, <<"Grant voice to this person?">>}
218 ],
219 2 #xmlel{name = <<"message">>,
220 children = [
221 #xmlel{name = <<"x">>,
222 attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}],
223 children = [#xmlel{name = <<"title">>,
224 children = [#xmlcdata{content = <<"Voice request">>}]},
225 #xmlel{name = <<"instructions">>,
226 children = [#xmlcdata{content = <<"To approve this request",
227 " for voice, select the &quot;Grant voice to this person?&quot; checkbox",
228 " and click OK. To skip this request, click the cancel button.">>}]} |
229 10 [form_field(El) || El <- Fields]
230 ]}
231 ]}.
232
233
234 -spec replace_from_to_attrs(From :: binary(),
235 To :: binary() | undefined,
236 [binary_pair()]) -> [binary_pair()].
237 replace_from_to_attrs(From, To, Attrs) ->
238 21661 Attrs1 = lists:keydelete(<<"to">>, 1, Attrs),
239 21661 Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1),
240 21661 Attrs3 = case To of
241 1928 undefined -> Attrs2;
242 19733 _ -> [{<<"to">>, To} | Attrs2]
243 end,
244 21661 Attrs4 = [{<<"from">>, From} | Attrs3],
245 21661 Attrs4.
246
247
248 -spec replace_from_to(From :: jid:simple_jid() | jid:jid(),
249 To :: jid:simple_jid() | jid:jid(),
250 XE :: exml:element()) -> exml:element().
251 replace_from_to(From, To, XE = #xmlel{attrs = Attrs}) ->
252 503 NewAttrs = replace_from_to_attrs(jid:to_binary(From),
253 jid:to_binary(To),
254 Attrs),
255 503 XE#xmlel{attrs = NewAttrs}.
256
257
258 -spec remove_attr(binary(), exml:element()) -> exml:element().
259 remove_attr(Attr, XE = #xmlel{attrs = Attrs}) ->
260
:-(
NewAttrs = lists:keydelete(Attr, 1, Attrs),
261
:-(
XE#xmlel{attrs = NewAttrs}.
262
263 -spec iq_query_info(exml:element()) -> 'invalid' | 'not_iq' | 'reply' | iq().
264 iq_query_info(El) ->
265 8587 iq_info_internal(El, request).
266
267
268 -spec iq_query_or_response_info(exml:element()) ->
269 'invalid' | 'not_iq' | 'reply' | iq().
270 iq_query_or_response_info(El) ->
271 9210 iq_info_internal(El, any).
272
273 -spec make_reply_from_type(binary()) -> {atom(), atom()}.
274 make_reply_from_type(<<"set">>) ->
275 13227 {set, request};
276 make_reply_from_type(<<"get">>) ->
277 1267 {get, request};
278 make_reply_from_type(<<"result">>) ->
279 3103 {result, reply};
280 make_reply_from_type(<<"error">>) ->
281 186 {error, reply};
282 make_reply_from_type(_) ->
283
:-(
{invalid, invalid}.
284
285 -spec extract_xmlns([exml:element()]) -> binary().
286 extract_xmlns([Element]) ->
287 2467 xml:get_tag_attr_s(<<"xmlns">>, Element);
288 extract_xmlns(_) ->
289 822 <<>>.
290
291 -spec iq_info_internal(exml:element(), Filter :: 'any' | 'request') ->
292 'invalid' | 'not_iq' | 'reply' | iq().
293 iq_info_internal(#xmlel{name = Name, attrs = Attrs,
294 children = Els}, Filter) when Name == <<"iq">> ->
295 %% Filter is either request or any. If it is request, any replies
296 %% are converted to the atom reply.
297 17783 ID = xml:get_attr_s(<<"id">>, Attrs),
298 17783 Type = xml:get_attr_s(<<"type">>, Attrs),
299 17783 Lang = xml:get_attr_s(<<"xml:lang">>, Attrs),
300 17783 {Type1, Class} = make_reply_from_type(Type),
301 17783 case {Type1, Class, Filter} of
302 {invalid, _, _} ->
303
:-(
invalid;
304 {_, Class, Filter} when Class == request; Filter == any ->
305 %% The iq record is a bit strange. The sub_el field is an
306 %% XML tuple for requests, but a list of XML tuples for
307 %% responses.
308 17783 FilteredEls = xml:remove_cdata(Els),
309 17783 {XMLNS, SubEl} =
310 case {Class, FilteredEls} of
311 {request, [#xmlel{attrs = Attrs2}]} ->
312 14494 {xml:get_attr_s(<<"xmlns">>, Attrs2),
313 hd(FilteredEls)};
314 {reply, _} ->
315 %% Find the namespace of the first non-error
316 %% element, if there is one.
317 3289 NonErrorEls = [El ||
318 #xmlel{name = SubName} = El
319 3289 <- FilteredEls,
320 2651 SubName /= <<"error">>],
321 3289 {extract_xmlns(NonErrorEls), FilteredEls};
322 _ ->
323
:-(
{<<>>, []}
324 end,
325 17783 case {XMLNS, Class} of
326 {<<>>, request} ->
327
:-(
invalid;
328 _ ->
329 17783 #iq{id = ID,
330 type = Type1,
331 xmlns = XMLNS,
332 lang = Lang,
333 sub_el = SubEl}
334 end;
335 {_, reply, _} ->
336
:-(
reply
337 end;
338 iq_info_internal(_, _) ->
339 14 not_iq.
340
341 -spec iq_type_to_binary(set|get|result|error) -> invalid | binary().
342 437 iq_type_to_binary(set) -> <<"set">>;
343 34 iq_type_to_binary(get) -> <<"get">>;
344 6789 iq_type_to_binary(result) -> <<"result">>;
345 166 iq_type_to_binary(error) -> <<"error">>;
346
:-(
iq_type_to_binary(_) -> invalid.
347
348 -spec iq_to_xml(iq()) -> exml:element().
349 iq_to_xml(#iq{id = ID, type = Type, sub_el = SubEl}) when ID /= "" ->
350 7426 #xmlel{name = <<"iq">>,
351 attrs = [{<<"id">>, ID}, {<<"type">>, iq_type_to_binary(Type)}],
352 children = sub_el_to_els(SubEl)};
353 iq_to_xml(#iq{type = Type, sub_el = SubEl}) ->
354
:-(
#xmlel{name = <<"iq">>,
355 attrs = [{<<"type">>, iq_type_to_binary(Type)}],
356 children = sub_el_to_els(SubEl)}.
357
358 %% @doc Convert `#iq.sub_el' back to `#xmlel.children'.
359 %% @end
360 -spec sub_el_to_els([exml:element()] | exml:element()) -> [exml:element()].
361 %% for requests.
362 24 sub_el_to_els(#xmlel{}=E) -> [E];
363 %% for replies.
364 7402 sub_el_to_els(Es) when is_list(Es) -> Es.
365
366
367 -spec parse_xdata_submit(FormEl :: exml:element()) ->
368 invalid | [{VarName :: binary(), Values :: [binary()]}].
369 parse_xdata_submit(FormEl) ->
370 189 case exml_query:attr(FormEl, <<"type">>) of
371 189 <<"submit">> -> parse_xdata_fields(FormEl#xmlel.children);
372
:-(
_ -> invalid
373 end.
374
375 -spec parse_xdata_fields(FormChildren :: [xmlcdata() | exml:element()]) ->
376 [{VarName :: binary(), Values :: [binary()]}].
377 parse_xdata_fields([]) ->
378 476 [];
379 parse_xdata_fields([#xmlel{ name = <<"field">> } = FieldEl | REls]) ->
380 1256 case exml_query:attr(FieldEl, <<"var">>) of
381 undefined ->
382 2 parse_xdata_fields(REls);
383 Var ->
384 1254 [ {Var, parse_xdata_values(FieldEl#xmlel.children)} | parse_xdata_fields(REls) ]
385 end;
386 parse_xdata_fields([_ | REls]) ->
387
:-(
parse_xdata_fields(REls).
388
389 -spec parse_xdata_values(VarChildren :: [xmlcdata() | exml:element()]) ->
390 Values :: [binary()].
391 parse_xdata_values([]) ->
392 1254 [];
393 parse_xdata_values([#xmlel{name = <<"value">> } = ValueEl | REls]) ->
394 1254 [exml_query:cdata(ValueEl) | parse_xdata_values(REls)];
395 parse_xdata_values([_ | REls]) ->
396
:-(
parse_xdata_values(REls).
397
398 -spec rsm_decode(exml:element() | iq()) -> 'none' | #rsm_in{}.
399 rsm_decode(#iq{sub_el=SubEl})->
400 62 rsm_decode(SubEl);
401 rsm_decode(#xmlel{}=SubEl) ->
402 1212 case xml:get_subtag(SubEl, <<"set">>) of
403 false ->
404 619 none;
405 #xmlel{name = <<"set">>, children = SubEls} ->
406 593 lists:foldl(fun rsm_parse_element/2, #rsm_in{}, SubEls)
407 end.
408
409
410 -spec rsm_parse_element(exml:element(), rsm_in()) -> rsm_in().
411 rsm_parse_element(#xmlel{name = <<"max">>, attrs = []}=Elem, RsmIn) ->
412 589 CountStr = xml:get_tag_cdata(Elem),
413 589 {Count, _} = string:to_integer(binary_to_list(CountStr)),
414 589 RsmIn#rsm_in{max=Count};
415 rsm_parse_element(#xmlel{name = <<"before">>,
416 attrs = []}=Elem, RsmIn) ->
417 241 UID = xml:get_tag_cdata(Elem),
418 241 RsmIn#rsm_in{direction=before, id=UID};
419 rsm_parse_element(#xmlel{name = <<"after">>, attrs = []}=Elem, RsmIn) ->
420 130 UID = xml:get_tag_cdata(Elem),
421 130 RsmIn#rsm_in{direction=aft, id=UID};
422 rsm_parse_element(#xmlel{name = <<"index">>, attrs = []}=Elem, RsmIn) ->
423 96 IndexStr = xml:get_tag_cdata(Elem),
424 96 {Index, _} = string:to_integer(binary_to_list(IndexStr)),
425 96 RsmIn#rsm_in{index=Index};
426 rsm_parse_element(_, RsmIn)->
427
:-(
RsmIn.
428
429
430 -spec rsm_encode('none' | rsm_out()) -> [exml:element()].
431 rsm_encode(none)->
432 6 [];
433 rsm_encode(RsmOut)->
434 48 [#xmlel{name = <<"set">>, attrs = [{<<"xmlns">>, ?NS_RSM}],
435 children = lists:reverse(rsm_encode_out(RsmOut))}].
436
437
438 -spec rsm_encode_out(rsm_out()) -> [exml:element()].
439 rsm_encode_out(#rsm_out{count=Count, index=Index, first=First, last=Last})->
440 48 El = rsm_encode_first(First, Index, []),
441 48 El2 = rsm_encode_last(Last, El),
442 48 rsm_encode_count(Count, El2).
443
444
445 -spec rsm_encode_first(First :: undefined | binary(),
446 Index :: 'undefined' | integer(),
447 Arr::[exml:element()]) -> [exml:element()].
448 rsm_encode_first(undefined, undefined, Arr) ->
449 12 Arr;
450 rsm_encode_first(First, undefined, Arr) ->
451 9 [#xmlel{name = <<"first">>, children = [#xmlcdata{content = First}]}|Arr];
452 rsm_encode_first(First, Index, Arr) ->
453 27 [#xmlel{name = <<"first">>, attrs = [{<<"index">>, i2b(Index)}],
454 children = [#xmlcdata{content = First}]}|Arr].
455
456
457 -spec rsm_encode_last(Last :: 'undefined', Arr :: [exml:element()]) -> [exml:element()].
458 12 rsm_encode_last(undefined, Arr) -> Arr;
459 rsm_encode_last(Last, Arr) ->
460 36 [#xmlel{name = <<"last">>, children = [#xmlcdata{content = Last}]}|Arr].
461
462
463 -spec rsm_encode_count(Count :: 'undefined' | pos_integer(),
464 Arr :: [exml:element()]) -> [exml:element()].
465
:-(
rsm_encode_count(undefined, Arr)-> Arr;
466 rsm_encode_count(Count, Arr)->
467 48 [#xmlel{name = <<"count">>, children = [#xmlcdata{content = i2b(Count)}]} | Arr].
468
469 -spec i2b(integer()) -> binary().
470 75 i2b(I) when is_integer(I) -> list_to_binary(integer_to_list(I)).
471
472 -spec timestamp_to_xml(TimestampString :: calendar:rfc3339_string(),
473 FromJID :: jid:simple_jid() | jid:jid() | undefined,
474 Desc :: iodata() | undefined) -> exml:element().
475 timestamp_to_xml(TimestampString, FromJID, Desc) ->
476 9297 Text = case Desc of
477 244 undefined -> [];
478 9053 _ -> [#xmlcdata{content = Desc}]
479 end,
480 9297 From = case FromJID of
481 244 undefined -> [];
482 9053 _ -> [{<<"from">>, jid:to_binary(FromJID)}]
483 end,
484 9297 #xmlel{name = <<"delay">>,
485 attrs = [{<<"xmlns">>, ?NS_DELAY},
486 {<<"stamp">>, list_to_binary(TimestampString)} | From],
487 children = Text}.
488
489 -spec decode_base64(binary() | string()) -> binary().
490 decode_base64(S) ->
491 4155 base64:mime_decode(S).
492
493 -spec encode_base64(binary() | string()) -> binary().
494 encode_base64(B) ->
495 66 base64:encode(B).
496
497 -spec stanza_error( Code :: binary()
498 , Type :: binary()
499 , Condition :: binary()
500 , SpecTag :: binary()
501 , SpecNs :: binary() | undefined) -> exml:element().
502 stanza_error(Code, Type, Condition, SpecTag, SpecNs) ->
503 4 Er = stanza_error(Code, Type, Condition),
504 4 Spec = #xmlel{ name = SpecTag, attrs = [{<<"xmlns">>, SpecNs}]},
505 4 NCh = [Spec | Er#xmlel.children],
506 4 Er#xmlel{children = NCh}.
507
508 %% TODO: remove `code' attribute (currently it used for backward-compatibility)
509
510 -spec stanza_error( Code :: binary()
511 , Type :: binary()
512 , Condition :: binary() | undefined) -> exml:element().
513 stanza_error(Code, Type, Condition) ->
514 220 #xmlel{ name = <<"error">>
515 , attrs = [{<<"code">>, Code}, {<<"type">>, Type}]
516 , children = [ #xmlel{ name = Condition
517 , attrs = [{<<"xmlns">>, ?NS_STANZAS}]
518 }]
519 }.
520
521 -spec stanza_errort( Code :: binary()
522 , Type :: binary()
523 , Condition :: binary()
524 , Lang :: ejabberd:lang()
525 , Text :: binary()) -> exml:element().
526 stanza_errort(Code, Type, Condition, Lang, Text) ->
527 485 Txt = translate:translate(Lang, Text),
528 485 #xmlel{ name = <<"error">>
529 , attrs = [{<<"code">>, Code}, {<<"type">>, Type}]
530 , children = [ #xmlel{ name = Condition
531 , attrs = [{<<"xmlns">>, ?NS_STANZAS}]
532 }
533 , #xmlel{ name = <<"text">>
534 , attrs = [{<<"xmlns">>, ?NS_STANZAS}]
535 , children = [#xmlcdata{ content = Txt }]
536 }]
537 }.
538
539 -spec stream_error(Condition :: binary()) -> exml:element().
540 stream_error(Condition) ->
541 16 #xmlel{ name = <<"stream:error">>
542 , children = [ #xmlel{ name = Condition
543 , attrs = [{<<"xmlns">>, ?NS_STREAMS}]
544 }
545 ]
546 }.
547
548 -spec stream_errort( Condition :: binary()
549 , Lang :: ejabberd:lang()
550 , Text :: binary()) -> exml:element().
551 stream_errort(Condition, Lang, Text) ->
552 54 Txt = translate:translate(Lang, Text),
553 54 #xmlel{ name = <<"stream:error">>
554 , children = [ #xmlel{ name = Condition
555 , attrs = [{<<"xmlns">>, ?NS_STREAMS}] }
556 , #xmlel{ name = <<"text">>
557 , attrs = [ {<<"xml:lang">>, Lang}
558 , {<<"xmlns">>, ?NS_STREAMS}]
559 , children = [ #xmlcdata{ content = Txt} ]}
560 ]
561 }.
562
563 remove_delay_tags(#xmlel{children = Els} = Packet) ->
564 10744 NEl = lists:foldl(
565 fun(#xmlel{name= <<"delay">>, attrs = Attrs} = R, El)->
566 47 case xml:get_attr_s(<<"xmlns">>, Attrs) of
567 ?NS_DELAY ->
568 40 El;
569 _ ->
570 7 El ++ [R]
571 end;
572 (#xmlel{name= <<"x">>, attrs = Attrs } = R, El) ->
573 615 case xml:get_attr_s(<<"xmlns">>, Attrs) of
574 ?NS_DELAY91 ->
575
:-(
El;
576 _ ->
577 615 El ++ [R]
578 end;
579 (R, El) ->
580 6665 El ++ [R]
581 end, [], Els),
582 10744 Packet#xmlel{children=NEl}.
Line Hits Source