diff options
Diffstat (limited to 'lib/inets')
-rw-r--r-- | lib/inets/doc/src/http_client.xml | 29 | ||||
-rw-r--r-- | lib/inets/doc/src/inets.xml | 22 | ||||
-rw-r--r-- | lib/inets/src/http_client/httpc_handler.erl | 23 | ||||
-rw-r--r-- | lib/inets/src/http_client/httpc_manager.erl | 36 | ||||
-rw-r--r-- | lib/inets/src/inets_app/inets.erl | 18 | ||||
-rw-r--r-- | lib/inets/test/ftp_macosx_x86_test.erl | 6 | ||||
-rw-r--r-- | lib/inets/test/ftp_suite_lib.erl | 26 | ||||
-rw-r--r-- | lib/inets/test/httpc_SUITE.erl | 82 | ||||
-rw-r--r-- | lib/inets/vsn.mk | 95 |
9 files changed, 164 insertions, 173 deletions
diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml index 510c30eb35..ea8053cafa 100644 --- a/lib/inets/doc/src/http_client.xml +++ b/lib/inets/doc/src/http_client.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -56,8 +56,8 @@ <pre> [{inets, [{services, [{httpc, PropertyList}]}]}] </pre> - <p>For valid properties see <seealso - marker="http">http(3)</seealso></p> + <p>For valid properties see + <seealso marker="http">httpc(3)</seealso>. </p> </section> <section> @@ -71,67 +71,66 @@ but not for requests to localhost. This will apply to all subsequent requests</p> <code type="erl"> - 2 > http:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, + 2 > httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, ["localhost"]}}]). ok </code> <p>An ordinary synchronous request. </p> <code type="erl"> 3 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - http:request(get, {"http://www.erlang.org", []}, [], []). + httpc:request(get, {"http://www.erlang.org", []}, [], []). </code> <p>With all default values, as above, a get request can also be written like this.</p> <code type="erl"> 4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = - http:request("http://www.erlang.org"). + httpc:request("http://www.erlang.org"). </code> <p>An ordinary asynchronous request. The result will be sent to the calling process on the form {http, {ReqestId, Result}}</p> <code type="erl"> 5 > {ok, RequestId} = - http:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). + httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]). </code> <p>In this case the calling process is the shell, so we receive the result.</p> <code type="erl"> - 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. + 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end. ok </code> <p>Send a request with a specified connection header. </p> <code type="erl"> 7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} = - http:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, + httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]}, [], []). </code> <p>Start a HTTP client profile. </p> <code><![CDATA[ - 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]). + 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]). {ok, <0.45.0>} ]]></code> <p>The new profile has no proxy settings so the connection will be refused</p> <code type="erl"> - 9 > http:request("http://www.erlang.org", foo). - {error,econnrefused} + 9 > httpc:request("http://www.erlang.org", foo). + {error, econnrefused} </code> <p>Stop a HTTP client profile. </p> <code type="erl"> - 10 > inets:stop(httpc, foo). + 10 > inets:stop(httpc, foo). ok </code> <p>Alternatively:</p> <code type="erl"> - 10 > inets:stop(httpc, Pid). + 10 > inets:stop(httpc, Pid). ok </code> - </section> </chapter> diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml index 81dfe7e944..c367d7fa77 100644 --- a/lib/inets/doc/src/inets.xml +++ b/lib/inets/doc/src/inets.xml @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>inets</title> @@ -40,13 +40,13 @@ <title>COMMON DATA TYPES </title> <p>Type definitions that are used more than once in this module: </p> - <p><c> service() = ftpc | tfptd | httpc | httpd</c></p> + <p><c> service() = ftpc | tftp | httpc | httpd</c></p> <p><c> property() = atom() </c></p> </section> <funcs> <func> <name>services() -> [{Service, Pid}]</name> - <fsummary>Returns a list of currently running services. </fsummary> + <fsummary>Returns a list of currently running services. </fsummary> <type> <v>Service = service()</v> <v>Pid = pid()</v> @@ -97,7 +97,7 @@ <name>start(Type) -> ok | {error, Reason}</name> <fsummary>Starts the Inets application. </fsummary> <type> - <v>Type = permanent | transient | temporary</v> + <v>Type = permanent | transient | temporary</v> </type> <desc> <p>Starts the Inets application. Default type @@ -115,11 +115,9 @@ </func> <func> <name>start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name> - <name>start(Service, ServiceConfig, How) -> {ok, Pid} | - {error, Reason}</name> + <name>start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name> <fsummary>Dynamically starts an inets - service after the inets application has been - started. </fsummary> + service after the inets application has been started. </fsummary> <type> <v>Service = service()</v> <v>ServiceConfig = [{Option, Value}]</v> @@ -153,9 +151,9 @@ <fsummary>Stops a started service of the inets application or takes down a "stand_alone-service" gracefully.</fsummary> <type> - <v>Service = service() | stand_alone</v> + <v>Service = service() | stand_alone</v> <v>Reference = pid() | term() - service specified reference</v> - <v>Reason = term()</v> + <v>Reason = term()</v> </type> <desc> <p>Stops a started service of the inets application or takes @@ -169,7 +167,7 @@ <section> <title>SEE ALSO</title> <p><seealso marker="ftp">ftp(3)</seealso>, - <seealso marker="http">http(3)</seealso>, + <seealso marker="httpc">httpc(3)</seealso>, <seealso marker="httpd">httpd(3)</seealso>, <seealso marker="tftp">tftp(3)</seealso></p> </section> diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index c34b641b7b..8af6613fa2 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2002-2010. All Rights Reserved. -%% +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -605,24 +605,29 @@ handle_info({ssl_error, _, _} = Reason, State) -> %% Internally, to a request handling process, a request timeout is %% seen as a canceled request. handle_info({timeout, RequestId}, - #state{request = #request{id = RequestId} = Request, - canceled = Canceled} = State) -> + #state{request = #request{id = RequestId} = Request, + canceled = Canceled, + profile_name = ProfileName} = State) -> ?hcri("timeout of current request", [{id, RequestId}]), httpc_response:send(Request#request.from, httpc_response:error(Request, timeout)), + httpc_manager:request_done(RequestId, ProfileName), ?hcrv("response (timeout) sent - now terminate", []), {stop, normal, State#state{request = Request#request{from = answer_sent}, canceled = [RequestId | Canceled]}}; -handle_info({timeout, RequestId}, #state{canceled = Canceled} = State) -> +handle_info({timeout, RequestId}, + #state{canceled = Canceled, + profile_name = ProfileName} = State) -> ?hcri("timeout", [{id, RequestId}]), Filter = fun(#request{id = Id, from = From} = Request) when Id =:= RequestId -> ?hcrv("found request", [{id, Id}, {from, From}]), %% Notify the owner - Response = httpc_response:error(Request, timeout), - httpc_response:send(From, Response), + httpc_response:send(From, + httpc_response:error(Request, timeout)), + httpc_manager:request_done(RequestId, ProfileName), ?hcrv("response (timeout) sent", []), [Request#request{from = answer_sent}]; (_) -> diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index d5d6376369..1e1bde220b 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2002-2010. All Rights Reserved. -%% +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -66,15 +66,6 @@ state % State of the handler: initiating | started | operational | canceled }). -%% Entries in the handler / request cross-ref table -%% -record(request_info, -%% { -%% id, % Id of the request -%% handler, % Pid of the handler process -%% from, % The From value for the caller -%% mref % Monitor ref for the caller -%% }). - %%==================================================================== %% Internal Application API @@ -577,7 +568,9 @@ handle_info({'EXIT', Pid, Reason}, #state{handler_db = HandlerDb} = State) -> handle_info({'DOWN', _, _, Pid, _}, State) -> %% - %% Check what happens to waiting requests! Chall we not send a reply? + %% Normally this should have been cleaned up already + %% (when receiving {request_done, PequestId}), but + %% just in case there is a glitch, cleanup anyway. %% Pattern = #handler_info{handler = Pid, _ = '_'}, @@ -649,7 +642,16 @@ get_handler_info(Tab) -> Acc end, Handlers2 = lists:foldl(F, [], Handlers1), - Handlers3 = [{Pid, State, httpc_handler:info(Pid)} || + Handlers3 = [{Pid, State, + case (catch httpc_handler:info(Pid)) of + {'EXIT', _} -> + %% Why would this crash? + %% Only if the process has died, but we don't + %% know about it? + []; + Else -> + Else + end} || {Pid, State} <- Handlers2], Handlers3. @@ -666,6 +668,10 @@ handle_started(StarterPid, ReqId, HandlerPid, case ets:lookup(HandlerDb, ReqId) of [#handler_info{state = initiating} = HandlerInfo] -> ?hcri("received started ack for initiating handler", []), + %% As a last resort, make sure we know when it exits, + %% in case it forgets to notify us. + %% We dont need to know the ref id? + erlang:monitor(process, HandlerPid), HandlerInfo2 = HandlerInfo#handler_info{handler = HandlerPid, state = started}, ets:insert(HandlerDb, HandlerInfo2), diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl index f1fa5fd997..054468e445 100644 --- a/lib/inets/src/inets_app/inets.erl +++ b/lib/inets/src/inets_app/inets.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2006-2010. All Rights Reserved. -%% +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -57,7 +57,7 @@ start(Type) -> %% Function: start(Service, ServiceConfig [, How]) -> {ok, Pid} | %% {error, Reason} %% -%% Service = - ftpc | tftpd | httpc | httpd +%% Service = - ftpc | tftpd | tftpc | tftp | httpc | httpd %% ServiceConfig = ConfPropList | ConfFile %% ConfPropList = [{Property, Value}] according to service %% ConfFile = Path - when service is httpd @@ -100,7 +100,7 @@ stop() -> %%-------------------------------------------------------------------- %% Function: stop(Service, Pid) -> ok %% -%% Service - ftp | tftpd | http | httpd | stand_alone +%% Service - ftpc | ftp | tftpd | tftpc | tftp | httpc | httpd | stand_alone %% %% Description: Stops a started service of the inets application or takes %% down a stand alone "service" gracefully. @@ -382,7 +382,7 @@ key1search(Key, Vals, Def) -> %% Description: Returns a list of supported services %%------------------------------------------------------------------- service_names() -> - [ftpc, tftpd, httpc, httpd]. + [ftpc, tftp, httpc, httpd]. %%----------------------------------------------------------------- @@ -725,8 +725,8 @@ call_service(Service, Call, Args) -> service_module(tftpd) -> tftp; -service_module(httpc) -> - httpc; +service_module(tftpc) -> + tftp; service_module(ftpc) -> ftp; service_module(Service) -> diff --git a/lib/inets/test/ftp_macosx_x86_test.erl b/lib/inets/test/ftp_macosx_x86_test.erl index c59a992421..5566d4feaa 100644 --- a/lib/inets/test/ftp_macosx_x86_test.erl +++ b/lib/inets/test/ftp_macosx_x86_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2010. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -108,7 +108,7 @@ passive_pwd(X) -> ?LIB_MOD:passive_pwd(X). passive_cd(X) -> ?LIB_MOD:passive_cd(X). passive_lcd(X) -> ?LIB_MOD:passive_lcd(X). passive_ls(X) -> ?LIB_MOD:passive_ls(X). -passive_nlist(X) -> ?LIB_MOD:passive_nlist(X). +passive_nlist(X) -> ?LIB_MOD:passive_nlist([{wildcard_support, false} | X]). passive_rename(X) -> ?LIB_MOD:passive_rename(X). passive_delete(X) -> ?LIB_MOD:passive_delete(X). passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X). @@ -129,7 +129,7 @@ active_pwd(X) -> ?LIB_MOD:active_pwd(X). active_cd(X) -> ?LIB_MOD:active_cd(X). active_lcd(X) -> ?LIB_MOD:active_lcd(X). active_ls(X) -> ?LIB_MOD:active_ls(X). -active_nlist(X) -> ?LIB_MOD:active_nlist(X). +active_nlist(X) -> ?LIB_MOD:active_nlist([{wildcard_support, false} | X]). active_rename(X) -> ?LIB_MOD:active_rename(X). active_delete(X) -> ?LIB_MOD:active_delete(X). active_mkdir(X) -> ?LIB_MOD:active_mkdir(X). diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl index 5e27bc3a86..c539b7c17c 100644 --- a/lib/inets/test/ftp_suite_lib.erl +++ b/lib/inets/test/ftp_suite_lib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2005-2010. All Rights Reserved. -%% +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -508,7 +508,8 @@ passive_nlist(suite) -> []; passive_nlist(Config) when is_list(Config) -> Pid = ?config(ftp, Config), - do_nlist(Pid). + WildcardSupport = ?config(wildcard_support, Config), + do_nlist(Pid, WildcardSupport). %%------------------------------------------------------------------------- @@ -768,7 +769,8 @@ active_nlist(suite) -> []; active_nlist(Config) when is_list(Config) -> Pid = ?config(ftp, Config), - do_nlist(Pid). + WildcardSupport = ?config(wildcard_support, Config), + do_nlist(Pid, WildcardSupport). %%------------------------------------------------------------------------- @@ -1242,16 +1244,20 @@ do_ls(Pid) -> {ok, _} = ftp:ls(Pid, "incom*"), ok. -do_nlist(Pid) -> +do_nlist(Pid, WildcardSupport) -> {ok, _} = ftp:nlist(Pid), {ok, _} = ftp:nlist(Pid, "incoming"), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group %% of files (including wildcards). - {ok, _} = ftp:nlist(Pid, "incom*"), -%% {error, epath} = ftp:nlist(Pid, ?BAD_DIR), - ok. + case WildcardSupport of + true -> + {ok, _} = ftp:nlist(Pid, "incom*"), + ok; + _ -> + ok + end. do_rename(Pid, Config) -> PrivDir = ?config(priv_dir, Config), diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index b5fd896001..902e440c80 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% +%% %% Copyright Ericsson AB 2004-2010. All Rights Reserved. -%% +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% @@ -306,7 +306,8 @@ tickets(suite) -> otp_8106, otp_8056, otp_8352, - otp_8371 + otp_8371, + otp_8739 ]. @@ -2561,7 +2562,78 @@ otp_8371(Config) when is_list(Config) -> ok. +%%------------------------------------------------------------------------- +otp_8739(doc) -> + ["OTP-8739"]; +otp_8739(suite) -> + []; +otp_8739(Config) when is_list(Config) -> + {_DummyServerPid, Port} = otp_8739_dummy_server(), + URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html", + Method = get, + Request = {URL, []}, + HttpOptions = [{connect_timeout, 500}, {timeout, 1}], + Options = [{sync, true}], + case http:request(Method, Request, HttpOptions, Options) of + {error, timeout} -> + %% And now we check the size of the handler db + Info = httpc:info(), + tsp("Info: ~p", [Info]), + {value, {handlers, Handlers}} = + lists:keysearch(handlers, 1, Info), + case Handlers of + [] -> + ok; + _ -> + tsf({unexpected_handlers, Handlers}) + end; + Unexpected -> + tsf({unexpected, Unexpected}) + end. + + +otp_8739_dummy_server() -> + Parent = self(), + Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end), + receive + {port, Port} -> + {Pid, Port} + end. + +otp_8739_dummy_server_init(Parent) -> + {ok, ListenSocket} = + gen_tcp:listen(0, [binary, inet, {packet, 0}, + {reuseaddr,true}, + {active, false}]), + {ok, Port} = inet:port(ListenSocket), + Parent ! {port, Port}, + otp_8739_dummy_server_main(Parent, ListenSocket). + +otp_8739_dummy_server_main(Parent, ListenSocket) -> + case gen_tcp:accept(ListenSocket) of + {ok, Sock} -> + %% Ignore the request, and simply wait for the socket to close + receive + {tcp_closed, Sock} -> + (catch gen_tcp:close(ListenSocket)), + exit(normal); + {tcp_error, Sock, Reason} -> + tsp("socket error: ~p", [Reason]), + (catch gen_tcp:close(ListenSocket)), + exit(normal) + after 10000 -> + %% Just in case + (catch gen_tcp:close(Sock)), + (catch gen_tcp:close(ListenSocket)), + exit(timeout) + end; + Error -> + exit(Error) + end. + + + %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 57c87e7036..ea6f4c9903 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -21,98 +21,3 @@ APPLICATION = inets INETS_VSN = 5.4 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" - -TICKETS = OTP-7907 OTP-8564 OTP-8573 - -TICKETS_5_3_3 = \ - OTP-8609 \ - OTP-8610 \ - OTP-8624 - -TICKETS_5_3_2 = \ - OTP-8542 \ - OTP-8607 - -TICKETS_5_3_1 = \ - OTP-8508 \ - OTP-8509 - -TICKETS_5_3 = \ - OTP-8016 \ - OTP-8056 \ - OTP-8103 \ - OTP-8106 \ - OTP-8312 \ - OTP-8315 \ - OTP-8327 \ - OTP-8349 \ - OTP-8351 \ - OTP-8352 \ - OTP-8359 \ - OTP-8371 - -TICKETS_5_2 = \ - OTP-8204 \ - OTP-8206 \ - OTP-8247 \ - OTP-8248 \ - OTP-8249 \ - OTP-8258 \ - OTP-8280 - -TICKETS_5_1_3 = OTP-8154 - -TICKETS_5_1_2 = OTP-7298 OTP-8101 OTP-8118 - -TICKETS_5_1_1 = OTP-8052 OTP-8069 - -TICKETS_5_1 = OTP-7994 OTP-7998 OTP-8001 OTP-8004 OTP-8005 - -TICKETS_5_0_14 = OTP-7882 OTP-7883 OTP-7888 OTP-7950 OTP-7976 - -TICKETS_5.0.13 = \ - OTP-7723 \ - OTP-7724 \ - OTP-7726 \ - OTP-7463 \ - OTP-7815 \ - OTP-7857 - -# TICKETS_5.0.12 = \ -# OTP-7636 -# -# TICKETS_5.0.11 = \ -# OTP-7574 \ -# OTP-7597 \ -# OTP-7598 \ -# OTP-7605 -# -# TICKETS_5.0.10 = \ -# OTP-7450 \ -# OTP-7454 \ -# OTP-7490 \ -# OTP-7512 -# -# TICKETS_5.0.9 = \ -# OTP-7257 \ -# OTP-7323 \ -# OTP-7341 -# -# TICKETS_5.0.8 = \ -# OTP-7315 \ -# OTP-7321 -# -# TICKETS_5.0.7 = \ -# OTP-7304 -# -# TICKETS_5.0.6 = \ -# OTP-7266 -# -# TICKETS_5.0.5 = \ -# OTP-7220 \ -# OTP-7221 -# -# TICKETS_5.0.4 = \ -# OTP-7173 -# - |