diff options
Diffstat (limited to 'src/xmpp_codec.erl')
-rw-r--r-- | src/xmpp_codec.erl | 184 |
1 files changed, 181 insertions, 3 deletions
diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index 113be860b..11bd741f4 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -15,6 +15,16 @@ decode(_el) -> decode(_el, []). decode({xmlel, _name, _attrs, _} = _el, Opts) -> IgnoreEls = proplists:get_bool(ignore_els, Opts), case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"address">>, <<"urn:xmpp:sic:0">>} -> + decode_sic(<<"urn:xmpp:sic:0">>, IgnoreEls, _el); + {<<"address">>, <<"urn:xmpp:sic:1">>} -> + decode_sic(<<"urn:xmpp:sic:1">>, IgnoreEls, _el); + {<<"port">>, <<"urn:xmpp:sic:1">>} -> + decode_sip_port(<<"urn:xmpp:sic:1">>, IgnoreEls, _el); + {<<"ip">>, <<"urn:xmpp:sic:0">>} -> + decode_sic_ip(<<"urn:xmpp:sic:0">>, IgnoreEls, _el); + {<<"ip">>, <<"urn:xmpp:sic:1">>} -> + decode_sic_ip(<<"urn:xmpp:sic:1">>, IgnoreEls, _el); {<<"x">>, <<"jabber:x:oob">>} -> decode_oob_x(<<"jabber:x:oob">>, IgnoreEls, _el); {<<"desc">>, <<"jabber:x:oob">>} -> @@ -1309,6 +1319,11 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> is_known_tag({xmlel, _name, _attrs, _} = _el) -> case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"address">>, <<"urn:xmpp:sic:0">>} -> true; + {<<"address">>, <<"urn:xmpp:sic:1">>} -> true; + {<<"port">>, <<"urn:xmpp:sic:1">>} -> true; + {<<"ip">>, <<"urn:xmpp:sic:0">>} -> true; + {<<"ip">>, <<"urn:xmpp:sic:1">>} -> true; {<<"x">>, <<"jabber:x:oob">>} -> true; {<<"desc">>, <<"jabber:x:oob">>} -> true; {<<"url">>, <<"jabber:x:oob">>} -> true; @@ -2609,7 +2624,9 @@ encode({media, _, _, _} = Media) -> encode_media(Media, [{<<"xmlns">>, <<"urn:xmpp:media-element">>}]); encode({oob_x, _, _, _} = X) -> - encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]). + encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]); +encode({sic, _, _, _} = Address) -> + encode_sic(Address, []). get_name({last, _, _}) -> <<"query">>; get_name({version, _, _, _}) -> <<"query">>; @@ -2802,7 +2819,8 @@ get_name({bob_data, _, _, _, _}) -> <<"data">>; get_name({xcaptcha, _}) -> <<"captcha">>; get_name({media_uri, _, _}) -> <<"uri">>; get_name({media, _, _, _}) -> <<"media">>; -get_name({oob_x, _, _, _}) -> <<"x">>. +get_name({oob_x, _, _, _}) -> <<"x">>; +get_name({sic, _, _, _}) -> <<"address">>. get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; @@ -3070,7 +3088,8 @@ get_ns({media_uri, _, _}) -> <<"urn:xmpp:media-element">>; get_ns({media, _, _, _}) -> <<"urn:xmpp:media-element">>; -get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>. +get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>; +get_ns({sic, _, _, Xmlns}) -> Xmlns. dec_int(Val) -> dec_int(Val, infinity, infinity). @@ -3319,8 +3338,18 @@ pp(xcaptcha, 1) -> [xdata]; pp(media_uri, 2) -> [type, uri]; pp(media, 3) -> [height, width, uri]; pp(oob_x, 3) -> [url, desc, sid]; +pp(sic, 3) -> [ip, port, xmlns]; pp(_, _) -> no. +enc_ip({0, 0, 0, 0, 0, 65535, A, B}) -> + enc_ip({(A bsr 8) band 255, A band 255, + (B bsr 8) band 255, B band 255}); +enc_ip(Addr) -> list_to_binary(inet_parse:ntoa(Addr)). + +dec_ip(S) -> + {ok, Addr} = inet_parse:address(binary_to_list(S)), + Addr. + join([], _Sep) -> <<>>; join([H | T], Sep) -> <<H/binary, << <<Sep, X/binary>> || X <- T >>/binary>>. @@ -3365,6 +3394,155 @@ dec_tzo(Val) -> M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. +decode_sic(__TopXMLNS, __IgnoreEls, + {xmlel, <<"address">>, _attrs, _els}) -> + {Ip, Port} = decode_sic_els(__TopXMLNS, __IgnoreEls, + _els, undefined, undefined), + Xmlns = decode_sic_attrs(__TopXMLNS, _attrs, undefined), + {sic, Ip, Port, Xmlns}. + +decode_sic_els(__TopXMLNS, __IgnoreEls, [], Ip, Port) -> + {Ip, Port}; +decode_sic_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"ip">>, _attrs, _} = _el | _els], Ip, + Port) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> + when __TopXMLNS == <<"urn:xmpp:sic:1">>; + __TopXMLNS == <<"urn:xmpp:sic:0">> -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, + decode_sic_ip(__TopXMLNS, __IgnoreEls, _el), Port); + <<"urn:xmpp:sic:0">> -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, + decode_sic_ip(<<"urn:xmpp:sic:0">>, __IgnoreEls, _el), + Port); + <<"urn:xmpp:sic:1">> -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, + decode_sic_ip(<<"urn:xmpp:sic:1">>, __IgnoreEls, _el), + Port); + _ -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port) + end; +decode_sic_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"port">>, _attrs, _} = _el | _els], Ip, + Port) -> + case get_attr(<<"xmlns">>, _attrs) of + <<"">> when __TopXMLNS == <<"urn:xmpp:sic:1">> -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, + decode_sip_port(__TopXMLNS, __IgnoreEls, _el)); + <<"urn:xmpp:sic:1">> -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, + decode_sip_port(<<"urn:xmpp:sic:1">>, __IgnoreEls, + _el)); + _ -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port) + end; +decode_sic_els(__TopXMLNS, __IgnoreEls, [_ | _els], Ip, + Port) -> + decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port). + +decode_sic_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], _Xmlns) -> + decode_sic_attrs(__TopXMLNS, _attrs, _val); +decode_sic_attrs(__TopXMLNS, [_ | _attrs], Xmlns) -> + decode_sic_attrs(__TopXMLNS, _attrs, Xmlns); +decode_sic_attrs(__TopXMLNS, [], Xmlns) -> + decode_sic_attr_xmlns(__TopXMLNS, Xmlns). + +encode_sic({sic, Ip, Port, Xmlns}, _xmlns_attrs) -> + _els = lists:reverse('encode_sic_$ip'(Ip, + 'encode_sic_$port'(Port, []))), + _attrs = encode_sic_attr_xmlns(Xmlns, _xmlns_attrs), + {xmlel, <<"address">>, _attrs, _els}. + +'encode_sic_$ip'(undefined, _acc) -> _acc; +'encode_sic_$ip'(Ip, _acc) -> + [encode_sic_ip(Ip, []) | _acc]. + +'encode_sic_$port'(undefined, _acc) -> _acc; +'encode_sic_$port'(Port, _acc) -> + [encode_sip_port(Port, []) | _acc]. + +decode_sic_attr_xmlns(__TopXMLNS, undefined) -> + undefined; +decode_sic_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_sic_attr_xmlns(undefined, _acc) -> _acc; +encode_sic_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_sip_port(__TopXMLNS, __IgnoreEls, + {xmlel, <<"port">>, _attrs, _els}) -> + Cdata = decode_sip_port_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_sip_port_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_sip_port_cdata(__TopXMLNS, Cdata); +decode_sip_port_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_sip_port_els(__TopXMLNS, __IgnoreEls, _els, + <<Cdata/binary, _data/binary>>); +decode_sip_port_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_sip_port_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_sip_port(Cdata, _xmlns_attrs) -> + _els = encode_sip_port_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"port">>, _attrs, _els}. + +decode_sip_port_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"port">>, __TopXMLNS}}); +decode_sip_port_cdata(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, 65535) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"port">>, __TopXMLNS}}); + _res -> _res + end. + +encode_sip_port_cdata(_val, _acc) -> + [{xmlcdata, enc_int(_val)} | _acc]. + +decode_sic_ip(__TopXMLNS, __IgnoreEls, + {xmlel, <<"ip">>, _attrs, _els}) -> + Cdata = decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els, + <<>>), + Cdata. + +decode_sic_ip_els(__TopXMLNS, __IgnoreEls, [], Cdata) -> + decode_sic_ip_cdata(__TopXMLNS, Cdata); +decode_sic_ip_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els, + <<Cdata/binary, _data/binary>>); +decode_sic_ip_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els, Cdata). + +encode_sic_ip(Cdata, _xmlns_attrs) -> + _els = encode_sic_ip_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"ip">>, _attrs, _els}. + +decode_sic_ip_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"ip">>, __TopXMLNS}}); +decode_sic_ip_cdata(__TopXMLNS, _val) -> + case catch dec_ip(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"ip">>, __TopXMLNS}}); + _res -> _res + end. + +encode_sic_ip_cdata(_val, _acc) -> + [{xmlcdata, enc_ip(_val)} | _acc]. + decode_oob_x(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> {Desc, Url} = decode_oob_x_els(__TopXMLNS, __IgnoreEls, |