From 62a07af4693ff3feb4d68d311256a9be2afa8bf1 Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 21 Dec 2020 22:11:52 +0100 Subject: [PATCH 1/6] Remove HTTP Upload 0.2.5 checks from the test suite --- big_tests/tests/mod_http_upload_SUITE.erl | 174 +++++++++------------- 1 file changed, 72 insertions(+), 102 deletions(-) diff --git a/big_tests/tests/mod_http_upload_SUITE.erl b/big_tests/tests/mod_http_upload_SUITE.erl index cb3095319df..a00738d000a 100644 --- a/big_tests/tests/mod_http_upload_SUITE.erl +++ b/big_tests/tests/mod_http_upload_SUITE.erl @@ -8,7 +8,6 @@ -include_lib("exml/include/exml.hrl"). -define(NS_XDATA, <<"jabber:x:data">>). --define(NS_HTTP_UPLOAD_025, <<"urn:xmpp:http:upload">>). -define(NS_HTTP_UPLOAD_030, <<"urn:xmpp:http:upload:0">>). -define(S3_HOSTNAME, "http://bucket.s3-eu-east-25.example.com"). @@ -123,26 +122,26 @@ http_upload_item_discovery(Config) -> end). http_upload_feature_discovery(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = escalus_client:server(Bob), Result = escalus:send_and_wait(Bob, escalus_stanza:disco_info(ServJID)), - escalus:assert(fun has_no_feature/2, [Namespace], Result), + escalus:assert(fun has_no_feature/2, [ns()], Result), SubServJID = upload_service(Bob), SubResult = escalus:send_and_wait(Bob, escalus_stanza:disco_info(SubServJID)), - escalus:assert(has_feature, [Namespace], SubResult) + escalus:assert(has_feature, [ns()], SubResult) end). advertises_max_file_size(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), Result = escalus:send_and_wait(Bob, escalus_stanza:disco_info(ServJID)), Forms = exml_query:paths(Result, [{element, <<"query">>}, {element, <<"x">>}]), [Form] = lists:filter( - fun(F) -> has_field(<<"FORM_TYPE">>, <<"hidden">>, Namespace, F) end, + fun(F) -> has_field(<<"FORM_TYPE">>, <<"hidden">>, ns(), F) end, Forms), escalus:assert(has_type, [<<"result">>], Form), @@ -160,50 +159,48 @@ does_not_advertise_max_size_if_unset(Config) -> end). rejects_set_iq(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - IQ = escalus_stanza:iq_set(Namespace, []), + IQ = escalus_stanza:iq_set(ns(), []), Request = escalus_stanza:to(IQ, ServJID), Result = escalus:send_and_wait(Bob, Request), escalus_assert:is_error(Result, <<"cancel">>, <<"not-allowed">>) end). request_slot(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, undefined), Result = escalus:send_and_wait(Bob, Request), escalus:assert(is_iq_result, Result), - escalus:assert(fun has_namespace/2, [Namespace], Result), - escalus:assert(fun has_put_and_get_fields/2, [Namespace], Result) + escalus:assert(fun has_upload_namespace/1, Result), + escalus:assert(fun has_put_and_get_fields/1, Result) end). get_url_ends_with_filename(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), Filename = <<"filename.jpg">>, - Request = create_slot_request_stanza(ServJID, Filename, 123, undefined, Namespace), + Request = create_slot_request_stanza(ServJID, Filename, 123, undefined), Result = escalus:send_and_wait(Bob, Request), - escalus:assert(fun path_ends_with/4, [<<"get">>, Filename, Namespace], Result) + escalus:assert(fun path_ends_with/3, [<<"get">>, Filename], Result) end). urls_contain_s3_hostname(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, undefined), Result = escalus:send_and_wait(Bob, Request), - escalus:assert(fun url_contains/4, [<<"get">>, <>, Namespace], Result), - escalus:assert(fun url_contains/4, [<<"put">>, <>, Namespace], Result) + escalus:assert(fun url_contains/3, [<<"get">>, <>], Result), + escalus:assert(fun url_contains/3, [<<"put">>, <>], Result) end). test_minio_upload_without_content_type(Config) -> @@ -213,16 +210,15 @@ test_minio_upload_with_content_type(Config) -> test_minio_upload(Config, <<"text/plain">>). test_minio_upload(Config, ContentType) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), FileSize = length(?MINIO_TEST_DATA), - Request = create_slot_request_stanza(ServJID, <<"somefile.txt">>, FileSize, - ContentType, Namespace), + Request = create_slot_request_stanza(ServJID, <<"file.txt">>, FileSize, ContentType), Result = escalus:send_and_wait(Bob, Request), - GetUrl = binary_to_list(extract_url(Result, <<"get">>, Namespace)), - PutUrl = binary_to_list(extract_url(Result, <<"put">>, Namespace)), + GetUrl = binary_to_list(extract_url(Result, <<"get">>)), + PutUrl = binary_to_list(extract_url(Result, <<"put">>)), Header = generate_header(Config, ContentType), PutRetValue = ibrowse:send_req(PutUrl, Header, put, ?MINIO_TEST_DATA), ?assertMatch({ok, "200", _, []}, PutRetValue), @@ -241,44 +237,41 @@ generate_header(Config, ContentType) -> [{<<"Content-Type">>, ContentType} | generate_header(Config, undefined)]. rejects_empty_filename(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<>>, 123, undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<>>, 123, undefined), Result = escalus:send_and_wait(Bob, Request), escalus_assert:is_error(Result, <<"modify">>, <<"bad-request">>) end). rejects_negative_filesize(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, -1, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, -1, undefined), Result = escalus:send_and_wait(Bob, Request), escalus_assert:is_error(Result, <<"modify">>, <<"bad-request">>) end). rejects_invalid_size_type(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, - <<"filesize">>, undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"a.jpg">>, <<"filesize">>, undefined), Result = escalus:send_and_wait(Bob, Request), escalus_assert:is_error(Result, <<"modify">>, <<"bad-request">>) end). denies_slots_over_max_file_size(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 54321, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 54321, undefined), Result = escalus:send_and_wait(Bob, Request), escalus:assert(is_error, [<<"modify">>, <<"not-acceptable">>], Result), <<"1234">> = exml_query:path(Result, [{element, <<"error">>}, @@ -288,25 +281,23 @@ denies_slots_over_max_file_size(Config) -> end). sends_different_put_and_get_urls(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, undefined), Result = escalus:send_and_wait(Bob, Request), - escalus:assert(fun urls_not_equal/2, [Namespace], Result) + escalus:assert(fun urls_not_equal/1, Result) end). escapes_urls_once(Config) -> - namespaced_story( + escalus:story( Config, [{bob, 1}], - fun(Namespace, Bob) -> + fun(Bob) -> ServJID = upload_service(Bob), - Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, - undefined, Namespace), + Request = create_slot_request_stanza(ServJID, <<"filename.jpg">>, 123, undefined), Result = escalus:send_and_wait(Bob, Request), - escalus:assert(fun url_contains/4, [<<"put">>, <<"%3Bx-amz-acl">>, Namespace], Result) + escalus:assert(fun url_contains/3, [<<"put">>, <<"%3Bx-amz-acl">>], Result) end). %%-------------------------------------------------------------------- @@ -321,57 +312,42 @@ is_minio_running(Config) -> lists:member(minio, DBs) end. -create_slot_request_stanza(Server, Filename, Size, ContentType, Namespace) when is_integer(Size) -> - create_slot_request_stanza(Server, Filename, integer_to_binary(Size), ContentType, Namespace); -create_slot_request_stanza(Server, Filename, BinSize, ContentType, Namespace) -> +create_slot_request_stanza(Server, Filename, Size, ContentType) when is_integer(Size) -> + create_slot_request_stanza(Server, Filename, integer_to_binary(Size), ContentType); +create_slot_request_stanza(Server, Filename, BinSize, ContentType) -> #xmlel{name = <<"iq">>, attrs = [{<<"type">>, <<"get">>}, {<<"to">>, Server}], - children = [create_request_for_namespace(Filename, BinSize, ContentType, Namespace)]}. + children = [create_request_element(Filename, BinSize, ContentType)]}. -create_request_for_namespace(Filename, BinSize, ContentType, Namespace = ?NS_HTTP_UPLOAD_025) -> - ContentTypeEl = - case ContentType of - undefined -> []; - _ -> [#xmlel{name = <<"content-type">>, children = [#xmlcdata{content = ContentType}]}] - end, - #xmlel{name = <<"request">>, - attrs = [{<<"xmlns">>, Namespace}], - children = - [#xmlel{name = <<"filename">>, children = [#xmlcdata{content = Filename}]}, - #xmlel{name = <<"size">>, children = [#xmlcdata{content = BinSize}]} - | ContentTypeEl]}; -create_request_for_namespace(Filename, BinSize, ContentType, Namespace = ?NS_HTTP_UPLOAD_030) -> +create_request_element(Filename, BinSize, ContentType) -> ContentTypeEl = case ContentType of undefined -> []; _ -> [{<<"content-type">>, ContentType}] end, #xmlel{name = <<"request">>, - attrs = [{<<"xmlns">>, Namespace}, + attrs = [{<<"xmlns">>, ?NS_HTTP_UPLOAD_030}, {<<"filename">>, Filename}, {<<"size">>, BinSize} | ContentTypeEl]}. -has_namespace(Namespace, #xmlel{name = <<"iq">>, children = [Slot]}) -> - case Slot of - #xmlel{name = <<"slot">>, attrs = [{<<"xmlns">>, Namespace}]} -> true; - _ -> false - end; -has_namespace(_Namespace, _) -> +has_upload_namespace(#xmlel{name = <<"iq">>, children = [#xmlel{ name = <<"slot">> } = Slot]}) -> + ?NS_HTTP_UPLOAD_030 == exml_query:attr(Slot, <<"xmlns">>); +has_upload_namespace(_) -> false. has_no_feature(Feature, Stanza) -> not escalus_pred:has_feature(Feature, Stanza). -has_put_and_get_fields(Namespace, Elem = #xmlel{name = <<"iq">>}) -> - PutUrl = extract_url(Elem, <<"put">>, Namespace), - GetUrl = extract_url(Elem, <<"get">>, Namespace), +has_put_and_get_fields(Elem = #xmlel{name = <<"iq">>}) -> + PutUrl = extract_url(Elem, <<"put">>), + GetUrl = extract_url(Elem, <<"get">>), is_binary(PutUrl) andalso is_binary(GetUrl) andalso byte_size(PutUrl) > 0 andalso byte_size(GetUrl) > 0; -has_put_and_get_fields(_Namespace, _Elem) -> +has_put_and_get_fields(_Elem) -> false. -path_ends_with(UrlType, Filename, Namespace, Result) -> - Url = extract_url(Result, UrlType, Namespace), +path_ends_with(UrlType, Filename, Result) -> + Url = extract_url(Result, UrlType), {ok, {_, _, _, _, PathList, _}} = http_uri:parse(binary_to_list(Url)), FilenameSize = byte_size(Filename), ReverseFilename = reverse(Filename), @@ -380,13 +356,13 @@ path_ends_with(UrlType, Filename, Namespace, Result) -> _ -> false end. -url_contains(UrlType, Filename, Namespace, Result) -> - Url = extract_url(Result, UrlType, Namespace), +url_contains(UrlType, Filename, Result) -> + Url = extract_url(Result, UrlType), binary:match(Url, Filename) =/= nomatch. -urls_not_equal(Namespace, Result) -> - Get = extract_url(Result, <<"get">>, Namespace), - Put = extract_url(Result, <<"put">>, Namespace), +urls_not_equal(Result) -> + Get = extract_url(Result, <<"get">>), + Put = extract_url(Result, <<"put">>), Get =/= Put. reverse(List) when is_list(List) -> @@ -412,14 +388,8 @@ has_field(Var, Type, Value, Form) -> host() -> ct:get_config({hosts, mim, domain}). -extract_url(Result, UrlType, ?NS_HTTP_UPLOAD_025) -> - exml_query:path(Result, [{element, <<"slot">>}, {element, UrlType}, cdata]); -extract_url(Result, UrlType, ?NS_HTTP_UPLOAD_030) -> +extract_url(Result, UrlType) -> exml_query:path(Result, [{element, <<"slot">>}, {element, UrlType}, {attr, <<"url">>}]). -namespaced_story(Config, Users, Story) -> - lists:foreach( - fun(Namespace) -> - escalus:story(Config, Users, fun(User) -> Story(Namespace, User) end) - end, - [?NS_HTTP_UPLOAD_025, ?NS_HTTP_UPLOAD_030]). +ns() -> ?NS_HTTP_UPLOAD_030. + From 7642ac10b2a80cd1099e71026e6bf48bbc953668 Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 21 Dec 2020 22:21:35 +0100 Subject: [PATCH 2/6] Replace deprecated function in mod_http_upload_SUITE --- big_tests/tests/mod_http_upload_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/big_tests/tests/mod_http_upload_SUITE.erl b/big_tests/tests/mod_http_upload_SUITE.erl index a00738d000a..05b9eb94293 100644 --- a/big_tests/tests/mod_http_upload_SUITE.erl +++ b/big_tests/tests/mod_http_upload_SUITE.erl @@ -348,10 +348,10 @@ has_put_and_get_fields(_Elem) -> path_ends_with(UrlType, Filename, Result) -> Url = extract_url(Result, UrlType), - {ok, {_, _, _, _, PathList, _}} = http_uri:parse(binary_to_list(Url)), + #{ path := Path } = uri_string:parse(Url), FilenameSize = byte_size(Filename), ReverseFilename = reverse(Filename), - case reverse(PathList) of + case reverse(Path) of <> -> true; _ -> false end. From 8c27808239981858d91ee140e8219ad794f8ef5c Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 21 Dec 2020 22:27:11 +0100 Subject: [PATCH 3/6] Eradicate export_all from mod_http_upload_SUITE --- big_tests/tests/mod_http_upload_SUITE.erl | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/big_tests/tests/mod_http_upload_SUITE.erl b/big_tests/tests/mod_http_upload_SUITE.erl index 05b9eb94293..41c0b05a910 100644 --- a/big_tests/tests/mod_http_upload_SUITE.erl +++ b/big_tests/tests/mod_http_upload_SUITE.erl @@ -1,6 +1,5 @@ -module(mod_http_upload_SUITE). --compile(export_all). -include_lib("escalus/include/escalus.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -30,6 +29,32 @@ ]} ]). +-export([all/0, groups/0, suite/0, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + init_per_testcase/2, end_per_testcase/2]). + +-export([ + does_not_advertise_max_size_if_unset/1, + + test_minio_upload_without_content_type/1, + test_minio_upload_with_content_type/1, + + http_upload_item_discovery/1, + http_upload_feature_discovery/1, + advertises_max_file_size/1, + request_slot/1, + rejects_set_iq/1, + get_url_ends_with_filename/1, + urls_contain_s3_hostname/1, + rejects_empty_filename/1, + rejects_negative_filesize/1, + rejects_invalid_size_type/1, + denies_slots_over_max_file_size/1, + sends_different_put_and_get_urls/1, + escapes_urls_once/1 + ]). + %%-------------------------------------------------------------------- %% Suite configuration %%-------------------------------------------------------------------- From 54c9a811a8e9b711c89fb992f26af48161416b4a Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 21 Dec 2020 23:05:09 +0100 Subject: [PATCH 4/6] Remove HTTP Upload support for pre-0.3.0 XEPs --- include/mongoose_ns.hrl | 1 - src/http_upload/mod_http_upload.erl | 64 ++++++++++++----------------- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/include/mongoose_ns.hrl b/include/mongoose_ns.hrl index 48553b0330b..7dbca515b5c 100644 --- a/include/mongoose_ns.hrl +++ b/include/mongoose_ns.hrl @@ -57,7 +57,6 @@ -define(NS_SERVERINFO, <<"http://jabber.org/network/serverinfo">>). -define(NS_MAM_04, <<"urn:xmpp:mam:1">>). % MAM 0.4.1 or 0.5 -define(NS_MAM_06, <<"urn:xmpp:mam:2">>). % MAM 0.6 --define(NS_HTTP_UPLOAD_025, <<"urn:xmpp:http:upload">>). -define(NS_HTTP_UPLOAD_030, <<"urn:xmpp:http:upload:0">>). -define(NS_PUSH, <<"urn:xmpp:push:0">>). % Push Notifications v0.2.1 -define(NS_STANZAID, <<"urn:xmpp:sid:0">>). diff --git a/src/http_upload/mod_http_upload.erl b/src/http_upload/mod_http_upload.erl index 82ab51c8cbc..87e9ba8318f 100644 --- a/src/http_upload/mod_http_upload.erl +++ b/src/http_upload/mod_http_upload.erl @@ -19,7 +19,6 @@ -behaviour(gen_mod). -behaviour(mongoose_module_metrics). --xep([{xep, 363}, {version, "0.2.5"}]). -xep([{xep, 363}, {version, "0.3.0"}]). -include("jlib.hrl"). @@ -59,8 +58,6 @@ start(Host, Opts) -> ejabberd_hooks:add(disco_local_identity, SubHost, ?MODULE, get_disco_identity, 90), ejabberd_hooks:add(disco_info, SubHost, ?MODULE, get_disco_info, 90), ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_disco_items, 90), - gen_iq_handler:add_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_025, ?MODULE, - iq_handler, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_030, ?MODULE, iq_handler, IQDisc), gen_mod:start_backend_module(?MODULE, with_default_backend(Opts), [create_slot]). @@ -70,7 +67,6 @@ start(Host, Opts) -> stop(Host) -> SubHost = subhost(Host), gen_iq_handler:remove_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_030), - gen_iq_handler:remove_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_025), ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_disco_items, 90), ejabberd_hooks:delete(disco_info, SubHost, ?MODULE, get_disco_info, 90), ejabberd_hooks:delete(disco_local_identity, SubHost, ?MODULE, get_disco_identity, 90), @@ -87,7 +83,7 @@ iq_handler(_From, _To, Acc, IQ = #iq{type = set, sub_el = SubEl}) -> iq_handler(_From, _To = #jid{lserver = SubHost}, Acc, IQ = #iq{type = get, sub_el = Request}) -> {ok, Host} = mongoose_subhosts:get_host(SubHost), Res = case parse_request(Request) of - {Filename, Size, ContentType, Namespace} -> + {Filename, Size, ContentType} -> MaxFileSize = max_file_size(Host), case MaxFileSize =:= undefined orelse Size =< MaxFileSize of true -> @@ -99,10 +95,10 @@ iq_handler(_From, _To = #jid{lserver = SubHost}, Acc, IQ = #iq{type = get, sub_e mod_http_upload_backend:create_slot(UTCDateTime, Token, Filename, ContentType, Size, Opts), - compose_iq_reply(IQ, Namespace, PutUrl, GetUrl, Headers); + compose_iq_reply(IQ, PutUrl, GetUrl, Headers); false -> - IQ#iq{type = error, sub_el = [file_too_large_error(MaxFileSize, Namespace)]} + IQ#iq{type = error, sub_el = [file_too_large_error(MaxFileSize)]} end; bad_request -> @@ -150,7 +146,7 @@ get_disco_items(Acc, _From, _To, _Node, _Lang) -> -spec get_disco_features(Acc :: term(), From :: jid:jid(), To :: jid:jid(), Node :: binary(), ejabberd:lang()) -> {result, [exml:element()]} | term(). get_disco_features({result, Nodes}, _From, _To, _Node = <<>>, _Lang) -> - {result, [?NS_HTTP_UPLOAD_025, ?NS_HTTP_UPLOAD_030 | Nodes]}; + {result, [?NS_HTTP_UPLOAD_030 | Nodes]}; get_disco_features(empty, From, To, Node, Lang) -> get_disco_features({result, []}, From, To, Node, Lang); get_disco_features(Acc, _From, _To, _Node, _Lang) -> @@ -165,8 +161,7 @@ get_disco_info(Acc, SubHost, _Mod, _Node = <<>>, _Lang) -> undefined -> Acc; MaxFileSize -> MaxFileSizeBin = integer_to_binary(MaxFileSize), - [get_disco_info_form(?NS_HTTP_UPLOAD_025, MaxFileSizeBin), - get_disco_info_form(?NS_HTTP_UPLOAD_030, MaxFileSizeBin) | Acc] + [get_disco_info_form(MaxFileSizeBin) | Acc] end; get_disco_info(Acc, _Host, _Mod, _Node, _Lang) -> Acc. @@ -185,16 +180,17 @@ my_disco_name(Lang) -> translate:translate(Lang, <<"HTTP File Upload">>). --spec compose_iq_reply(IQ :: jlib:iq(), Namespace :: binary(), - PutUrl :: binary(), GetUrl :: binary(), +-spec compose_iq_reply(IQ :: jlib:iq(), + PutUrl :: binary(), + GetUrl :: binary(), Headers :: #{binary() => binary()}) -> - Reply :: jlib:iq(). -compose_iq_reply(IQ, Namespace, PutUrl, GetUrl, Headers) -> + Reply :: jlib:iq(). +compose_iq_reply(IQ, PutUrl, GetUrl, Headers) -> Slot = #xmlel{ name = <<"slot">>, - attrs = [{<<"xmlns">>, Namespace}], - children = [create_url_xmlel(<<"put">>, PutUrl, Headers, Namespace), - create_url_xmlel(<<"get">>, GetUrl, #{}, Namespace)]}, + attrs = [{<<"xmlns">>, ?NS_HTTP_UPLOAD_030}], + children = [create_url_xmlel(<<"put">>, PutUrl, Headers), + create_url_xmlel(<<"get">>, GetUrl, #{})]}, IQ#iq{type = result, sub_el =[Slot]}. @@ -226,42 +222,35 @@ generate_token(Host) -> base16:encode(crypto:strong_rand_bytes(token_bytes(Host))). --spec file_too_large_error(MaxFileSize :: non_neg_integer(), Namespace :: binary()) -> exml:element(). -file_too_large_error(MaxFileSize, Namespace) -> +-spec file_too_large_error(MaxFileSize :: non_neg_integer()) -> exml:element(). +file_too_large_error(MaxFileSize) -> MaxFileSizeBin = integer_to_binary(MaxFileSize), MaxSizeEl = #xmlel{name = <<"max-file-size">>, children = [#xmlcdata{content = MaxFileSizeBin}]}, FileTooLargeEl = #xmlel{name = <<"file-too-large">>, - attrs = [{<<"xmlns">>, Namespace}], + attrs = [{<<"xmlns">>, ?NS_HTTP_UPLOAD_030}], children = [MaxSizeEl]}, Error0 = mongoose_xmpp_errors:not_acceptable(), Error0#xmlel{children = [FileTooLargeEl | Error0#xmlel.children]}. -spec parse_request(Request :: exml:element()) -> - {Filename :: binary(), Size :: integer(), - ContentType :: binary() | undefined, Namespace :: binary()} | - bad_request. + {Filename :: binary(), Size :: integer(), ContentType :: binary() | undefined} | bad_request. parse_request(Request) -> - Namespace = exml_query:attr(Request, <<"xmlns">>), Keys = [<<"filename">>, <<"size">>, <<"content-type">>], - [Filename, SizeBin, ContentType] = - case Namespace of - ?NS_HTTP_UPLOAD_025 -> [exml_query:path(Request, [{element, K}, cdata]) || K <- Keys]; - ?NS_HTTP_UPLOAD_030 -> [exml_query:attr(Request, K) || K <- Keys] - end, + [Filename, SizeBin, ContentType] = [exml_query:attr(Request, K) || K <- Keys], Size = (catch erlang:binary_to_integer(SizeBin)), case is_nonempty_binary(Filename) andalso is_positive_integer(Size) of false -> bad_request; - true -> {Filename, Size, ContentType, Namespace} + true -> {Filename, Size, ContentType} end. --spec get_disco_info_form(Namespace :: binary(), MaxFileSizeBin :: binary()) -> exml:element(). -get_disco_info_form(Namespace, MaxFileSizeBin) -> +-spec get_disco_info_form(MaxFileSizeBin :: binary()) -> exml:element(). +get_disco_info_form(MaxFileSizeBin) -> #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], - children = [jlib:form_field({<<"FORM_TYPE">>, <<"hidden">>, Namespace}), + children = [jlib:form_field({<<"FORM_TYPE">>, <<"hidden">>, ?NS_HTTP_UPLOAD_030}), jlib:form_field({<<"max-file-size">>, MaxFileSizeBin})]}. @@ -272,11 +261,9 @@ header_to_xmlel({Key, Value}) -> children = [#xmlcdata{content = Value}]}. --spec create_url_xmlel(Name :: binary(), Url :: binary(), Headers :: #{binary() => binary()}, - Namespace :: binary()) -> exml:element(). -create_url_xmlel(Name, Url, _Headers, ?NS_HTTP_UPLOAD_025) -> - #xmlel{name = Name, children = [#xmlcdata{content = Url}]}; -create_url_xmlel(Name, Url, Headers, ?NS_HTTP_UPLOAD_030) -> +-spec create_url_xmlel(Name :: binary(), Url :: binary(), Headers :: #{binary() => binary()}) -> + exml:element(). +create_url_xmlel(Name, Url, Headers) -> HeadersXml = [header_to_xmlel(H) || H <- maps:to_list(Headers)], #xmlel{name = Name, attrs = [{<<"url">>, Url}], children = HeadersXml}. @@ -293,3 +280,4 @@ is_positive_integer(_) -> false. config_metrics(Host) -> OptsToReport = [{backend, s3}], %list of tuples {option, defualt_value} mongoose_module_metrics:opts_for_module(Host, ?MODULE, OptsToReport). + From 726e11e7cf09c6f09cd3358488bd7f53f0c70af2 Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 21 Dec 2020 23:55:43 +0100 Subject: [PATCH 5/6] Update HTTP File Upload and migration docs about the removed version --- doc/migrations/4.0.1_4.x.x.md | 8 ++++++++ doc/modules/mod_http_upload.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 doc/migrations/4.0.1_4.x.x.md diff --git a/doc/migrations/4.0.1_4.x.x.md b/doc/migrations/4.0.1_4.x.x.md new file mode 100644 index 00000000000..eff708d517b --- /dev/null +++ b/doc/migrations/4.0.1_4.x.x.md @@ -0,0 +1,8 @@ +## HTTP File Upload + +[HTTP File Upload](https://xmpp.org/extensions/xep-0363.html) specification older than 0.3.0 is no longer supported, i.e. the one namespaced with `urn:xmpp:http:upload`. +Currently, only the `urn:xmpp:http:upload:0` XMLNS is served. + +All major, modern client libraries and applications support the 0.3.0+ specification. +If you experience any issues with making requests to the HTTP File Upload service, please update your client. + diff --git a/doc/modules/mod_http_upload.md b/doc/modules/mod_http_upload.md index 3212b255601..8c865652043 100644 --- a/doc/modules/mod_http_upload.md +++ b/doc/modules/mod_http_upload.md @@ -1,5 +1,5 @@ ## Module Description -This module implements [XEP-0363: HTTP File Upload](https://xmpp.org/extensions/xep-0363.html). +This module implements [XEP-0363: HTTP File Upload](https://xmpp.org/extensions/xep-0363.html), version 0.3.0+. It enables a service that on user request creates an upload "slot". A slot is a pair of URLs, one of which can be used with a `PUT` method to upload a user's file, the other with a `GET` method to retrieve such file. From bab8ed96f7c7a73082e3906f86cbcdbc1b14f9ff Mon Sep 17 00:00:00 2001 From: Piotr Nosek Date: Mon, 28 Dec 2020 17:57:22 +0100 Subject: [PATCH 6/6] [skip ci] Fix minor cosmetic issues --- src/http_upload/mod_http_upload.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/http_upload/mod_http_upload.erl b/src/http_upload/mod_http_upload.erl index 87e9ba8318f..2af6b797beb 100644 --- a/src/http_upload/mod_http_upload.erl +++ b/src/http_upload/mod_http_upload.erl @@ -278,6 +278,5 @@ is_positive_integer(X) when is_integer(X) -> X > 0; is_positive_integer(_) -> false. config_metrics(Host) -> - OptsToReport = [{backend, s3}], %list of tuples {option, defualt_value} + OptsToReport = [{backend, s3}], % list of tuples {option, default_value} mongoose_module_metrics:opts_for_module(Host, ?MODULE, OptsToReport). -