mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Add zlib compression test case
This commit is contained in:
parent
167dd59941
commit
60dbaa0dac
@ -61,7 +61,7 @@ init_per_testcase(start_ejabberd, Config) ->
|
||||
Config;
|
||||
init_per_testcase(TestCase, OrigConfig) ->
|
||||
Resource = list_to_binary(atom_to_list(TestCase)),
|
||||
Config = [{resource, Resource}|OrigConfig],
|
||||
Config = set_opt(resource, Resource, OrigConfig),
|
||||
case TestCase of
|
||||
test_connect ->
|
||||
Config;
|
||||
@ -69,6 +69,8 @@ init_per_testcase(TestCase, OrigConfig) ->
|
||||
connect(Config);
|
||||
test_starttls ->
|
||||
connect(Config);
|
||||
test_zlib ->
|
||||
connect(Config);
|
||||
test_register ->
|
||||
connect(Config);
|
||||
auth_md5 ->
|
||||
@ -89,12 +91,13 @@ end_per_testcase(_TestCase, _Config) ->
|
||||
groups() ->
|
||||
[].
|
||||
|
||||
%%all() -> [start_ejabberd, test_starttls].
|
||||
%%all() -> [start_ejabberd, test_zlib].
|
||||
|
||||
all() ->
|
||||
[start_ejabberd,
|
||||
test_connect,
|
||||
test_starttls,
|
||||
test_zlib,
|
||||
test_register,
|
||||
auth_plain,
|
||||
auth_md5,
|
||||
@ -134,7 +137,7 @@ connect(Config) ->
|
||||
binary_to_list(?config(server, Config)),
|
||||
?config(port, Config),
|
||||
[binary, {packet, 0}, {active, false}]),
|
||||
init_stream([{socket, Sock}|Config]).
|
||||
init_stream(set_opt(socket, Sock, Config)).
|
||||
|
||||
init_stream(Config) ->
|
||||
ok = send_text(Config, io_lib:format(?STREAM_HEADER,
|
||||
@ -149,15 +152,16 @@ init_stream(Config) ->
|
||||
(_) ->
|
||||
[]
|
||||
end, Fs),
|
||||
Feats = lists:foldl(
|
||||
fun(#feature_register{}, Acc) ->
|
||||
[{register, true}|Acc];
|
||||
(#starttls{}, Acc) ->
|
||||
[{starttls, true}|Acc];
|
||||
(_, Acc) ->
|
||||
Acc
|
||||
end, [], Fs),
|
||||
[{mechs, Mechs}|Feats ++ Config].
|
||||
lists:foldl(
|
||||
fun(#feature_register{}, Acc) ->
|
||||
set_opt(register, true, Acc);
|
||||
(#starttls{}, Acc) ->
|
||||
set_opt(starttls, true, Acc);
|
||||
(#compression{methods = Ms}, Acc) ->
|
||||
set_opt(compression, Ms, Acc);
|
||||
(_, Acc) ->
|
||||
Acc
|
||||
end, set_opt(mechs, Mechs, Config), Fs).
|
||||
|
||||
disconnect(Config) ->
|
||||
Socket = ?config(socket, Config),
|
||||
@ -181,8 +185,26 @@ starttls(Config) ->
|
||||
?config(socket, Config),
|
||||
[{certfile, ?config(certfile, Config)},
|
||||
connect]),
|
||||
NewConfig = [{socket, TLSSocket}|lists:keydelete(socket, 1, Config)],
|
||||
disconnect(init_stream(NewConfig)).
|
||||
disconnect(init_stream(set_opt(socket, TLSSocket, Config))).
|
||||
|
||||
test_zlib(Config) ->
|
||||
case ?config(compression, Config) of
|
||||
[_|_] = Ms ->
|
||||
case lists:member(<<"zlib">>, Ms) of
|
||||
true ->
|
||||
zlib(Config);
|
||||
false ->
|
||||
{skipped, 'zlib_not_available'}
|
||||
end;
|
||||
_ ->
|
||||
{skipped, 'compression_not_available'}
|
||||
end.
|
||||
|
||||
zlib(Config) ->
|
||||
_ = send(Config, #compress{methods = [<<"zlib">>]}),
|
||||
#compressed{} = recv(),
|
||||
ZlibSocket = ejabberd_socket:compress(?config(socket, Config)),
|
||||
disconnect(init_stream(set_opt(socket, ZlibSocket, Config))).
|
||||
|
||||
test_register(Config) ->
|
||||
case ?config(register, Config) of
|
||||
@ -528,7 +550,7 @@ auth_SASL(Mech, Config) ->
|
||||
?config(server, Config),
|
||||
?config(password, Config)),
|
||||
send(Config, #sasl_auth{mechanism = Mech, text = Response}),
|
||||
wait_auth_SASL_result([{sasl, SASL}|Config]).
|
||||
wait_auth_SASL_result(set_opt(sasl, SASL, Config)).
|
||||
|
||||
wait_auth_SASL_result(Config) ->
|
||||
case recv() of
|
||||
@ -545,8 +567,7 @@ wait_auth_SASL_result(Config) ->
|
||||
#sasl_challenge{text = ClientIn} ->
|
||||
{Response, SASL} = (?config(sasl, Config))(ClientIn),
|
||||
send(Config, #sasl_response{text = Response}),
|
||||
Config1 = proplists:delete(sasl, Config),
|
||||
wait_auth_SASL_result([{sasl, SASL}|Config1]);
|
||||
wait_auth_SASL_result(set_opt(sasl, SASL, Config));
|
||||
#sasl_failure{} ->
|
||||
ct:fail(sasl_auth_failed)
|
||||
end.
|
||||
@ -716,3 +737,6 @@ bookmark_conference() ->
|
||||
<<"some">>,
|
||||
<<"some.conference.org">>,
|
||||
<<>>)}.
|
||||
|
||||
set_opt(Opt, Val, Config) ->
|
||||
[{Opt, Val}|lists:keydelete(Opt, 1, Config)].
|
||||
|
@ -6,7 +6,7 @@
|
||||
{5222, ejabberd_c2s, [
|
||||
{access, c2s},
|
||||
{shaper, c2s_shaper},
|
||||
starttls,
|
||||
starttls, zlib,
|
||||
{certfile, 'CERTFILE'},
|
||||
{max_stanza_size, 65536}
|
||||
]},
|
||||
|
@ -1,6 +1,6 @@
|
||||
%% Created automatically by XML generator (xml_gen.erl)
|
||||
%% Source: xmpp_codec.spec
|
||||
%% Date: Fri, 14 Jun 2013 08:43:04 GMT
|
||||
%% Date: Fri, 14 Jun 2013 14:30:53 GMT
|
||||
|
||||
-module(xmpp_codec).
|
||||
|
||||
@ -348,6 +348,33 @@ decode({xmlel, _name, _attrs, _} = _el) ->
|
||||
{<<"stream:features">>,
|
||||
<<"http://etherx.jabber.org/streams">>} ->
|
||||
decode_stream_features(_el);
|
||||
{<<"compression">>,
|
||||
<<"http://jabber.org/features/compress">>} ->
|
||||
decode_compression(_el);
|
||||
{<<"method">>,
|
||||
<<"http://jabber.org/features/compress">>} ->
|
||||
decode_compression_method(_el);
|
||||
{<<"compressed">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compressed(_el);
|
||||
{<<"compress">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress(_el);
|
||||
{<<"method">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress_method(_el);
|
||||
{<<"failure">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress_failure(_el);
|
||||
{<<"unsupported-method">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress_failure_unsupported_method(_el);
|
||||
{<<"processing-failed">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress_failure_processing_failed(_el);
|
||||
{<<"setup-failed">>,
|
||||
<<"http://jabber.org/protocol/compress">>} ->
|
||||
decode_compress_failure_setup_failed(_el);
|
||||
{<<"failure">>,
|
||||
<<"urn:ietf:params:xml:ns:xmpp-tls">>} ->
|
||||
decode_starttls_failure(_el);
|
||||
@ -715,6 +742,22 @@ encode({stream_features, _} = Stream_features) ->
|
||||
encode_stream_features(Stream_features,
|
||||
[{<<"xmlns">>,
|
||||
<<"http://etherx.jabber.org/streams">>}]);
|
||||
encode({compression, _} = Compression) ->
|
||||
encode_compression(Compression,
|
||||
[{<<"xmlns">>,
|
||||
<<"http://jabber.org/features/compress">>}]);
|
||||
encode({compressed} = Compressed) ->
|
||||
encode_compressed(Compressed,
|
||||
[{<<"xmlns">>,
|
||||
<<"http://jabber.org/protocol/compress">>}]);
|
||||
encode({compress, _} = Compress) ->
|
||||
encode_compress(Compress,
|
||||
[{<<"xmlns">>,
|
||||
<<"http://jabber.org/protocol/compress">>}]);
|
||||
encode({compress_failure, _} = Failure) ->
|
||||
encode_compress_failure(Failure,
|
||||
[{<<"xmlns">>,
|
||||
<<"http://jabber.org/protocol/compress">>}]);
|
||||
encode({starttls_failure} = Failure) ->
|
||||
encode_starttls_failure(Failure,
|
||||
[{<<"xmlns">>,
|
||||
@ -4638,6 +4681,234 @@ encode_starttls_failure({starttls_failure},
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"failure">>, _attrs, _els}.
|
||||
|
||||
decode_compress_failure_setup_failed({xmlel,
|
||||
<<"setup-failed">>, _attrs, _els}) ->
|
||||
'setup-failed'.
|
||||
|
||||
encode_compress_failure_setup_failed('setup-failed',
|
||||
_xmlns_attrs) ->
|
||||
_els = [],
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"setup-failed">>, _attrs, _els}.
|
||||
|
||||
decode_compress_failure_processing_failed({xmlel,
|
||||
<<"processing-failed">>, _attrs,
|
||||
_els}) ->
|
||||
'processing-failed'.
|
||||
|
||||
encode_compress_failure_processing_failed('processing-failed',
|
||||
_xmlns_attrs) ->
|
||||
_els = [],
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"processing-failed">>, _attrs, _els}.
|
||||
|
||||
decode_compress_failure_unsupported_method({xmlel,
|
||||
<<"unsupported-method">>, _attrs,
|
||||
_els}) ->
|
||||
'unsupported-method'.
|
||||
|
||||
encode_compress_failure_unsupported_method('unsupported-method',
|
||||
_xmlns_attrs) ->
|
||||
_els = [],
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"unsupported-method">>, _attrs, _els}.
|
||||
|
||||
decode_compress_failure({xmlel, <<"failure">>, _attrs,
|
||||
_els}) ->
|
||||
Reason = decode_compress_failure_els(_els, undefined),
|
||||
{compress_failure, Reason}.
|
||||
|
||||
decode_compress_failure_els([], Reason) -> Reason;
|
||||
decode_compress_failure_els([{xmlel, <<"setup-failed">>,
|
||||
_attrs, _} =
|
||||
_el
|
||||
| _els],
|
||||
Reason) ->
|
||||
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||
if _xmlns == <<>>;
|
||||
_xmlns == <<"http://jabber.org/protocol/compress">> ->
|
||||
decode_compress_failure_els(_els,
|
||||
decode_compress_failure_setup_failed(_el));
|
||||
true -> decode_compress_failure_els(_els, Reason)
|
||||
end;
|
||||
decode_compress_failure_els([{xmlel,
|
||||
<<"processing-failed">>, _attrs, _} =
|
||||
_el
|
||||
| _els],
|
||||
Reason) ->
|
||||
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||
if _xmlns == <<>>;
|
||||
_xmlns == <<"http://jabber.org/protocol/compress">> ->
|
||||
decode_compress_failure_els(_els,
|
||||
decode_compress_failure_processing_failed(_el));
|
||||
true -> decode_compress_failure_els(_els, Reason)
|
||||
end;
|
||||
decode_compress_failure_els([{xmlel,
|
||||
<<"unsupported-method">>, _attrs, _} =
|
||||
_el
|
||||
| _els],
|
||||
Reason) ->
|
||||
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||
if _xmlns == <<>>;
|
||||
_xmlns == <<"http://jabber.org/protocol/compress">> ->
|
||||
decode_compress_failure_els(_els,
|
||||
decode_compress_failure_unsupported_method(_el));
|
||||
true -> decode_compress_failure_els(_els, Reason)
|
||||
end;
|
||||
decode_compress_failure_els([_ | _els], Reason) ->
|
||||
decode_compress_failure_els(_els, Reason).
|
||||
|
||||
encode_compress_failure({compress_failure, Reason},
|
||||
_xmlns_attrs) ->
|
||||
_els = 'encode_compress_failure_$reason'(Reason, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"failure">>, _attrs, _els}.
|
||||
|
||||
'encode_compress_failure_$reason'(undefined, _acc) ->
|
||||
_acc;
|
||||
'encode_compress_failure_$reason'('setup-failed' =
|
||||
Reason,
|
||||
_acc) ->
|
||||
[encode_compress_failure_setup_failed(Reason, [])
|
||||
| _acc];
|
||||
'encode_compress_failure_$reason'('processing-failed' =
|
||||
Reason,
|
||||
_acc) ->
|
||||
[encode_compress_failure_processing_failed(Reason, [])
|
||||
| _acc];
|
||||
'encode_compress_failure_$reason'('unsupported-method' =
|
||||
Reason,
|
||||
_acc) ->
|
||||
[encode_compress_failure_unsupported_method(Reason, [])
|
||||
| _acc].
|
||||
|
||||
decode_compress_method({xmlel, <<"method">>, _attrs,
|
||||
_els}) ->
|
||||
Cdata = decode_compress_method_els(_els, <<>>), Cdata.
|
||||
|
||||
decode_compress_method_els([], Cdata) ->
|
||||
decode_compress_method_cdata(Cdata);
|
||||
decode_compress_method_els([{xmlcdata, _data} | _els],
|
||||
Cdata) ->
|
||||
decode_compress_method_els(_els,
|
||||
<<Cdata/binary, _data/binary>>);
|
||||
decode_compress_method_els([_ | _els], Cdata) ->
|
||||
decode_compress_method_els(_els, Cdata).
|
||||
|
||||
encode_compress_method(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_compress_method_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"method">>, _attrs, _els}.
|
||||
|
||||
decode_compress_method_cdata(<<>>) -> undefined;
|
||||
decode_compress_method_cdata(_val) -> _val.
|
||||
|
||||
encode_compress_method_cdata(undefined, _acc) -> _acc;
|
||||
encode_compress_method_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_compress({xmlel, <<"compress">>, _attrs,
|
||||
_els}) ->
|
||||
Methods = decode_compress_els(_els, []),
|
||||
{compress, Methods}.
|
||||
|
||||
decode_compress_els([], Methods) ->
|
||||
lists:reverse(Methods);
|
||||
decode_compress_els([{xmlel, <<"method">>, _attrs, _} =
|
||||
_el
|
||||
| _els],
|
||||
Methods) ->
|
||||
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||
if _xmlns == <<>>;
|
||||
_xmlns == <<"http://jabber.org/protocol/compress">> ->
|
||||
decode_compress_els(_els,
|
||||
[decode_compress_method(_el) | Methods]);
|
||||
true -> decode_compress_els(_els, Methods)
|
||||
end;
|
||||
decode_compress_els([_ | _els], Methods) ->
|
||||
decode_compress_els(_els, Methods).
|
||||
|
||||
encode_compress({compress, Methods}, _xmlns_attrs) ->
|
||||
_els = 'encode_compress_$methods'(Methods, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"compress">>, _attrs, _els}.
|
||||
|
||||
'encode_compress_$methods'([], _acc) -> _acc;
|
||||
'encode_compress_$methods'([Methods | _els], _acc) ->
|
||||
'encode_compress_$methods'(_els,
|
||||
[encode_compress_method(Methods, []) | _acc]).
|
||||
|
||||
decode_compressed({xmlel, <<"compressed">>, _attrs,
|
||||
_els}) ->
|
||||
{compressed}.
|
||||
|
||||
encode_compressed({compressed}, _xmlns_attrs) ->
|
||||
_els = [],
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"compressed">>, _attrs, _els}.
|
||||
|
||||
decode_compression_method({xmlel, <<"method">>, _attrs,
|
||||
_els}) ->
|
||||
Cdata = decode_compression_method_els(_els, <<>>),
|
||||
Cdata.
|
||||
|
||||
decode_compression_method_els([], Cdata) ->
|
||||
decode_compression_method_cdata(Cdata);
|
||||
decode_compression_method_els([{xmlcdata, _data}
|
||||
| _els],
|
||||
Cdata) ->
|
||||
decode_compression_method_els(_els,
|
||||
<<Cdata/binary, _data/binary>>);
|
||||
decode_compression_method_els([_ | _els], Cdata) ->
|
||||
decode_compression_method_els(_els, Cdata).
|
||||
|
||||
encode_compression_method(Cdata, _xmlns_attrs) ->
|
||||
_els = encode_compression_method_cdata(Cdata, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"method">>, _attrs, _els}.
|
||||
|
||||
decode_compression_method_cdata(<<>>) -> undefined;
|
||||
decode_compression_method_cdata(_val) -> _val.
|
||||
|
||||
encode_compression_method_cdata(undefined, _acc) ->
|
||||
_acc;
|
||||
encode_compression_method_cdata(_val, _acc) ->
|
||||
[{xmlcdata, _val} | _acc].
|
||||
|
||||
decode_compression({xmlel, <<"compression">>, _attrs,
|
||||
_els}) ->
|
||||
Methods = decode_compression_els(_els, []),
|
||||
{compression, Methods}.
|
||||
|
||||
decode_compression_els([], Methods) ->
|
||||
lists:reverse(Methods);
|
||||
decode_compression_els([{xmlel, <<"method">>, _attrs,
|
||||
_} =
|
||||
_el
|
||||
| _els],
|
||||
Methods) ->
|
||||
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||
if _xmlns == <<>>;
|
||||
_xmlns == <<"http://jabber.org/features/compress">> ->
|
||||
decode_compression_els(_els,
|
||||
[decode_compression_method(_el) | Methods]);
|
||||
true -> decode_compression_els(_els, Methods)
|
||||
end;
|
||||
decode_compression_els([_ | _els], Methods) ->
|
||||
decode_compression_els(_els, Methods).
|
||||
|
||||
encode_compression({compression, Methods},
|
||||
_xmlns_attrs) ->
|
||||
_els = 'encode_compression_$methods'(Methods, []),
|
||||
_attrs = _xmlns_attrs,
|
||||
{xmlel, <<"compression">>, _attrs, _els}.
|
||||
|
||||
'encode_compression_$methods'([], _acc) -> _acc;
|
||||
'encode_compression_$methods'([Methods | _els], _acc) ->
|
||||
'encode_compression_$methods'(_els,
|
||||
[encode_compression_method(Methods, [])
|
||||
| _acc]).
|
||||
|
||||
decode_stream_features({xmlel, <<"stream:features">>,
|
||||
_attrs, _els}) ->
|
||||
__Els = decode_stream_features_els(_els, []),
|
||||
|
@ -1,6 +1,6 @@
|
||||
%% Created automatically by XML generator (xml_gen.erl)
|
||||
%% Source: xmpp_codec.spec
|
||||
%% Date: Fri, 14 Jun 2013 08:43:04 GMT
|
||||
%% Date: Fri, 14 Jun 2013 14:30:53 GMT
|
||||
|
||||
-record(last, {seconds, text}).
|
||||
|
||||
@ -86,6 +86,14 @@
|
||||
|
||||
-record(starttls_failure, {}).
|
||||
|
||||
-record(compress_failure, {reason}).
|
||||
|
||||
-record(compress, {methods = []}).
|
||||
|
||||
-record(compressed, {}).
|
||||
|
||||
-record(compression, {methods = []}).
|
||||
|
||||
-record(stream_features, {sub_els = []}).
|
||||
|
||||
-record(p1_push, {}).
|
||||
|
@ -748,6 +748,62 @@
|
||||
xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>,
|
||||
result = {starttls_failure}}}.
|
||||
|
||||
%% <xs:element name='setup-failed' type='empty'/>
|
||||
%% <xs:element name='processing-failed' type='empty'/>
|
||||
%% <xs:element name='unsupported-method' type='empty'/>
|
||||
|
||||
{compress_failure_setup_failed,
|
||||
#elem{name = <<"setup-failed">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = 'setup-failed'}}.
|
||||
{compress_failure_processing_failed,
|
||||
#elem{name = <<"processing-failed">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = 'processing-failed'}}.
|
||||
{compress_failure_unsupported_method,
|
||||
#elem{name = <<"unsupported-method">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = 'unsupported-method'}}.
|
||||
|
||||
{compress_failure,
|
||||
#elem{name = <<"failure">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = {compress_failure, '$reason'},
|
||||
refs = [#ref{name = compress_failure_setup_failed,
|
||||
min = 0, max = 1, label = '$reason'},
|
||||
#ref{name = compress_failure_processing_failed,
|
||||
min = 0, max = 1, label = '$reason'},
|
||||
#ref{name = compress_failure_unsupported_method,
|
||||
min = 0, max = 1, label = '$reason'}]}}.
|
||||
|
||||
{compress_method,
|
||||
#elem{name = <<"method">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = '$cdata'}}.
|
||||
|
||||
{compress,
|
||||
#elem{name = <<"compress">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = {compress, '$methods'},
|
||||
refs = [#ref{name = compress_method,
|
||||
label = '$methods'}]}}.
|
||||
|
||||
{compressed,
|
||||
#elem{name = <<"compressed">>,
|
||||
xmlns = <<"http://jabber.org/protocol/compress">>,
|
||||
result = {compressed}}}.
|
||||
|
||||
{compression_method,
|
||||
#elem{name = <<"method">>,
|
||||
xmlns = <<"http://jabber.org/features/compress">>,
|
||||
result = '$cdata'}}.
|
||||
|
||||
{compression,
|
||||
#elem{name = <<"compression">>,
|
||||
xmlns = <<"http://jabber.org/features/compress">>,
|
||||
result = {compression, '$methods'},
|
||||
refs = [#ref{name = compression_method, label = '$methods'}]}}.
|
||||
|
||||
{stream_features,
|
||||
#elem{name = <<"stream:features">>,
|
||||
xmlns = <<"http://etherx.jabber.org/streams">>,
|
||||
|
Loading…
Reference in New Issue
Block a user