Skip to content

Latest commit

 

History

History
2500 lines (2233 loc) · 75 KB

API.md

File metadata and controls

2500 lines (2233 loc) · 75 KB

Erlang/Elixir XMPP library API documentation

The document describes exported functions from the following modules:

  1. xmpp
  2. xmpp_util
  3. jid

xmpp

The following functions are exported from xmpp module:

decode/1

-spec decode(El :: xmlel() | xmpp_element()) -> xmpp_element().

Shorthand for decode(El, ?NS_CLIENT, []).

decode/3

-spec decode(El :: xmlel() | xmpp_element(),
             Namespace :: binary(),
	     [Option]) -> Pkt :: xmpp_element().

Decodes xmlel() element into xmpp_element().

The only available value of Option is ignore_els: if this option is set, lazy decoding is performed. By default, full decoding is applied, i.e. all known sub-elements get decoded. If El doesn't possess an xmlns attribute, it is assumed that it is within namespace Namespace. The function might fail with {xmpp_codec, Reason} exception. The value of Reason can be used to format the failure reason into human readable description using format_error/1 or io_format_error/1 functions.

In the examples below we assume El is obtained from the following XML:

<message>
  <composing xmlns='http://jabber.org/protocol/chatstates'/>
  <foo xmlns='unknown:namespace'/>
</message>

thus it is defined as:

#xmlel{name = <<"message">>,attrs = [],
       children = [#xmlel{name = <<"composing">>,
                          attrs = [{<<"xmlns">>,
                                    <<"http://jabber.org/protocol/chatstates">>}],
                          children = []},
                   #xmlel{name = <<"foo">>,
                          attrs = [{<<"xmlns">>,<<"unknown:namespace">>}],
                          children = []}]}

Example 1: lazy decoding

> xmpp:decode(El, <<"jabber:client">>, [ignore_els]).
#message{id = <<>>,type = normal,lang = <<>>,
         from = undefined,to = undefined,subject = [],body = [],
         thread = undefined,
         sub_els = [#xmlel{name = <<"composing">>,
                           attrs = [{<<"xmlns">>,
                                     <<"http://jabber.org/protocol/chatstates">>}],
                           children = []},
                    #xmlel{name = <<"foo">>,
                           attrs = [{<<"xmlns">>,<<"unknown:namespace">>}],
                           children = []}],
         meta = #{}}

Note that sub-elements (a list in #message.sub_els field) remain untouched: during lazy decoding only top-level element is decoded.

Example 2: full decoding

> xmpp:decode(El, <<"jabber:client">>, []).
#message{id = <<>>,type = normal,lang = <<>>,
         from = undefined,to = undefined,subject = [],body = [],
         thread = undefined,
         sub_els = [#chatstate{type = composing},
                    #xmlel{name = <<"foo">>,
                           attrs = [{<<"xmlns">>,<<"unknown:namespace">>}],
                           children = []}],
         meta = #{}}

Note that in this case all known sub-elements were decoded, and unknown sub-elements (<foo/> in our case) remain untouched.

Example 3: no namespace is provided and El doesn't possess any

> xmpp:decode(El, <<>>, []).
** exception error: {xmpp_codec,{missing_tag_xmlns,<<"message">>}}
     in function  xmpp_codec:decode/3 (src/xmpp_codec.erl, line 16)

It is safe to apply the function to xmpp_element():

Example 4: double decoding

> xmpp:decode(xmpp:decode(El, <<"jabber:client">>, [])).
#message{id = <<>>,type = normal,lang = <<>>,
         from = undefined,to = undefined,subject = [],body = [],
         thread = undefined,
         sub_els = [#chatstate{type = composing},
                    #xmlel{name = <<"foo">>,
                           attrs = [{<<"xmlns">>,<<"unknown:namespace">>}],
                           children = []}],
         meta = #{}}

encode/1

-spec encode(Pkt :: xmpp_element() | xmlel()) -> El :: xmlel().

Shorthand for encode(Pkt, <<>>).

encode/2

-spec encode(Pkt :: xmpp_element() | xmlel(),
             Namespace :: binary()) -> El :: xmlel().

Encodes xmpp_element() into xmlel(). Namespace is a top-level namespace: it is used to tell the codec whether to include xmlns attribute into resulting xmlel() element or not - if the Pkt is within the same Namespace, xmlns attribute will be omitted in the result.

Example 1: encoding without top-level namespace

> xmpp:encode(#message{}, <<>>).
#xmlel{name = <<"message">>,
       attrs = [{<<"xmlns">>,<<"jabber:client">>}],
       children = []}

Example 2: encoding within 'jabber:client' namespace

> xmpp:encode(#message{}, <<"jabber:client">>).
#xmlel{name = <<"message">>,attrs = [],children = []}

Note that xmlns attribute is omitted in this case because message() stanza is defined within 'jabber:client' namespace.

Example 3: encoding within 'urn:xmpp:time' namespace

> xmpp:encode(#message{}, <<"urn:xmpp:time">>).
#xmlel{name = <<"message">>,
       attrs = [{<<"xmlns">>,<<"jabber:client">>}],
       children = []}

Note that xmlns is included in the result because message() stanza is not defined within 'urn:xmpp:time' namespace.

Example 4: encoding with sub-elements

> xmpp:encode(#message{sub_els = [#chatstate{type = composing}]}).
#xmlel{name = <<"message">>,
       attrs = [{<<"xmlns">>,<<"jabber:client">>}],
       children = [#xmlel{name = <<"composing">>,
                          attrs = [{<<"xmlns">>,
                                    <<"http://jabber.org/protocol/chatstates">>}],
                          children = []}]}

It's acceptable to encode XMPP elements whose sub-elements are of mixed content, i.e. sub_els field contains both xmpp_element() and xmlel() elements as shown in the following example.

Example 5: encoding with mixed sub-elements

> xmpp:encode(#message{sub_els = [#chatstate{type = composing},
                                  #xmlel{name = <<"foo">>,
                                         attrs = [{<<"xmlns">>, <<"unknown:namespace">>}]}]}).
#xmlel{name = <<"message">>,
       attrs = [{<<"xmlns">>,<<"jabber:client">>}],
       children = [#xmlel{name = <<"composing">>,
                          attrs = [{<<"xmlns">>,
                                    <<"http://jabber.org/protocol/chatstates">>}],
                          children = []},
                   #xmlel{name = <<"foo">>,
                          attrs = [{<<"xmlns">>,<<"unknown:namespace">>}],
                          children = []}]}

It is safe to apply the function to xmlel() elements

Example 6: double encoding

> xmpp:encode(xmpp:encode(#message{})).
#xmlel{name = <<"message">>,
       attrs = [{<<"xmlns">>,<<"jabber:client">>}],
       children = []}

NOTE: encoding would never fail as long as the provided input is a valid xmpp_element() with valid values of its record fields. Use Dialyzer to validate this.

get_id/1

-spec get_id(stanza() | xmlel()) -> binary().

Returns a value of id field of a stanza() or a value of id attribute of an xmlel() element.

Example 1: obtaining id of message()

> xmpp:get_id(#message{id = <<"abcd">>}).
<<"abcd">>

Example 2: obtaining id of xmlel()

> xmpp:get_id(#xmlel{attrs = [{<<"id">>, <<"abcd">>}]}).
<<"abcd">>

set_id/2

-spec set_id(iq(), binary()) -> iq();
	    (message(), binary()) -> message();
	    (presence(), binary()) -> presence().

Sets id field of a stanza().

Example 1: setting id field of iq()

xmpp:set_id(#iq{}, <<"abcd">>).
> #iq{id = <<"abcd">>,type = undefined,lang = <<>>,
    from = undefined,to = undefined,sub_els = [],meta = #{}}

get_type/1

-spec get_type(iq()) -> iq_type();
	      (message()) -> message_type();
	      (presence()) -> presence_type();
	      (xmlel()) -> binary().

Returns a value of type field of a stanza() or a value of type attribute of an xmlel() element.

Example 1: obtaining type of presence()

> xmpp:get_type(#presence{}).
available

Example 2: obtaining type of xmlel()

> xmpp:get_type(#xmlel{attrs = [{<<"type">>, <<"set">>}]}).
<<"set">>

set_type/2

-spec set_type(iq(), iq_type()) -> iq();
	      (message(), message_type()) -> message();
	      (presence(), presence_type()) -> presence().

Sets type field of a stanza().

Example 1: setting type field of message()

> xmpp:set_type(#message{}, chat).
#message{id = <<>>,type = chat,lang = <<>>,from = undefined,
         to = undefined,subject = [],body = [],thread = undefined,
         sub_els = [],meta = #{}}

get_lang/1

-spec get_lang(stanza() | xmlel()) -> binary().

Returns a value of lang field of a stanza() or a value of xml:lang attribute of an xmlel() element.

Example 1: obtaining lang of iq()

> xmpp:get_lang(#iq{lang = <<"fr">>}).
<<"fr">>

Example 2: obtaining xml:lang of xmlel()

> xmpp:get_lang(#xmlel{attrs = [{<<"xml:lang">>, <<"fr">>}]}).
<<"fr">>

set_lang/2

-spec set_lang(iq(), binary()) -> iq();
	      (message(), binary()) -> message();
	      (presence(), binary()) -> presence().

Sets lang field of a stanza().

Example 1: setting lang field of presence()

> xmpp:set_lang(#presence{}, <<"fr">>).
#presence{id = <<>>,type = available,lang = <<"fr">>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

get_from/1

-spec get_from(stanza()) -> undefined | jid().

Returns a value of from field of a stanza().

Example 1: obtaining from of message()

> xmpp:get_from(#message{from = jid:decode(<<"user@server/resource">>)}).
#jid{user = <<"user">>,server = <<"server">>,
     resource = <<"resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"resource">>}

Example 2: from field is not set

> xmpp:get_from(#message{}).
undefined

set_from/2

-spec set_from(iq(), jid:jid() | undefined) -> iq();
	      (message(), jid:jid() | undefined) -> message();
	      (presence(), jid:jid() | undefined) -> presence().

Sets from field of a stanza().

Example 1: setting from field of presence()

> xmpp:set_from(#presence{}, jid:decode(<<"user@server/resource">>)).
#presence{id = <<>>,type = available,lang = <<>>,
          from = #jid{user = <<"user">>,server = <<"server">>,
                      resource = <<"resource">>,luser = <<"user">>,
                      lserver = <<"server">>,lresource = <<"resource">>},
          to = undefined,show = undefined,status = [],
          priority = undefined,sub_els = [],meta = #{}}

Example 2: removing from value from iq()

> xmpp:set_from(#iq{from = jid:decode(<<"user@server/resource">>)}, undefined).
#iq{id = <<>>,type = undefined,lang = <<>>,from = undefined,
    to = undefined,sub_els = [],meta = #{}}

get_to/1

-spec get_to(stanza()) -> undefined | jid().

Returns a value of to field of a stanza().

Example 1: obtaining to of message()

> xmpp:get_to(#message{to = jid:decode(<<"user@server/resource">>)}).
#jid{user = <<"user">>,server = <<"server">>,
     resource = <<"resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"resource">>}

Example 2: to field is not set

> xmpp:get_to(#message{}).
undefined

set_to/2

-spec set_to(iq(), jid:jid() | undefined) -> iq();
	    (message(), jid:jid() | undefined) -> message();
	    (presence(), jid:jid() | undefined) -> presence().

Sets to field of a stanza().

Example 1: setting to field of presence()

> xmpp:set_to(#presence{}, jid:decode(<<"user@server/resource">>)).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,
          to = #jid{user = <<"user">>,server = <<"server">>,
                    resource = <<"resource">>,luser = <<"user">>,
                    lserver = <<"server">>,lresource = <<"resource">>},
          show = undefined,status = [],priority = undefined,
          sub_els = [],meta = #{}}

Example 2: removing to value from iq()

> xmpp:set_to(#iq{to = jid:decode(<<"user@server/resource">>)}, undefined).
#iq{id = <<>>,type = undefined,lang = <<>>,from = undefined,
    to = undefined,sub_els = [],meta = #{}}

set_from_to/3

-spec set_from_to(iq(), undefined | jid:jid(), undefined | jid:jid()) -> iq();
		 (message(), undefined | jid:jid(), undefined | jid:jid()) -> message();
		 (presence(), undefined | jid:jid(), undefined | jid:jid()) -> presence().

Sets from and to fields of a stanza().

Example 1: setting from and to fields of message()

> xmpp:set_from_to(#message{}, jid:decode(<<"[email protected]">>), jid:decode(<<"[email protected]">>)).
#message{id = <<>>,type = normal,lang = <<>>,
         from = #jid{user = <<"user1">>,server = <<"server.com">>,
                     resource = <<>>,luser = <<"user1">>,
                     lserver = <<"server.com">>,lresource = <<>>},
         to = #jid{user = <<"user2">>,server = <<"server.com">>,
                   resource = <<>>,luser = <<"user2">>,
                   lserver = <<"server.com">>,lresource = <<>>},
         subject = [],body = [],thread = undefined,sub_els = [],
         meta = #{}}

get_els/1

-spec get_els(stanza()) -> [xmpp_element() | xmlel()];
	     (xmlel()) -> [xmlel()].

Returns a value of sub_els field of a stanza() or child elements of an xmlel() element.

Example 1: obtaining sub_els of message()

> xmpp:get_els(#message{sub_els = [#chatstate{type = composing}, #xmlel{name = <<"foo">>}]}).
[#chatstate{type = composing},
 #xmlel{name = <<"foo">>,attrs = [],children = []}]

Example 2: obtaining child elements of xmlel()

> xmpp:get_els(#xmlel{children = [#xmlel{name = <<"foo">>}, {xmlcdata, <<"bar">>}]}).
[#xmlel{name = <<"foo">>,attrs = [],children = []}]

Note that only xmlel() elements are returned and xmlcdata() is ignored.

set_els/2

-spec set_els(Stanza :: iq(), [xmpp_element() | xmlel()]) -> iq();
	     (Stanza :: message(), [xmpp_element() | xmlel()]) -> message();
	     (Stanza :: presence(), [xmpp_element() | xmlel()]) -> presence().

Sets sub_els field of Stanza. Note that the function replaces all existing sub-elements of Stanza: use append_subtags/2 if you only want to add new elements.

Example 1: setting sub_els field of iq()

> xmpp:set_els(#iq{type = get}, [#ping{}]).
#iq{id = <<>>,type = get,lang = <<>>,from = undefined,
    to = undefined,
    sub_els = [#ping{}],
    meta = #{}}

Example 2: removing sub_els from presence()

> xmpp:set_els(#presence{sub_els = [#caps{}]}, []).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

get_subtag/2

-spec get_subtag(Stanza :: stanza(), Tag :: xmpp_element()) -> xmpp_element() | false.

Returns first sub-element of Stanza matching Tag (i.e. xmpp_element() or xmlel() element with the same tag name and namespace as Tag) or false if no such element found or decoding of the matched element has failed.

Example 1: obtaining disco_info() element

> IQ.
#iq{id = <<"id">>,type = result,lang = <<>>,
    from = undefined,to = undefined,
    sub_els = [#xmlel{name = <<"query">>,
                      attrs = [{<<"node">>,<<"node">>},
                               {<<"xmlns">>,<<"http://jabber.org/protocol/disco#info">>}],
                      children = [#xmlel{name = <<"feature">>,
                                         attrs = [{<<"var">>,<<"feature">>}],
                                         children = []}]}],
    meta = #{}}
> xmpp:get_subtag(IQ, #disco_info{}).
#disco_info{node = <<"node">>,identities = [],
            features = [<<"feature">>],
            xdata = []}

Example 2: obtaining non-existing element

> xmpp:get_subtag(#presence{}, #caps{}).
false

In the example below jid attribute is malformed, so the function will return false.

Example 3: obtaining malformed element

> IQ.
#iq{id = <<>>,type = undefined,lang = <<>>,from = undefined,
    to = undefined,
    sub_els = [#xmlel{name = <<"query">>,
                      attrs = [{<<"xmlns">>,
                                <<"http://jabber.org/protocol/disco#items">>}],
                      children = [#xmlel{name = <<"item">>,
                                         attrs = [{<<"jid">>,<<"@">>},
                                                  {<<"xmlns">>,<<"http://jabber.org/protocol/disco#items">>}],
                                         children = []}]}],
    meta = #{}}
> xmpp:get_subtag(IQ, #disco_items{}).
false

It is also possible to use the function to obtain already decoded elements as show in the following example.

Example 4: obtaining already decoded element

> xmpp:get_subtag(#iq{sub_els = [#ping{}]}, #ping{}).
#ping{}

get_subtags/2

-spec get_subtags(Stanza :: stanza(), Tag :: xmpp_element()) -> [xmpp_element()].

Same as get_subtag/2, but returns all elements matching Tag, preserving their original order.

try_subtag/2

-spec try_subtag(Stanza :: stanza(), Tag :: xmpp_element()) -> xmpp_element() | false.

Works exactly like get_subtag/2, but raises {xmpp_codec, _} exception if decoding of a matching subtag fails.

Example 1

> Msg = #message{sub_els = [#xmlel{name = <<"iq">>}]}.
#message{id = <<>>,type = normal,lang = <<>>,
         from = undefined,to = undefined,subject = [],body = [],
         thread = undefined,
         sub_els = [#xmlel{name = <<"iq">>,attrs = [],children = []}],
         meta = #{}}
> xmpp:get_subtag(Msg, #iq{}).
false
> xmpp:try_subtag(Msg, #iq{}).
** exception error: {xmpp_codec,{missing_attr,<<"id">>,<<"iq">>, <<"jabber:client">>}}

try_subtags/2

-spec try_subtags(Stanza :: stanza(), Tag :: xmpp_element()) -> [xmpp_element()].

Same as try_subtag/2, but returns all elements matching Tag, preserving their original order.

set_subtag/2

-spec set_subtag(Stanza :: iq(), Tag :: xmpp_element()) -> iq();
		(Stanza :: message(), Tag :: xmpp_element()) -> message();
		(Stanza :: presence(), Tag :: xmpp_element()) -> presence().

Inserts Tag into sub-elements of Stanza. If Stanza already contains an element with the same tag name and namespace as Tag, the first occurrence of such element is replaced by Tag. Otherwise Tag is appended to the end of the list of sub-elements. Note that even malformed element will be replaced if it is matched, because decoding is not applied during matching.

Example 1: insertion without replacement

> xmpp:set_subtag(#presence{sub_els = [#delay{stamp = now()}]}, #nick{name = <<"nick">>}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#delay{stamp = {1489,605315,130667},
                            from = undefined,desc = <<>>},
                     #nick{name = <<"nick">>}],
          meta = #{}}

Example 2: insertion with replacement

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"nick">>,
                            attrs = [{<<"xmlns">>,
                                      <<"http://jabber.org/protocol/nick">>}],
                            children = [{xmlcdata,<<"old">>}]}],
          meta = #{}}
> xmpp:set_subtag(Presence, #nick{name = <<"new">>}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#nick{name = <<"new">>}],
          meta = #{}}

In the example below existing <delay/> tag is replaced even though it's malformed (<delay/> element MUST possess stamp attribute).

Example 3: replacement of malformed matching element

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"delay">>,
                            attrs = [{<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []}],
          meta = #{}}
> xmpp:set_subtag(Presence, #delay{stamp = now()}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#delay{stamp = {1489,605957,281474},
                            from = undefined,desc = <<>>}],
          meta = #{}}

remove_subtag/2

-spec remove_subtag(Stanza :: iq(), Tag :: xmpp_element()) -> iq();
		   (Stanza :: message(), Tag :: xmpp_element()) -> message();
		   (Stanza :: presence(), Tag :: xmpp_element()) -> presence().

Removes all sub-elements of Stanza matching Tag (i.e. xmpp_element() or xmlel() elements with the same tag name and namespace as Tag). Note that even malformed elements will be removed if they are matched, because decoding is not applied during matching.

Example 1: removing all matching elements

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"delay">>,
                            attrs = [{<<"stamp">>,<<"2017-03-15T20:04:50.711597Z">>},
                                     {<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []},
                     #xmlel{name = <<"delay">>,
                            attrs = [{<<"stamp">>,<<"2017-03-15T20:04:50.711613Z">>},
                                     {<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []}],
          meta = #{}}
> xmpp:remove_subtag(Presence, #delay{}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

In the example below <delay/> tag is removed even though it's malformed (<delay/> element MUST possess stamp attribute).

Example 2: removing malformed matching element

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"delay">>,
                            attrs = [{<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []}],
          meta = #{}}
> xmpp:remove_subtag(Presence, #delay{}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

has_subtag/2

-spec has_subtag(Stanza :: stanza(), Tag :: xmpp_element()) -> boolean().

Returns true if there exists a sub-element of Stanza matching Tag (i.e. an xmpp_element() or xmlel() element with the same tag name and namespace as Tag). Otherwise returns false. Note that true is returned even if matched element is malformed, because decoding is not applied during matching.

Example 1: found matching element

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"delay">>,
                            attrs = [{<<"stamp">>,<<"2017-03-15T20:31:17.911811Z">>},
                                     {<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []}],
          meta = #{}}
> xmpp:has_subtag(Presence, #delay{}).
true

Example 2: no matching elements found

> xmpp:has_subtag(#presence{}, #delay{}).
false

In the example below <delay/> element is considered as being matched even though it's malformed (<delay/> element MUST possess stamp attribute).

Example 3: found matching malformed element

> Presence.
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#xmlel{name = <<"delay">>,
                            attrs = [{<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []}],
          meta = #{}}
> xmpp:has_subtag(Presence, #delay{}).
true.

append_subtags/2

-spec append_subtags(Stanza :: iq(), Els :: [xmpp_element() | xmlel()]) -> iq();
		    (Stanza :: message(), Els :: [xmpp_element() | xmlel()]) -> message();
		    (Stanza :: presence(), Els :: [xmpp_element() | xmlel()]) -> presence().

Appends a list of elements Els to the end of a list of sub-elements of Stanza.

Example 1: appending elements

> Els.
[#xmlel{name = <<"delay">>,
        attrs = [{<<"stamp">>,<<"2017-03-15T20:39:26.339167Z">>},
                 {<<"xmlns">>,<<"urn:xmpp:delay">>}],
        children = []},
 #stanza_error{type = modify,code = 400,by = <<>>,
               reason = 'bad-request',text = undefined,sub_els = []}]
> xmpp:append_subtags(#presence{sub_els = [#caps{}]}, Els).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,
          sub_els = [#caps{node = <<>>,version = <<>>,hash = <<>>,
                           exts = []},
                     #xmlel{name = <<"delay">>,
                            attrs = [{<<"stamp">>,<<"2017-03-15T20:39:26.339167Z">>},
                                     {<<"xmlns">>,<<"urn:xmpp:delay">>}],
                            children = []},
                     #stanza_error{type = modify,code = 400,by = <<>>,
                                   reason = 'bad-request',text = undefined,sub_els = []}],
          meta = #{}}

get_meta/1

-spec get_meta(Stanza :: stanza()) -> Meta :: map().

Returns metadata associated with Stanza (that is, the value of its meta field).

Example 1: obtaining metadata

> xmpp:get_meta(#presence{meta = #{foo => bar}}).
#{foo => bar}

get_meta/2

-spec get_meta(Stanza :: stanza(), Key :: any()) -> Value :: any().

Returns value Value associated with Key if metadata of Stanza contains Key. Fails with a {badkey, Key} exception otherwise.

Example 1: obtaining a value

> xmpp:get_meta(#presence{meta = #{foo => bar}}, foo).
bar

Example 2: key not found

> xmpp:get_meta(#presence{meta = #{foo => bar}}, bar).
** exception error: {badkey,bar}
     ...

get_meta/3

-spec get_meta(Stanza :: stanza(), Key :: any(), Default :: any()) -> Value :: any().

Returns value Value associated with Key if metadata of Stanza contains Key. If no value is associated with Key, Default is returned.

Example 1: obtaining a value

> xmpp:get_meta(#presence{meta = #{foo => bar}}, foo, undefined).
bar

Example 2: key not found

> xmpp:get_meta(#presence{meta = #{foo => bar}}, bar, undefined).
undefined

set_meta/2

-spec set_meta(Stanza :: stanza(), Meta :: map()) -> stanza().

Sets metadata of Stanza.

Example 1: setting metadata

> xmpp:set_meta(#presence{}, #{foo => bar}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],
          meta = #{foo => bar}}

Example 2: removing entire metadata

> xmpp:set_meta(#presence{meta = #{foo => bar}}, #{}).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

put_meta/3

-spec put_meta(Stanza :: stanza(), Key :: any(), Value :: any()) -> stanza().

Associates Key with value Value and inserts the association into metadata of Stanza.

Example 1: sets new key in metadata

> xmpp:put_meta(#presence{}, foo, bar).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],
          meta = #{foo => bar}}

Example 2: replacing existing key in metadata

> xmpp:put_meta(#presence{meta = #{foo => bar}}, foo, baz).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],
          meta = #{foo => baz}}

update_meta/3

-spec update_meta(Stanza :: stanza(), Key :: any(), Value :: any()) -> Stanza :: stanza().

If Key exists in metadata of Stanza, the old associated value is replaced by value Value. Fails with {badkey,Key} exception if no value is associated with Key.

Example 1: updating existing key

> xmpp:update_meta(#presence{meta = #{foo => bar}}, foo, baz).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],
          meta = #{foo => baz}}

Example 2: updating non-existing key

> xmpp:update_meta(#presence{}, foo, bar).
** exception error: {badkey,foo}
     ...

del_meta/2

-spec del_meta(Stanza :: stanza(), Key :: any()) -> stanza().

Removes the Key, if it exists, and its associated value from metadata of Stanza.

Example 1: removing value by key

> xmpp:del_meta(#presence{meta = #{foo => bar}}, foo).
#presence{id = <<>>,type = available,lang = <<>>,
          from = undefined,to = undefined,show = undefined,
          status = [],priority = undefined,sub_els = [],meta = #{}}

is_stanza/1

-spec is_stanza(Term :: any()) -> boolean().

Returns true if Term is either of type stanza() or an xmlel() element representing stanza. Returns false otherwise.

Examples:

> xmpp:is_stanza(#iq{}).
true
> xmpp:is_stanza(#disco_info{}).
false.
> xmpp:is_stanza(123).
false.
> xmpp:is_stanza(#xmlel{name = <<"message">>}).
true
> xmpp:is_stanza(#xmlel{name = <<"foo">>}).
false.

is_known_tag/1

-spec is_known_tag(El :: xmlel()) -> boolean().

Shorthand for is_known_tag(El, ?NS_CLIENT).

is_known_tag/2

-spec is_known_tag(El :: xmlel(), Namespace :: binary()) -> boolean().

Returns true if El has corresponding xmpp_element(). Otherwise returns false. If El doesn't possess an xmlns attribute it's assumed that it is within namespace Namespace.

NOTE: if El is considered known doesn't mean it's valid: decoding may still fail.

Example 1: the tag is known

> xmpp:is_known_tag(#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>,<<"http://jabber.org/protocol/muc">>}]}).
true

Example 2: the tag is unknown

> xmpp:is_known_tag(#xmlel{name = <<"foo">>, attrs = [{<<"xmlns">>,<<"bar">>}]}).
false

Example 3: the element lacks namespace, so it's always unknown

> xmpp:is_known_tag(#xmlel{name = <<"x">>}).
false

Example 4: the element lacks namespace, but we assume it's within 'jabber:server' namespace

> xmpp:is_known_tag(#xmlel{name = <<"message">>}, <<"jabber:server">>).
true

get_ns/1

-spec get_ns(El :: xmpp_element() | xmlel()) -> Namespace :: binary().

Returns namespace of xmpp_element() or xmlel() element.

Example 1: obtaining namespace of xmpp_element()

> xmpp:get_ns(#disco_info{}).
<<"http://jabber.org/protocol/disco#info">>

Example 2: obtaining namespace of xmlel() element

> xmpp:get_ns(#xmlel{attrs = [{<<"xmlns">>, <<"foo:bar">>}]}).
<<"foo:bar">>

get_name/1

-spec get_name(xmpp_element() | xmlel()) -> binary().

Returns tag name of xmpp_element() or xmlel() element.

Example 1: obtaining tag name of xmpp_element()

> xmpp:get_name(#disco_info{}).
<<"query">>
> xmpp:get_name(#chatstate{type = composing}).
<<"composing">>

Example 2: obtaining tag name of xmlel() element

> xmpp:get_name(#xmlel{name = <<"some">>}).
<<"some">>

make_iq_result/1

-spec make_iq_result(IQ :: iq()) -> iq().

Creates from IQ an iq() of type result with empty sub-elements.

WARNING: only iq() of type set or get should be provided, otherwise the function will fail

Example 1: creating a result

> xmpp:make_iq_result(#iq{type = get, id = <<"1">>, sub_els = [#ping{}]}).
#iq{id = <<"1">>,type = result,lang = <<>>,from = undefined,
    to = undefined,sub_els = [],meta = #{}}

Example 2: trying to create a result of a result

> xmpp:make_iq_result(#iq{type = result, id = <<"1">>}).
** exception error: no function clause matching

make_iq_result/2

-spec make_iq_result(IQ :: iq(), El :: xmpp_element() | xmlel()) -> iq().

Creates from IQ an iq() of type result with sub-elements set to [El].

WARNING: only iq() of type set or get should be provided, otherwise the function will fail

Example 1: creating a result

> xmpp:make_iq_result(#iq{type = get, id = <<"1">>}, #disco_info{features = [<<"feature">>]}).
#iq{id = <<"1">>,type = result,lang = <<>>,from = undefined,
    to = undefined,
    sub_els = [#disco_info{node = <<>>,identities = [],
                           features = [<<"feature">>],
                           xdata = []}],
    meta = #{}}

Example 2: trying to create a result of a result

> xmpp:make_iq_result(#iq{type = result, id = <<"1">>}, #disco_items{}).
** exception error: no function clause matching

make_error/2

-spec make_error(Stanza :: stanza(), stanza_error() | xmlel()) -> stanza();
                (El :: xmlel(), stanza_error() | xmlel()) -> xmlel().

Constructs stanza() of type error from Stanza.

WARNING: Stanza should not have type error or result, otherwise the function will fail

Example 1: creating message-error

> xmpp:make_error(#message{type = chat}, xmpp:err_bad_request()).
#message{id = <<>>,type = error,lang = <<>>,
         from = undefined,to = undefined,subject = [],body = [],
         thread = undefined,
         sub_els = [#stanza_error{type = modify,code = 400,by = <<>>,
                                  reason = 'bad-request',text = undefined,sub_els = []}],
         meta = #{}}

Example 2: trying to create an error from an error

> xmpp:make_error(#presence{type = error}, xmpp:err_bad_request()).
** exception error: no function clause matching

get_error/1

-spec get_error(Stanza :: stanza()) -> undefined | stanza_error().

Returns stanza_error() sub-element from Stanza or undefined if not found of if decoding has failed.

Example 1: extracting stanza_error() element

> Err.
#xmlel{name = <<"error">>,
       attrs = [{<<"code">>,<<"400">>},{<<"type">>,<<"modify">>}],
       children = [#xmlel{name = <<"bad-request">>,
                          attrs = [{<<"xmlns">>,
                                    <<"urn:ietf:params:xml:ns:xmpp-stanzas">>}],
                          children = []}]}
> xmpp:get_error(#message{sub_els = [Err]}).
#stanza_error{type = modify,code = 400,by = <<>>,
              reason = 'bad-request',text = undefined,sub_els = []}

Example 2: no stanza_error() element found

> xmpp:get_error(#message{}).
undefined

format_error/1

-spec format_error(_) -> binary().

Creates diagnostic text from an error generated by decode/1 or decode/3.

Examples:

> try xmpp:decode(#xmlel{name = <<"foo">>})
  catch _:{xmpp_codec, Reason} -> xmpp:format_error(Reason)
  end.
<<"Unknown tag <foo/> qualified by namespace 'jabber:client'">>
> try xmpp:decode(#xmlel{name = <<"iq">>})
  catch _:{xmpp_codec, Reason} -> xmpp:format_error(Reason)
  end.
<<"Missing attribute 'id' in tag <iq/> qualified by namespace 'jabber:client'">>
> try xmpp:decode(#xmlel{name = <<"x">>}, <<>>, [])
  catch _:{xmpp_codec, Reason} -> xmpp:format_error(Reason)
  end.
<<"Missing namespace for tag <x/>">>

io_format_error/1

-spec io_format_error(_) -> {binary(), [binary()]}.

Same as format_error/1, but result is suitable for using in formatting functions from io or io_lib modules.

Example:

> {Format, Args} = try xmpp:decode(#xmlel{name = <<"iq">>})
                   catch _:{xmpp_codec, Reason} -> xmpp:io_format_error(Reason)
		   end.
{<<"Missing attribute '~s' in tag <~s/> qualified by namespace '~s'">>,
 [<<"id">>,<<"iq">>,<<"jabber:client">>]}
> io:format(Format, Args).
Missing attribute 'id' in tag <iq/> qualified by namespace 'jabber:client'

format_stanza_error/1

-spec format_stanza_error(Err :: stanza_error()) -> binary().

Same as format_stanza_error(Err, <<"en">>).

format_stanza_error/2

-spec format_stanza_error(Err :: stanza_error(), Lang :: binary()) -> binary().

Creates diagnostic text from stanza_error() element.

Example:

> Err.
#stanza_error{type = cancel,code = 501,by = <<>>,
              reason = 'feature-not-implemented',
              text = [#text{lang = <<"en">>,
                            data = <<"Unsupported query">>}],
              sub_els = []}
> xmpp:format_stanza_error(Err, <<"en">>).
<<"Unsupported query (feature-not-implemented)">>

format_stream_error/1

-spec format_stream_error(Err :: stream_error()) -> binary().

Same as format_stream_error(Err, <<"en">>).

format_stream_error/2

-spec format_stream_error(Err :: stream_error(), Lang :: binary()) -> binary().

Creates diagnostic text from stream_error() element.

Example:

> Err.
#stream_error{reason = 'policy-violation',
              text = [#text{lang = <<"en">>,
                            data = <<"Too many connections">>}]}
> xmpp:format_stream_error(Err, <<"en">>).
<<"Too many connections (policy-violation)">>

format_sasl_error/1

-spec format_sasl_error(Err :: sasl_failure()) -> binary().

Same as format_sasl_error(Err, <<"en">>).

format_sasl_error/2

-spec format_sasl_error(Err :: sasl_failure(), Lang :: binary()) -> binary().

Creates diagnostic text from sasl_failure() element.

Example:

> Err.
#sasl_failure{reason = 'not-authorized',
              text = [#text{lang = <<"en">>,
                            data = <<"Invalid username">>}]}
> xmpp:format_sasl_error(Err, <<"en">>).
<<"Invalid username (not-authorized)">>

pp/1

-spec pp(any()) -> iodata().

Pretty printer for XMPP elements.

Example:

> S = xmpp:pp(#sm_a{h = 10, xmlns = <<"urn:xmpp:sm:3">>}).
["#sm_a",123,
 [["h"," = ",49,48],
  44,
  ["xmlns"," = ",60,60,"\"urn:xmpp:sm:3\"",62,62]],
 125]
> io:format(S).
#sm_a{h = 10,xmlns = <<"urn:xmpp:sm:3">>}

set_tr_callback/1

-spec set_tr_callback({Module :: module(), Function :: atom()} | undefined) -> ok.

Installs Module:Function/2 as a callback translation function or uninstalls the callback if undefined is provided. The callback function should be defined as:

-spec Module:Function(Lang :: binary(), TextIn :: binary()) -> TextOut :: binary().

where Lang is a language tag, TextIn is a text to be translated and TextOut is a resulting translated text. By default, no translation callback is set and thus translation is not performed.

Example 1: installing the callback

> xmpp:mk_text(<<"hello">>, <<"ru">>).
[#text{lang = <<"en">>,data = <<"hello">>}]
> my_trans_mod:trans(<<"ru">>, <<"hello">>).
<<"привет">>.
> xmpp:set_tr_callback({my_trans_mod, trans}).
ok
> xmpp:mk_text(<<"hello">>, <<"ru">>).
[#text{lang = <<"ru">>,data = <<"привет">>},
 #text{lang = <<"en">>,data = <<"hello">>}]

Example 2: uninstalling any callback

> xmpp:mk_text(<<"hello">>, <<"ru">>).
[#text{lang = <<"ru">>,data = <<"привет">>},
 #text{lang = <<"en">>,data = <<"hello">>}]
> xmpp:set_tr_callback(undefined).
ok
> xmpp:mk_text(<<"hello">>, <<"ru">>).
[#text{lang = <<"en">>,data = <<"hello">>}]

get_text/1

-spec get_text(Text :: [text()]) -> binary().

Shorthand for get_text(Text, <<"en">>).

get_text/2

-spec get_text(Text :: [text()], Lang :: binary()) -> binary().

Extracts data from a list of text() elements, tagged by language Lang.

Example:

> Text.
[#text{lang = <<"en">>,data = <<"hello">>},
 #text{lang = <<"ru">>,data = <<"привет">>}]
> xmpp:get_text(Text, <<"ru">>).
<<"привет">>
> xmpp:get_text(Text, <<"en">>).
<<"hello">>
> xmpp:get_text(Text, <<"fr">>).
<<"hello">>

mk_text/1

-spec mk_text(Text :: binary() | {io:format(), list()}) -> [text()].

Shorthand for mk_text(Text, <<"en">>).

mk_text/2

-spec mk_text(binary() | {io:format(), list()}, Lang :: binary()) -> [text()].

Creates a list of a single text() element from binary() or formatted text, translated into language Lang using a callback function set in set_tr_callback/1.

Example:

> xmpp:mk_text(<<"hello">>, <<"en">>).
[#text{lang = <<"en">>, data = <<"hello">>}]
> xmpp:mk_text({"hello, ~s!", ["Bob"]}, <<"en">>).
[#text{lang = <<"en">>, data = <<"hello, Bob!">>}]

err_bad_request/0

-spec err_bad_request() -> stanza_error()

Creates 'bad-request' stanza error.

err_bad_request/2

-spec err_bad_request(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'bad-request' stanza error.

err_conflict/0

-spec err_conflict() -> stanza_error()

Creates 'conflict' stanza error.

err_conflict/2

-spec err_conflict(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'conflict' stanza error.

err_feature_not_implemented/0

-spec err_feature_not_implemented() -> stanza_error()

Creates 'feature-not-implemented' stanza error.

err_feature_not_implemented/2

-spec err_feature_not_implemented(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'feature-not-implemented' stanza error.

err_forbidden/0

-spec err_forbidden() -> stanza_error()

Creates 'forbidden' stanza error.

err_forbidden/2

-spec err_forbidden(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'forbidden' stanza error.

err_gone/1

-spec err_gone(URI :: binary()) -> stanza_error()

Creates 'gone' stanza error. URI is a Uniform or Internationalized Resource Identifier, typically an XMPP IRI.

err_gone/3

-spec err_gone(
         URI  :: binary(),
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'gone' stanza error. URI is a Uniform or Internationalized Resource Identifier, typically an XMPP IRI.

err_internal_server_error/0

-spec err_internal_server_error() -> stanza_error()

Creates 'internal-server-error' stanza error.

err_internal_server_error/2

-spec err_internal_server_error(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'internal-server-error' stanza error.

err_item_not_found/0

-spec err_item_not_found() -> stanza_error()

Creates 'item-not-found' stanza error.

err_item_not_found/2

-spec err_item_not_found(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'item-not-found' stanza error.

err_jid_malformed/0

-spec err_jid_malformed() -> stanza_error()

Creates 'jid-malformed' stanza error.

err_jid_malformed/2

-spec err_jid_malformed(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'jid-malformed' stanza error.

err_not_acceptable/0

-spec err_not_acceptable() -> stanza_error()

Creates 'not-acceptable' stanza error.

err_not_acceptable/2

-spec err_not_acceptable(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'not-acceptable' stanza error.

err_not_allowed/0

-spec err_not_allowed() -> stanza_error()

Creates 'not-allowed' stanza error.

err_not_allowed/2

-spec err_not_allowed(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'not-allowed' stanza error.

err_not_authorized/0

-spec err_not_authorized() -> stanza_error()

Creates 'not-authorized' stanza error.

err_not_authorized/2

-spec err_not_authorized(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'not-authorized' stanza error.

err_payment_required/0

-spec err_payment_required() -> stanza_error()

Creates 'payment-required' stanza error.

err_payment_required/2

-spec err_payment_required(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'payment-required' stanza error.

err_policy_violation/0

-spec err_policy_violation() -> stanza_error()

Creates 'policy-violation' stanza error.

err_policy_violation/2

-spec err_policy_violation(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'policy-violation' stanza error.

err_recipient_unavailable/0

-spec err_recipient_unavailable() -> stanza_error()

Creates 'recipient-unavailable' stanza error.

err_recipient_unavailable/2

-spec err_recipient_unavailable(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'recipient-unavailable' stanza error.

err_redirect/1

-spec err_redirect(URI :: binary()) -> stanza_error()

Creates 'redirect' stanza error. URI is a Uniform or Internationalized Resource Identifier, typically an XMPP IRI.

err_redirect/3

-spec err_redirect(
         URI  :: binary(),
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'redirect' stanza error. URI is a Uniform or Internationalized Resource Identifier, typically an XMPP IRI.

err_registration_required/0

-spec err_registration_required() -> stanza_error()

Creates 'registration-required' stanza error.

err_registration_required/2

-spec err_registration_required(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'registration-required' stanza error.

err_remote_server_not_found/0

-spec err_remote_server_not_found() -> stanza_error()

Creates 'remote-server-not-found' stanza error.

err_remote_server_not_found/2

-spec err_remote_server_not_found(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'remote-server-not-found' stanza error.

err_remote_server_timeout/0

-spec err_remote_server_timeout() -> stanza_error()

Creates 'remote-server-timeout' stanza error.

err_remote_server_timeout/2

-spec err_remote_server_timeout(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'remote-server-timeout' stanza error.

err_resource_constraint/0

-spec err_resource_constraint() -> stanza_error()

Creates 'resource-constraint' stanza error.

err_resource_constraint/2

-spec err_resource_constraint(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'resource-constraint' stanza error.

err_service_unavailable/0

-spec err_service_unavailable() -> stanza_error()

Creates 'service-unavailable' stanza error.

err_service_unavailable/2

-spec err_service_unavailable(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'service-unavailable' stanza error.

err_subscription_required/0

-spec err_subscription_required() -> stanza_error()

Creates 'subscription-required' stanza error.

err_subscription_required/2

-spec err_subscription_required(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'subscription-required' stanza error.

err_undefined_condition/1

-spec err_undefined_condition(
         Type :: 'auth' | 'cancel' | 'continue' | 'modify' | 'wait') -> stanza_error()

Creates 'undefined-condition' stanza error.

err_undefined_condition/3

-spec err_undefined_condition(
         Type :: 'auth' | 'cancel' | 'continue' | 'modify' | 'wait',
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'undefined-condition' stanza error.

err_unexpected_request/0

-spec err_unexpected_request() -> stanza_error()

Creates 'unexpected-request' stanza error.

err_unexpected_request/2

-spec err_unexpected_request(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stanza_error()

Creates 'unexpected-request' stanza error.

serr_bad_format/0

-spec serr_bad_format() -> stream_error()

Creates 'bad-format' stream error.

serr_bad_format/2

-spec serr_bad_format(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'bad-format' stream error.

serr_bad_namespace_prefix/0

-spec serr_bad_namespace_prefix() -> stream_error()

Creates 'bad-namespace-prefix' stream error.

serr_bad_namespace_prefix/2

-spec serr_bad_namespace_prefix(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'bad-namespace-prefix' stream error.

serr_conflict/0

-spec serr_conflict() -> stream_error()

Creates 'conflict' stream error.

serr_conflict/2

-spec serr_conflict(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'conflict' stream error.

serr_connection_timeout/0

-spec serr_connection_timeout() -> stream_error()

Creates 'connection-timeout' stream error.

serr_connection_timeout/2

-spec serr_connection_timeout(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'connection-timeout' stream error.

serr_host_gone/0

-spec serr_host_gone() -> stream_error()

Creates 'host-gone' stream error.

serr_host_gone/2

-spec serr_host_gone(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'host-gone' stream error.

serr_host_unknown/0

-spec serr_host_unknown() -> stream_error()

Creates 'host-unknown' stream error.

serr_host_unknown/2

-spec serr_host_unknown(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'host-unknown' stream error.

serr_improper_addressing/0

-spec serr_improper_addressing() -> stream_error()

Creates 'improper-addressing' stream error.

serr_improper_addressing/2

-spec serr_improper_addressing(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'improper-addressing' stream error.

serr_internal_server_error/0

-spec serr_internal_server_error() -> stream_error()

Creates 'internal-server-error' stream error.

serr_internal_server_error/2

-spec serr_internal_server_error(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'internal-server-error' stream error.

serr_invalid_from/0

-spec serr_invalid_from() -> stream_error()

Creates 'invalid-from' stream error.

serr_invalid_from/2

-spec serr_invalid_from(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'invalid-from' stream error.

serr_invalid_id/0

-spec serr_invalid_id() -> stream_error()

Creates 'invalid-id' stream error.

serr_invalid_id/2

-spec serr_invalid_id(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'invalid-id' stream error.

serr_invalid_namespace/0

-spec serr_invalid_namespace() -> stream_error()

Creates 'invalid-namespace' stream error.

serr_invalid_namespace/2

-spec serr_invalid_namespace(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'invalid-namespace' stream error.

serr_invalid_xml/0

-spec serr_invalid_xml() -> stream_error()

Creates 'invalid-xml' stream error.

serr_invalid_xml/2

-spec serr_invalid_xml(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'invalid-xml' stream error.

serr_not_authorized/0

-spec serr_not_authorized() -> stream_error()

Creates 'not-authorized' stream error.

serr_not_authorized/2

-spec serr_not_authorized(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'not-authorized' stream error.

serr_not_well_formed/0

-spec serr_not_well_formed() -> stream_error()

Creates 'not-well-formed' stream error.

serr_not_well_formed/2

-spec serr_not_well_formed(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'not-well-formed' stream error.

serr_policy_violation/0

-spec serr_policy_violation() -> stream_error()

Creates 'policy-violation' stream error.

serr_policy_violation/2

-spec serr_policy_violation(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'policy-violation' stream error.

serr_remote_connection_failed/0

-spec serr_remote_connection_failed() -> stream_error()

Creates 'remote-connection-failed' stream error.

serr_remote_connection_failed/2

-spec serr_remote_connection_failed(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'remote-connection-failed' stream error.

serr_reset/0

-spec serr_reset() -> stream_error()

Creates 'reset' stream error.

serr_reset/2

-spec serr_reset(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'reset' stream error.

serr_resource_constraint/0

-spec serr_resource_constraint() -> stream_error()

Creates 'resource-constraint' stream error.

serr_resource_constraint/2

-spec serr_resource_constraint(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'resource-constraint' stream error.

serr_restricted_xml/0

-spec serr_restricted_xml() -> stream_error()

Creates 'restricted-xml' stream error.

serr_restricted_xml/2

-spec serr_restricted_xml(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'restricted-xml' stream error.

serr_see_other_host/1

-spec serr_see_other_host(HostPort :: xmpp_host()) -> stream_error()

where xmpp_host() is defined as

-type xmpp_host() :: binary() | inet:ip_address() |
		     {binary() | inet:ip_address(), inet:port_number()}.

Creates 'see-other-host' stream error. HostPort is a hostname or IP address (with or without a port).

serr_see_other_host/3

-spec serr_see_other_host(
         HostPort :: xmpp_host(),
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

where xmpp_host() is defined as

-type xmpp_host() :: binary() | inet:ip_address() |
		     {binary() | inet:ip_address(), inet:port_number()}.

Creates 'see-other-host' stream error. HostPort is a hostname or IP address (with or without a port).

serr_system_shutdown/0

-spec serr_system_shutdown() -> stream_error()

Creates 'system-shutdown' stream error.

serr_system_shutdown/2

-spec serr_system_shutdown(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'system-shutdown' stream error.

serr_undefined_condition/0

-spec serr_undefined_condition() -> stream_error()

Creates 'undefined-condition' stream error.

serr_undefined_condition/2

-spec serr_undefined_condition(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'undefined-condition' stream error.

serr_unsupported_encoding/0

-spec serr_unsupported_encoding() -> stream_error()

Creates 'unsupported-encoding' stream error.

serr_unsupported_encoding/2

-spec serr_unsupported_encoding(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'unsupported-encoding' stream error.

serr_unsupported_feature/0

-spec serr_unsupported_feature() -> stream_error()

Creates 'unsupported-feature' stream error.

serr_unsupported_feature/2

-spec serr_unsupported_feature(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'unsupported-feature' stream error.

serr_unsupported_stanza_type/0

-spec serr_unsupported_stanza_type() -> stream_error()

Creates 'unsupported-stanza-type' stream error.

serr_unsupported_stanza_type/2

-spec serr_unsupported_stanza_type(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'unsupported-stanza-type' stream error.

serr_unsupported_version/0

-spec serr_unsupported_version() -> stream_error()

Creates 'unsupported-version' stream error.

serr_unsupported_version/2

-spec serr_unsupported_version(
         Desc :: binary() | {io:format(), list()},
         Lang :: binary()) -> stream_error()

Creates 'unsupported-version' stream error.

xmpp_util

The following functions are exported from xmpp_util module:

decode_timestamp/1

-spec decode_timestamp(Data :: binary()) -> erlang:timestamp().

Decodes timestamp from XEP-0082 format (both DateTime and legacy) into erlang:timestamp() format. Fails with {bad_timestamp, Data} exception if Data doesn't represent a valid timestamp.

Example 1: decoding from DateTime format

> xmpp_util:decode_timestamp(<<"2006-12-19T17:58:35Z">>).
{1166,551115,0}

Example 2: decoding from legacy format

> xmpp_util:decode_timestamp(<<"20020910T17:58:35">>).
{1031,680715,0}

Example 3: decoding failure - not even remotely a timestamp

> xmpp_util:decode_timestamp(<<"sd324klsjdpsdf">>).
** exception error: {bad_timestamp,<<"sd324klsjdpsdf">>}
     ...

Example 4: decoding failure - month is invalid

> xmpp_util:decode_timestamp(<<"2006-13-19T17:58:35Z">>).
** exception error: {bad_timestamp,<<"2006-13-19T17:58:35Z">>}
     ...

encode_timestamp/1

-spec encode_timestamp(Timestamp :: erlang:timestamp()) -> binary().

Encodes Timestamp into DateTime format of XEP-0082.

Example:

> xmpp_util:encode_timestamp({1166,551115,34}).
<<"2006-12-19T17:58:35.000034Z">>

get_xdata_values/2

-spec get_xdata_values(Var :: binary(), Form :: xdata()) -> Values :: [binary()].

Returns Values associated with Var field of a data form Form.

Example: obtaining values

> Form.
#xdata{type = submit,instructions = [],title = undefined,
       reported = undefined,items = [],
       fields = [#xdata_field{label = <<>>,type = 'text-single',
                              var = <<"search_request">>,required = false,desc = <<>>,
                              values = [<<"verona">>],
                              options = [],sub_els = []}]}
> xmpp_util:get_xdata_values(<<"search_request">>, Form).
[<<"verona">>]
> xmpp_util:get_xdata_values(<<"non_existent">>, Form).
[]

set_xdata_field/2

-spec set_xdata_field(Field :: xdata_field(), Form :: xdata()) -> xdata().

Sets Field in a data form Form. If there is already field matching Field exists (i.e. has the same value of #xdata_field.var), then it's replaced. Otherwise Field is appended to the end of Form#xdata.fields list.

Example 1: setting new field

> xmpp_util:set_xdata_field(#xdata_field{var = <<"var">>, values = [<<"val">>]}, #xdata{}).
#xdata{type = undefined,instructions = [],title = undefined,
       reported = undefined,items = [],
       fields = [#xdata_field{label = <<>>,type = undefined,
                              var = <<"var">>,required = false,desc = <<>>,
                              values = [<<"val">>],
                              options = [],sub_els = []}]}

Example 2: replacing existing field

> xmpp_util:set_xdata_field(#xdata_field{var = <<"var">>,
                                         values = [<<"new">>]},
                            #xdata{fields = [#xdata_field{var = <<"var">>,
			                                  values = [<<"old">>]}]}).
#xdata{type = undefined,instructions = [],title = undefined,
       reported = undefined,items = [],
       fields = [#xdata_field{label = <<>>,type = undefined,
                              var = <<"var">>,required = false,desc = <<>>,
                              values = [<<"new">>],
                              options = [],sub_els = []}]}

has_xdata_var/2

-spec has_xdata_var(Var :: binary(), Form :: xdata()) -> boolean().

Returns true if there is xdata_field() exists in the Form with value of #xdata_field.var field matching Var. Returns false otherwise.

Example 1: the field exists

> xmpp_util:has_xdata_var(<<"var">>,
                          #xdata{fields = [#xdata_field{var = <<"var">>,
			                                values = [<<"old">>]}]}).
true

Example 2: the field doesn't exist

> xmpp_util:has_xdata_var(<<"var">>, #xdata{}).
false

jid

The following functions are exported from jid module:

decode/1

-spec decode(Data :: binary()) -> jid().

Decodes Data into JID. Fails with {bad_jid, Data} on failure.

Example 1: successful decoding

> jid:decode(<<"User@Server/Resource">>).
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}

Example 2: decoding failure

> jid:decode(<<"@server">>).
** exception error: {bad_jid,<<"@server">>}
     ...

encode/1

-spec encode(jid() | ljid()) -> binary().

Encodes JID.

Example 1: encoding jid()

> JID.
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}
> jid:encode(J).
<<"User@Server/Resource">>

Example 2: encoding ljid()

> jid:encode({<<"user">>, <<"server">>, <<"resource">>}).
<<"user@server/resource">>

make/1

-spec make(ljid() | binary()) -> jid() | error.

Creates jid() from ljid() or from namepart. Returns error if stringprep has failed.

Example 1: creating jid() from ljid()

> jid:make({<<"User">>, <<"Server">>, <<"Resource">>}).
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}

Example 2: creating jid() from namepart

> jid:make(<<"Server">>).
#jid{user = <<>>,server = <<"Server">>,resource = <<>>,
     luser = <<>>,lserver = <<"server">>,lresource = <<>>}

Example 3: stringprep failure

> jid:make({<<"@">>, <<"server">>, <<"resource">>}).
error

make/2

-spec make(User :: binary(), Server :: binary()) -> jid() | error.

Shorthand for make({User, Server, <<>>}).

make/3

-spec make(User :: binary(), Server :: binary(), Resource :: binary()) -> jid() | error.

Same as make({User, Server, Resource}).

nodeprep/1

-spec nodeprep(binary()) -> binary() | error.

Applies Nodeprep Profile of Stringprep. Returns error on failure.

Example:

> jid:nodeprep(<<"User">>).
<<"user">>
> jid:nodeprep(<<"@">>).
error

nameprep/1

-spec nameprep(binary()) -> binary() | error.

Applies Nameprep Profile of Stringprep. Returns error on failure.

Example:

> jid:nameprep(<<"SerVer">>).
<<"server">>

resourceprep/1

-spec resourceprep(binary()) -> binary() | error.

Applies Resourceprep Profile of Stringprep. Returns error on failure.

Example:

> jid:resourceprep(<<"Resource">>).
<<"Resource">>

tolower/1

-spec tolower(jid() | ljid()) -> ljid() | error.

Creates ljid() with Stringprep Profile applied to its parts. Returns error if stringprep has failed.

Example 1: creating from jid()

> JID.
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}
> jid:tolower(JID).
{<<"user">>,<<"server">>,<<"Resource">>}

Example 2: creating from ljid()

> jid:tolower({<<"User">>, <<"Server">>, <<"Resource">>}).
{<<"user">>,<<"server">>,<<"Resource">>}

Example 3: stringprep failure

> jid:tolower({<<"@">>, <<"Server">>, <<"Resource">>}).
error

split/1

-spec split(jid()) -> ljid().

Creates ljid() from jid(). Unlike tolower/1 Strinprep Profile is not applied.

Example:

> JID.
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}
> jid:split(JID).
{<<"User">>,<<"Server">>,<<"Resource">>}

remove_resource/1

-spec remove_resource(jid()) -> jid();
		     (ljid()) -> ljid().

Removes resource part of a JID.

Example 1: removing resource of jid()

> JID.
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"Resource">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"Resource">>}
> jid:remove_resource(JID).
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<>>,luser = <<"user">>,lserver = <<"server">>,
     lresource = <<>>}

Example 2: removing resource of ljid()

> jid:remove_resource({<<"User">>, <<"Server">>, <<"Resource">>}).
{<<"User">>,<<"Server">>,<<>>}

replace_resource/2

-spec replace_resource(jid(), binary()) -> error | jid().

Replaces resource part of a JID. Returns error if resourceprep has failed.

Example: replacing resource

> JID.
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"old">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"old">>}
> jid:replace_resource(JID, <<"new">>).
#jid{user = <<"User">>,server = <<"Server">>,
     resource = <<"new">>,luser = <<"user">>,
     lserver = <<"server">>,lresource = <<"new">>}