Subject: [alpine-aports] [PATCH] community/erlang: upgrade to 18.3.4

From: Marlus Saraiva <[email-masked]>
Date: Sun, 19 Jun 2016 22:46:29 +0000

---
 .../erlang/0080-otp-update-version-18.3.4.patch    | 2964 ++++++++++++++++++++
 community/erlang/APKBUILD                          |   14 +-
 2 files changed, 2973 insertions(+), 5 deletions(-)
 create mode 100644 community/erlang/0080-otp-update-version-18.3.4.patch

diff --git a/community/erlang/0080-otp-update-version-18.3.4.patch b/community/erlang/0080-otp-update-version-18.3.4.patch
new file mode 100644
index 0000000..cd669f0
--- /dev/null
+++ b/community/erlang/0080-otp-update-version-18.3.4.patch
@@ -0,0 +1,2964 @@
+--- a/OTP_VERSION
++++ b/OTP_VERSION
+@@ -1 +1 @@
+-18.3.2
++18.3.4
+--- a/lib/common_test/doc/src/ct.xml
++++ b/lib/common_test/doc/src/ct.xml
+@@ -601,18 +601,21 @@
+     </func>
+ 
+     <func>
+-      <name>get_timetrap_info() -&gt; {Time, Scale}</name>
++      <name>get_timetrap_info() -&gt; {Time, {Scaling,ScaleVal}}</name>
+       <fsummary>Reads information about the timetrap set for the current
+         test case.</fsummary>
+       <type>
+         <v>Time = integer() | infinity</v>
+-        <v>Scale = true | false</v>
++        <v>Scaling = true | false</v>
++        <v>ScaleVal = integer()</v>
+       </type>
+      <desc><marker id="get_timetrap_info-0"/>
+         <p>Reads information about the timetrap set for the current test
+-          case. <c>Scale</c> indicates if <c>Common Test</c> will attempt
++          case. <c>Scaling</c> indicates if <c>Common Test</c> will attempt
+           to compensate timetraps automatically for runtime delays
+-          introduced by, for example, tools like cover.</p>
++          introduced by, for example, tools like cover. <c>ScaleVal</c> is
++	  the value of the current scaling multipler (always 1 if scaling is
++	  disabled). Note the <c>Time</c> is not the scaled result.</p>
+       </desc>
+     </func>
+ 
+@@ -1136,7 +1139,7 @@
+         Opts.</fsummary>
+       <type>
+         <v>Opts = [OptTuples]</v>
+-        <v>OptTuples = {dir, TestDirs} | {suite, Suites} | {group, Groups} | {testcase, Cases} | {spec, TestSpecs} | {join_specs, Bool} | {label, Label} | {config, CfgFiles} | {userconfig, UserConfig} | {allow_user_terms, Bool} | {logdir, LogDir} | {silent_connections, Conns} | {stylesheet, CSSFile} | {cover, CoverSpecFile} | {cover_stop, Bool} | {step, StepOpts} | {event_handler, EventHandlers} | {include, InclDirs} | {auto_compile, Bool} | {abort_if_missing_suites, Bool} | {create_priv_dir, CreatePrivDir} | {multiply_timetraps, M} | {scale_timetraps, Bool} | {repeat, N} | {duration, DurTime} | {until, StopTime} | {force_stop, ForceStop} | {decrypt, DecryptKeyOrFile} | {refresh_logs, LogDir} | {logopts, LogOpts} | {verbosity, VLevels} | {basic_html, Bool} | {ct_hooks, CTHs} | {enable_builtin_hooks, Bool} | {release_shell, Bool}</v>
++        <v>OptTuples = {dir, TestDirs} | {suite, Suites} | {group, Groups} | {testcase, Cases} | {spec, TestSpecs} | {join_specs, Bool} | {label, Label} | {config, CfgFiles} | {userconfig, UserConfig} | {allow_user_terms, Bool} | {logdir, LogDir} | {silent_connections, Conns} | {stylesheet, CSSFile} | {cover, CoverSpecFile} | {cover_stop, Bool} | {step, StepOpts} | {event_handler, EventHandlers} | {include, InclDirs} | {auto_compile, Bool} | {abort_if_missing_suites, Bool} | {create_priv_dir, CreatePrivDir} | {multiply_timetraps, M} | {scale_timetraps, Bool} | {repeat, N} | {duration, DurTime} | {until, StopTime} | {force_stop, ForceStop} | {decrypt, DecryptKeyOrFile} | {refresh_logs, LogDir} | {logopts, LogOpts} | {verbosity, VLevels} | {basic_html, Bool} | {esc_chars, Bool} | {ct_hooks, CTHs} | {enable_builtin_hooks, Bool} | {release_shell, Bool}</v>
+         <v>TestDirs = [string()] | string()</v>
+         <v>Suites = [string()] | [atom()] | string() | atom()</v>
+         <v>Cases = [atom()] | atom()</v>
+--- a/lib/common_test/doc/src/ct_run.xml
++++ b/lib/common_test/doc/src/ct_run.xml
+@@ -124,6 +124,7 @@
+   [-duration HHMMSS [-force_stop [skip_rest]]] |
+   [-until [YYMoMoDD]HHMMSS [-force_stop [skip_rest]]]
+   [-basic_html]
++  [-no_esc_chars]
+   [-ct_hooks CTHModule1 CTHOpts1 and CTHModule2 CTHOpts2 and ..
+    CTHModuleN CTHOptsN]
+   [-exit_status ignore_config]
+@@ -162,6 +163,7 @@
+   [-duration HHMMSS [-force_stop [skip_rest]]] |
+   [-until [YYMoMoDD]HHMMSS [-force_stop [skip_rest]]]
+   [-basic_html]
++  [-no_esc_chars]
+   [-ct_hooks CTHModule1 CTHOpts1 and CTHModule2 CTHOpts2 and ..
+    CTHModuleN CTHOptsN]
+   [-exit_status ignore_config]</pre>
+@@ -186,7 +188,8 @@
+   [-muliply_timetraps Multiplier]
+   [-scale_timetraps]
+   [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]
+-  [-basic_html]</pre>
++  [-basic_html]
++  [-no_esc_chars]</pre>
+   </section>
+ 
+   <section>
+--- a/lib/common_test/doc/src/ct_telnet.xml
++++ b/lib/common_test/doc/src/ct_telnet.xml
+@@ -64,6 +64,8 @@
+         remaining string terminated) = 0</p></item>
+       <item><p>Polling interval (sleep time between polls) = 1 second</p>
+       </item>
++      <item><p>The TCP_NODELAY option for the telnet socket
++        is disabled (set to <c>false</c>) per default</p></item>
+     </list>
+ 
+     <p>These parameters can be modified by the user with the following
+@@ -76,7 +78,8 @@
+                     {reconnection_interval,Millisec},
+                     {keep_alive,Bool},
+                     {poll_limit,N},
+-                    {poll_interval,Millisec}]}.</pre>
++                    {poll_interval,Millisec},
++                    {tcp_nodelay,Bool}]}.</pre>
+ 
+     <p><c>Millisec = integer(), N = integer()</c></p>
+ 
+--- a/lib/common_test/doc/src/notes.xml
++++ b/lib/common_test/doc/src/notes.xml
+@@ -33,6 +33,68 @@
+     <file>notes.xml</file>
+     </header>
+ 
++<section><title>Common_Test 1.12.1</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    The <c>nodelay</c> option used to be enabled
++	    (<c>true</c>) by default for sockets opened by the Common
++	    Test telnet client. This appeared to cause communication
++	    problems with telnet servers on some systems, and
++	    therefore the option is no longer used. Its value may
++	    instead be specified in the telnet connection settings.
++	    See the man page for <c>ct_telnet</c> for details. Please
++	    note that the interface function <c>connect</c> in
++	    <c>unix_telnet</c> has been updated with an extra
++	    argument and is now <c>unix_telnet:connect/7</c>.</p>
++          <p>
++	    Own Id: OTP-13462 Aux Id: seq13077 </p>
++        </item>
++        <item>
++          <p>
++	    Fix bug in cth_surefire: When a pre_init_per_suite hook
++	    fails before reaching the
++	    cth_surefire:pre_init_per_suite, cth_surefire produced
++	    incorrect XML.</p>
++          <p>
++	    Own Id: OTP-13513</p>
++        </item>
++        <item>
++          <p>
++	    The <c>ct:get_timetrap_info/0</c> function has been
++	    updated to return more information about timetrap
++	    scaling.</p>
++          <p>
++	    Own Id: OTP-13535</p>
++        </item>
++        <item>
++          <p>
++	    A problem with stylesheet HTML tags getting incorrectly
++	    escaped by Common Test has been corrected.</p>
++          <p>
++	    Own Id: OTP-13536</p>
++        </item>
++        <item>
++          <p>
++	    The <c>ct_run</c> start flag <c>-no_esc_chars</c> and
++	    <c>ct:run_test/1</c> start option <c>{esc_chars,Bool}</c>
++	    have been introduced to make it possible to disable
++	    automatic escaping of characters. Automatic escaping of
++	    special HTML characters printed with <c>io:format/1,2</c>
++	    and <c>ct:pal/1,2,3,4</c> was introduced in Common Test
++	    1.12. The new flag/option may be used to disable this
++	    feature for backwards compatibility reasons. (The option
++	    is also supported in test specifications).</p>
++          <p>
++	    Own Id: OTP-13537</p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>Common_Test 1.12</title>
+ 
+     <section><title>Fixed Bugs and Malfunctions</title>
+--- a/lib/common_test/doc/src/run_test_chapter.xml
++++ b/lib/common_test/doc/src/run_test_chapter.xml
+@@ -266,6 +266,10 @@
+       <tag><c><![CDATA[-verbosity <levels>]]></c></tag>
+       <item><p>Sets <seealso marker="write_test_chapter#logging">verbosity levels
+       for printouts</seealso>.</p></item>
++
++      <tag><c><![CDATA[-no_esc_chars]]></c></tag>
++      <item><p>Disables automatic escaping of special HTML characters.
++      See the <seealso marker="write_test_chapter#logging">Logging chapter</seealso>.</p></item>
+     </taglist>
+ 
+     <note><p>Directories passed to <c>Common Test</c> can have either relative or absolute paths.</p></note>
+@@ -802,7 +806,7 @@
+ 	program</seealso> for an overview of available start flags
+ 	(as most flags have a corresponding configuration term)</item>
+        <item><seealso marker="write_test_chapter#logging">Logging</seealso>
+-	(for terms <c>verbosity</c>, <c>stylesheet</c> and <c>basic_html</c>)</item>
++	(for terms <c>verbosity</c>, <c>stylesheet</c>, <c>basic_html</c> and <c>esc_chars</c>)</item>
+        <item><seealso marker="config_file_chapter#top">External Configuration Data</seealso>
+ 	(for terms <c>config</c> and <c>userconfig</c>)</item>
+        <item><seealso marker="event_handler_chapter#event_handling">Event
+@@ -887,6 +891,9 @@
+  {basic_html, Bool}.
+  {basic_html, NodeRefs, Bool}.
+ 
++ {esc_chars, Bool}.
++ {esc_chars, NodeRefs, Bool}.
++
+  {release_shell, Bool}.</pre>
+ 	
+       <p><em>Test terms:</em></p>
+--- a/lib/common_test/doc/src/unix_telnet.xml
++++ b/lib/common_test/doc/src/unix_telnet.xml
+@@ -80,7 +80,7 @@
+ 
+   <funcs>
+     <func>
+-      <name>connect(ConnName, Ip, Port, Timeout, KeepAlive, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
++      <name>connect(ConnName, Ip, Port, Timeout, KeepAlive, TCPNoDelay, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
+       <fsummary>Callback for ct_telnet.erl.</fsummary>
+         <type>
+           <v>ConnName = target_name()</v>
+@@ -88,6 +88,7 @@
+           <v>Port = integer()</v>
+           <v>Timeout = integer()</v>
+           <v>KeepAlive = bool()</v>
++	  <v>TCPNoDelay = bool()</v>
+           <v>Extra = target_name() | {Username, Password}</v>
+           <v>Username = string()</v>
+           <v>Password = string()</v>
+--- a/lib/common_test/doc/src/write_test_chapter.xml
++++ b/lib/common_test/doc/src/write_test_chapter.xml
+@@ -1047,9 +1047,15 @@
+     
+     <p>Common Test will escape special HTML characters (&lt;, &gt; and &amp;) in printouts
+     to the log file made with <c>ct:pal/4</c> and <c>io:format/2</c>. In order to print
+-    strings with HTML tags to the log, use the <c>ct:log/5</c> function. The character escaping
+-    feature is per default disabled for <c>ct:log/5</c>, but can be enabled with the
+-    <c>esc_chars</c> option.</p>
++    strings with HTML tags to the log, use the <c>ct:log/3,4,5</c> function. The character
++    escaping feature is per default disabled for <c>ct:log/3,4,5</c> but can be enabled with
++    the <c>esc_chars</c> option in the <c>Opts</c> list, see <seealso marker="ct#log-5">
++    <c>ct:log/3,4,5</c></seealso>.</p>
++
++    <p>If the character escaping feature needs to be disabled (typically for backwards
++    compatibility reasons), use the <c>ct_run</c> start flag <c>-no_esc_chars</c>, or the
++    <c>ct:run_test/1</c> start option <c>{esc_chars,Bool}</c> (this start option is also
++    supported in test specifications).</p>
+ 
+     <p>For more information about log files, see section
+     <seealso marker="run_test_chapter#log_files">Log Files</seealso> 
+--- a/lib/common_test/src/ct.erl
++++ b/lib/common_test/src/ct.erl
+@@ -161,9 +161,9 @@ run(TestDirs) ->
+ %%%               {repeat,N} | {duration,DurTime} | {until,StopTime} |
+ %%%               {force_stop,ForceStop} | {decrypt,DecryptKeyOrFile} |
+ %%%               {refresh_logs,LogDir} | {logopts,LogOpts} | 
+-%%%               {verbosity,VLevels} | {basic_html,Bool} | 
+-%%%               {ct_hooks, CTHs} | {enable_builtin_hooks,Bool} |
+-%%%               {release_shell,Bool}
++%%%               {verbosity,VLevels} | {basic_html,Bool} |
++%%%               {esc_chars,Bool} | {ct_hooks, CTHs} |
++%%%               {enable_builtin_hooks,Bool} | {release_shell,Bool}
+ %%%   TestDirs = [string()] | string()
+ %%%   Suites = [string()] | [atom()] | string() | atom()
+ %%%   Cases = [atom()] | atom()
+--- a/lib/common_test/src/ct_groups.erl
++++ b/lib/common_test/src/ct_groups.erl
+@@ -325,7 +325,7 @@ modify_tc_list1(GrSpecTs, TSCs) ->
+ 		      true ->
+ 			  {[TC|TSCs1],lists:delete(TC,GrSpecTs2)};
+ 		      false ->
+-			  case lists:keymember(TC, 2, GrSpecTs) of
++			  case lists:keysearch(TC, 2, GrSpecTs) of
+ 			      {value,Test} ->
+ 				  {[Test|TSCs1],
+ 				   lists:keydelete(TC, 2, GrSpecTs2)};
+--- a/lib/common_test/src/ct_hooks.erl
++++ b/lib/common_test/src/ct_hooks.erl
+@@ -67,6 +67,8 @@ terminate(Hooks) ->
+ %% tests.
+ -spec init_tc(Mod :: atom(),
+ 	      FuncSpec :: atom() | 
++			  {ConfigFunc :: init_per_testcase | end_per_testcase,
++			   TestCase :: atom()} |
+ 			  {ConfigFunc :: init_per_group | end_per_group,
+ 			   GroupName :: atom(),
+ 			   Properties :: list()},
+@@ -103,7 +105,9 @@ init_tc(_Mod, TC = error_in_suite, Config) ->
+ %% @doc Called as each test case is completed. This includes all configuration
+ %% tests.
+ -spec end_tc(Mod :: atom(),
+-	     FuncSpec :: atom() | 
++	     FuncSpec :: atom() |  
++			 {ConfigFunc :: init_per_testcase | end_per_testcase,
++			  TestCase :: atom()} |
+ 			 {ConfigFunc :: init_per_group | end_per_group,
+ 			  GroupName :: atom(),
+ 			  Properties :: list()},
+--- a/lib/common_test/src/ct_logs.erl
++++ b/lib/common_test/src/ct_logs.erl
+@@ -609,7 +609,8 @@ log_timestamp({MS,S,US}) ->
+ 		      ct_log_fd,
+ 		      tc_groupleaders,
+ 		      stylesheet,
+-		      async_print_jobs}).
++		      async_print_jobs,
++		      tc_esc_chars}).
+ 
+ logger(Parent, Mode, Verbosity) ->
+     register(?MODULE,self()),
+@@ -728,14 +729,18 @@ logger(Parent, Mode, Verbosity) ->
+ 	   end
+      end || {Cat,VLvl} <- Verbosity],
+     io:nl(CtLogFd),
+-
++    TcEscChars = case application:get_env(common_test, esc_chars) of
++		   {ok,ECBool} -> ECBool;
++		   _           -> true
++	       end,
+     logger_loop(#logger_state{parent=Parent,
+ 			      log_dir=AbsDir,
+ 			      start_time=Time,
+ 			      orig_GL=group_leader(),
+ 			      ct_log_fd=CtLogFd,
+ 			      tc_groupleaders=[],
+-			      async_print_jobs=[]}).
++			      async_print_jobs=[],
++			      tc_esc_chars=TcEscChars}).
+ 
+ copy_priv_files([SrcF | SrcFs], [DestF | DestFs]) ->
+     case file:copy(SrcF, DestF) of
+@@ -761,20 +766,21 @@ logger_loop(State) ->
+ 		end,
+ 	    if Importance >= (100-VLvl) ->
+ 		    CtLogFd = State#logger_state.ct_log_fd,
++		    DoEscChars = State#logger_state.tc_esc_chars and EscChars,
+ 		    case get_groupleader(Pid, GL, State) of
+ 			{tc_log,TCGL,TCGLs} ->
+ 			    case erlang:is_process_alive(TCGL) of
+ 				true ->
+ 				    State1 = print_to_log(SyncOrAsync, Pid,
+ 							  Category, TCGL, Content,
+-							  EscChars, State),
++							  DoEscChars, State),
+ 				    logger_loop(State1#logger_state{
+ 						  tc_groupleaders = TCGLs});
+ 				false ->
+ 				    %% Group leader is dead, so write to the
+ 				    %% CtLog or unexpected_io log instead
+ 				    unexpected_io(Pid, Category, Importance,
+-						  Content, CtLogFd, EscChars),
++						  Content, CtLogFd, DoEscChars),
+ 
+ 				    logger_loop(State)			    
+ 			    end;
+@@ -783,7 +789,7 @@ logger_loop(State) ->
+ 			    %% to ct_log, else write to unexpected_io
+ 			    %% log
+ 			    unexpected_io(Pid, Category, Importance, Content,
+-					  CtLogFd, EscChars),
++					  CtLogFd, DoEscChars),
+ 			    logger_loop(State#logger_state{
+ 					  tc_groupleaders = TCGLs})
+ 		    end;
+@@ -794,7 +800,7 @@ logger_loop(State) ->
+ 	    %% make sure no IO for this test case from the
+ 	    %% CT logger gets rejected
+ 	    test_server:permit_io(GL, self()),
+-	    print_style(GL, State#logger_state.stylesheet),
++	    print_style(GL,GL,State#logger_state.stylesheet),
+ 	    set_evmgr_gl(GL),
+ 	    TCGLs = add_tc_gl(TCPid,GL,State),
+ 	    if not RefreshLog ->
+@@ -882,7 +888,7 @@ create_io_fun(FromPid, CtLogFd, EscChars) ->
+ 		    {_HdOrFt,S,A} -> {false,S,A};
+ 		    {S,A}         -> {true,S,A}
+ 		end,
+-	    try io_lib:format(Str,Args) of
++	    try io_lib:format(Str, Args) of
+ 		IoStr when Escapable, EscChars, IoList == [] ->
+ 		    escape_chars(IoStr);
+ 		IoStr when Escapable, EscChars ->
+@@ -925,7 +931,12 @@ print_to_log(sync, FromPid, Category, TCGL, Content, EscChars, State) ->
+     if FromPid /= TCGL ->
+ 	    IoFun = create_io_fun(FromPid, CtLogFd, EscChars),
+ 	    IoList = lists:foldl(IoFun, [], Content),
+-	    io:format(TCGL,["$tc_html","~ts"], [IoList]);
++	    try io:format(TCGL,["$tc_html","~ts"], [IoList]) of
++		ok -> ok
++	    catch
++		_:_ ->
++		    io:format(TCGL,"~ts", [IoList])
++	    end;
+        true ->
+ 	    unexpected_io(FromPid, Category, ?MAX_IMPORTANCE, Content,
+ 			  CtLogFd, EscChars)
+@@ -958,7 +969,10 @@ print_to_log(async, FromPid, Category, TCGL, Content, EscChars, State) ->
+ 				    _:terminated ->
+ 					unexpected_io(FromPid, Category,
+ 						      ?MAX_IMPORTANCE,
+-						      Content, CtLogFd, EscChars)
++						      Content, CtLogFd, EscChars);
++				    _:_ ->
++					io:format(TCGL, "~ts",
++						  [lists:foldl(IoFun,[],Content)])
+ 				end;
+ 			    false ->
+ 				unexpected_io(FromPid, Category,
+@@ -1099,26 +1113,27 @@ open_ctlog(MiscIoName) ->
+ 	      "View I/O logged after the test run</a></li>\n</ul>\n",
+ 	      [MiscIoName,MiscIoName]),
+ 
+-    print_style(Fd,undefined),
++    print_style(Fd,group_leader(),undefined),
+     io:format(Fd, 
+ 	      xhtml("<br><h2>Progress Log</h2>\n<pre>\n",
+ 		    "<br />\n<h4>PROGRESS LOG</h4>\n<pre>\n"), []),
+     Fd.
+ 
+-print_style(Fd,undefined) ->
++print_style(Fd,GL,undefined) ->
+     case basic_html() of
+ 	true ->
+-	    io:format(Fd,
+-		      "<style>\n"
+-		      "div.ct_internal { background:lightgrey; color:black; }\n"
+-		      "div.default     { background:lightgreen; color:black; }\n"
+-		      "</style>\n",
+-		      []);
++	    Style = "<style>\n
++		div.ct_internal { background:lightgrey; color:black; }\n
++		div.default     { background:lightgreen; color:black; }\n
++		</style>\n",
++	    if Fd == GL -> io:format(["$tc_html",Style], []);
++	       true     -> io:format(Fd, Style, [])
++	    end;
+ 	_ ->
+ 	    ok
+     end;
+ 
+-print_style(Fd,StyleSheet) ->
++print_style(Fd,GL,StyleSheet) ->
+     case file:read_file(StyleSheet) of
+ 	{ok,Bin} ->
+ 	    Str = b2s(Bin,encoding(StyleSheet)),
+@@ -1131,23 +1146,30 @@ print_style(Fd,StyleSheet) ->
+ 		       N1 -> N1
+ 		   end,
+ 	    if (Pos0 == 0) and (Pos1 /= 0) ->
+-		    print_style_error(Fd,StyleSheet,missing_style_start_tag);
++		    print_style_error(Fd,GL,StyleSheet,missing_style_start_tag);
+ 	       (Pos0 /= 0) and (Pos1 == 0) ->
+-		    print_style_error(Fd,StyleSheet,missing_style_end_tag);
++		    print_style_error(Fd,GL,StyleSheet,missing_style_end_tag);
+ 	       Pos0 /= 0 ->
+ 		    Style = string:sub_string(Str,Pos0,Pos1+7),
+-		    io:format(Fd,"~ts\n",[Style]);
++		    if Fd == GL -> io:format(Fd,["$tc_html","~ts\n"],[Style]);
++		       true     -> io:format(Fd,"~ts\n",[Style])
++		    end;
+ 	       Pos0 == 0 ->
+-		    io:format(Fd,"<style>~ts</style>\n",[Str])
++		    if Fd == GL -> io:format(Fd,["$tc_html","<style>\n~ts</style>\n"],[Str]);
++		       true     -> io:format(Fd,"<style>\n~ts</style>\n",[Str])
++		    end
+ 	    end;
+ 	{error,Reason} ->
+-	    print_style_error(Fd,StyleSheet,Reason)  
++	    print_style_error(Fd,GL,StyleSheet,Reason)  
+     end.
+ 
+-print_style_error(Fd,StyleSheet,Reason) ->
+-    io:format(Fd,"\n<!-- Failed to load stylesheet ~ts: ~p -->\n",
+-	      [StyleSheet,Reason]),
+-    print_style(Fd,undefined).    
++print_style_error(Fd,GL,StyleSheet,Reason) ->
++    IO = io_lib:format("\n<!-- Failed to load stylesheet ~ts: ~p -->\n",
++		       [StyleSheet,Reason]),
++    if Fd == GL -> io:format(Fd,["$tc_html",IO],[]);
++       true     -> io:format(Fd,IO,[])
++    end,
++    print_style(Fd,GL,undefined).    
+ 
+ close_ctlog(Fd) ->
+     io:format(Fd, "\n</pre>\n", []),
+--- a/lib/common_test/src/ct_master.erl
++++ b/lib/common_test/src/ct_master.erl
+@@ -27,7 +27,7 @@
+ -export([run_on_node/2,run_on_node/3]).
+ -export([run_test/1,run_test/2]).
+ -export([get_event_mgr_ref/0]).
+--export([basic_html/1]).
++-export([basic_html/1,esc_chars/1]).
+ 
+ -export([abort/0,abort/1,progress/0]).
+ 
+@@ -317,6 +317,16 @@ basic_html(Bool) ->
+     ok.
+ 
+ %%%-----------------------------------------------------------------
++%%% @spec esc_chars(Bool) -> ok
++%%%       Bool = true | false
++%%%
++%%% @doc If set to false, the ct_master logs will be written without
++%%%      special characters being escaped in the HTML logs.
++esc_chars(Bool) ->
++    application:set_env(common_test_master, esc_chars, Bool),
++    ok.
++
++%%%-----------------------------------------------------------------
+ %%% MASTER, runs on central controlling node.
+ %%%-----------------------------------------------------------------
+ start_master(NodeOptsList) ->
+--- a/lib/common_test/src/ct_run.erl
++++ b/lib/common_test/src/ct_run.erl
+@@ -65,6 +65,7 @@
+ 	       logdir,
+ 	       logopts = [],
+ 	       basic_html,
++	       esc_chars = true,
+ 	       verbosity = [],
+ 	       config = [],
+ 	       event_handlers = [],
+@@ -346,6 +347,15 @@ script_start1(Parent, Args) ->
+ 			application:set_env(common_test, basic_html, true),
+ 			true
+ 		end,
++    %% esc_chars - used by ct_logs
++    EscChars = case proplists:get_value(no_esc_chars, Args) of
++		   undefined ->
++		       application:set_env(common_test, esc_chars, true),
++		       undefined;
++		   _ ->
++		       application:set_env(common_test, esc_chars, false),
++		       false
++	       end,
+     %% disable_log_cache - used by ct_logs
+     case proplists:get_value(disable_log_cache, Args) of
+ 	undefined ->
+@@ -359,6 +369,7 @@ script_start1(Parent, Args) ->
+ 		 cover = Cover, cover_stop = CoverStop,
+ 		 logdir = LogDir, logopts = LogOpts,
+ 		 basic_html = BasicHtml,
++		 esc_chars = EscChars,
+ 		 verbosity = Verbosity,
+ 		 event_handlers = EvHandlers,
+ 		 ct_hooks = CTHooks,
+@@ -587,6 +598,17 @@ combine_test_opts(TS, Specs, Opts) ->
+ 		BHBool
+ 	end,
+ 
++    EscChars =
++	case choose_val(Opts#opts.esc_chars,
++			TSOpts#opts.esc_chars) of
++	    undefined ->
++		true;
++	    ECBool ->
++		application:set_env(common_test, esc_chars,
++				    ECBool),
++		ECBool
++	end,
++
+     Opts#opts{label = Label,
+ 	      profile = Profile,
+ 	      testspec_files = Specs,
+@@ -595,6 +617,7 @@ combine_test_opts(TS, Specs, Opts) ->
+ 	      logdir = which(logdir, LogDir),
+ 	      logopts = AllLogOpts,
+ 	      basic_html = BasicHtml,
++	      esc_chars = EscChars,
+ 	      verbosity = AllVerbosity,
+ 	      silent_connections = AllSilentConns,
+ 	      config = TSOpts#opts.config,
+@@ -795,6 +818,7 @@ script_usage() ->
+ 	      "\n\t [-scale_timetraps]"
+ 	      "\n\t [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
+ 	      "\n\t [-basic_html]"
++	      "\n\t [-no_esc_chars]"
+ 	      "\n\t [-repeat N] |"
+ 	      "\n\t [-duration HHMMSS [-force_stop [skip_rest]]] |"
+ 	      "\n\t [-until [YYMoMoDD]HHMMSS [-force_stop [skip_rest]]]"
+@@ -822,6 +846,7 @@ script_usage() ->
+ 	      "\n\t [-scale_timetraps]"
+ 	      "\n\t [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
+ 	      "\n\t [-basic_html]"
++	      "\n\t [-no_esc_chars]"
+ 	      "\n\t [-repeat N] |"
+ 	      "\n\t [-duration HHMMSS [-force_stop [skip_rest]]] |"
+ 	      "\n\t [-until [YYMoMoDD]HHMMSS [-force_stop [skip_rest]]]\n\n"),
+@@ -847,7 +872,8 @@ script_usage() ->
+ 	      "\n\t [-multiply_timetraps N]"
+ 	      "\n\t [-scale_timetraps]"
+ 	      "\n\t [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
+-	      "\n\t [-basic_html]\n\n").
++	      "\n\t [-basic_html]"
++	      "\n\t [-no_esc_chars]\n\n").
+ 
+ %%%-----------------------------------------------------------------
+ %%% @hidden
+@@ -1089,7 +1115,17 @@ run_test2(StartOpts) ->
+ 		application:set_env(common_test, basic_html, BasicHtmlBool),
+ 		BasicHtmlBool		
+     end,
+-
++    %% esc_chars - used by ct_logs
++    EscChars =
++	case proplists:get_value(esc_chars, StartOpts) of
++	    undefined ->
++		application:set_env(common_test, esc_chars, true),
++		undefined;
++	    EscCharsBool ->
++		application:set_env(common_test, esc_chars, EscCharsBool),
++		EscCharsBool		
++    end,
++    %% disable_log_cache - used by ct_logs
+     case proplists:get_value(disable_log_cache, StartOpts) of
+ 	undefined ->
+ 	    application:set_env(common_test, disable_log_cache, false);
+@@ -1104,6 +1140,7 @@ run_test2(StartOpts) ->
+ 		 cover = Cover, cover_stop = CoverStop,
+ 		 step = Step, logdir = LogDir,
+ 		 logopts = LogOpts, basic_html = BasicHtml,
++		 esc_chars = EscChars,
+ 		 config = CfgFiles,
+ 		 verbosity = Verbosity,
+ 		 event_handlers = EvHandlers,
+@@ -1445,6 +1482,7 @@ get_data_for_node(#testspec{label = Labels,
+ 			    logdir = LogDirs,
+ 			    logopts = LogOptsList,
+ 			    basic_html = BHs,
++			    esc_chars = EscChs,
+ 			    stylesheet = SSs,
+ 			    verbosity = VLvls,
+ 			    silent_connections = SilentConnsList,
+@@ -1472,6 +1510,7 @@ get_data_for_node(#testspec{label = Labels,
+ 		  LOs -> LOs
+ 	      end,
+     BasicHtml = proplists:get_value(Node, BHs),
++    EscChars = proplists:get_value(Node, EscChs),
+     Stylesheet = proplists:get_value(Node, SSs),
+     Verbosity = case proplists:get_value(Node, VLvls) of
+ 		    undefined -> [];
+@@ -1498,6 +1537,7 @@ get_data_for_node(#testspec{label = Labels,
+ 	  logdir = LogDir,
+ 	  logopts = LogOpts,
+ 	  basic_html = BasicHtml,
++	  esc_chars = EscChars,
+ 	  stylesheet = Stylesheet,
+ 	  verbosity = Verbosity,
+ 	  silent_connections = SilentConns,
+@@ -2182,10 +2222,18 @@ do_run_test(Tests, Skip, Opts0) ->
+ 	    %% test_server needs to know the include path too
+ 	    InclPath = case application:get_env(common_test, include) of
+ 			   {ok,Incls} -> Incls;
+-			   _ -> []
++			   _          -> []
+ 		       end,
+ 	    application:set_env(test_server, include, InclPath),
+ 
++	    %% copy the escape characters setting to test_server
++	    EscChars =
++		case application:get_env(common_test, esc_chars) of
++		    {ok,ECBool} -> ECBool;
++		    _           -> true
++		end,
++	    application:set_env(test_server, esc_chars, EscChars),
++
+ 	    test_server_ctrl:start_link(local),
+ 
+ 	    %% let test_server expand the test tuples and count no of cases
+@@ -3071,6 +3119,10 @@ opts2args(EnvStartOpts) ->
+ 			  [{basic_html,[]}];
+ 		     ({basic_html,false}) ->
+ 			  [];
++		     ({esc_chars,false}) ->
++			  [{no_esc_chars,[]}];
++		     ({esc_chars,true}) ->
++			  [];
+ 		     ({event_handler,EH}) when is_atom(EH) ->
+ 			  [{event_handler,[atom_to_list(EH)]}];
+ 		     ({event_handler,EHs}) when is_list(EHs) ->
+--- a/lib/common_test/src/ct_telnet.erl
++++ b/lib/common_test/src/ct_telnet.erl
+@@ -42,7 +42,8 @@
+ %%                    {reconnection_interval,Millisec},
+ %%                    {keep_alive,Bool},
+ %%                    {poll_limit,N},
+-%%                    {poll_interval,Millisec}]}.</pre>
++%%                    {poll_interval,Millisec},
++%%                    {tcp_nodelay,Bool}]}.</pre>
+ %% <p><code>Millisec = integer(), N = integer()</code></p>
+ %% <p>Enter the <code>telnet_settings</code> term in a configuration 
+ %% file included in the test and ct_telnet will retrieve the information
+@@ -182,7 +183,8 @@
+ 	       conn_to=?DEFAULT_TIMEOUT, 
+ 	       com_to=?DEFAULT_TIMEOUT, 
+ 	       reconns=?RECONNS,
+-	       reconn_int=?RECONN_TIMEOUT}).
++	       reconn_int=?RECONN_TIMEOUT,
++	       tcp_nodelay=false}).
+ 
+ %%%-----------------------------------------------------------------
+ %%% @spec open(Name) -> {ok,Handle} | {error,Reason}
+@@ -602,8 +604,18 @@ init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
+ 	     Settings ->
+ 		 set_telnet_defaults(Settings,#state{})				    
+ 	 end,
+-    case catch TargetMod:connect(Name,Ip,Port,S0#state.conn_to,
+-				 KeepAlive,Extra) of
++    %% Handle old user versions of TargetMod
++    code:ensure_loaded(TargetMod),
++    try
++	case erlang:function_exported(TargetMod,connect,7) of
++	    true ->
++		TargetMod:connect(Name,Ip,Port,S0#state.conn_to,
++				  KeepAlive,S0#state.tcp_nodelay,Extra);
++	    false ->
++		TargetMod:connect(Name,Ip,Port,S0#state.conn_to,
++				  KeepAlive,Extra)
++	end
++    of
+ 	{ok,TelnPid} ->
+ 	    put({ct_telnet_pid2name,TelnPid},Name),
+ 	    S1 = S0#state{host=Ip,
+@@ -625,15 +637,18 @@ init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
+ 		"Connection timeout: ~p\n"
+ 		"Keep alive: ~w\n"
+ 		"Poll limit: ~w\n"
+-		"Poll interval: ~w",
++		"Poll interval: ~w\n"
++		"TCP nodelay: ~w",
+ 		[Ip,Port,S1#state.com_to,S1#state.reconns,
+ 		 S1#state.reconn_int,S1#state.conn_to,KeepAlive,
+-		 S1#state.poll_limit,S1#state.poll_interval]),
++		 S1#state.poll_limit,S1#state.poll_interval,
++		 S1#state.tcp_nodelay]),
+ 	    {ok,TelnPid,S1};
+-	{'EXIT',Reason} ->
+-	    {error,Reason};
+ 	Error ->
+ 	    Error
++    catch
++	_:Reason ->
++	    {error,Reason}
+     end.
+ 
+ type(telnet) -> ip;
+@@ -653,6 +668,8 @@ set_telnet_defaults([{poll_limit,PL}|Ss],S) ->
+     set_telnet_defaults(Ss,S#state{poll_limit=PL});
+ set_telnet_defaults([{poll_interval,PI}|Ss],S) ->
+     set_telnet_defaults(Ss,S#state{poll_interval=PI});
++set_telnet_defaults([{tcp_nodelay,NoDelay}|Ss],S) ->
++    set_telnet_defaults(Ss,S#state{tcp_nodelay=NoDelay});
+ set_telnet_defaults([Unknown|Ss],S) ->
+     force_log(S,error,
+ 	      "Bad element in telnet_settings: ~p",[Unknown]),
+@@ -794,8 +811,17 @@ reconnect(Ip,Port,N,State=#state{name=Name,
+ 				 keep_alive=KeepAlive,
+ 				 extra=Extra,
+ 				 conn_to=ConnTo,
+-				 reconn_int=ReconnInt}) ->
+-    case TargetMod:connect(Name,Ip,Port,ConnTo,KeepAlive,Extra) of
++				 reconn_int=ReconnInt,
++				 tcp_nodelay=NoDelay}) ->
++    %% Handle old user versions of TargetMod
++    ConnResult =
++	case erlang:function_exported(TargetMod,connect,7) of
++	    true ->
++		TargetMod:connect(Name,Ip,Port,ConnTo,KeepAlive,NoDelay,Extra);
++	    false ->
++		TargetMod:connect(Name,Ip,Port,ConnTo,KeepAlive,Extra)
++	end,
++    case ConnResult of
+ 	{ok,NewPid} ->
+ 	    put({ct_telnet_pid2name,NewPid},Name),
+ 	    {ok, NewPid, State#state{teln_pid=NewPid}};
+--- a/lib/common_test/src/ct_telnet_client.erl
++++ b/lib/common_test/src/ct_telnet_client.erl
+@@ -35,7 +35,7 @@
+ 
+ %%-define(debug, true).
+ 
+--export([open/2, open/3, open/4, open/5, close/1]).
++-export([open/2, open/3, open/4, open/5, open/6, close/1]).
+ -export([send_data/2, send_data/3, get_data/1]).
+ 
+ -define(TELNET_PORT, 23).
+@@ -70,19 +70,22 @@
+ -record(state,{conn_name, get_data, keep_alive=true, log_pos=1}).
+ 
+ open(Server, ConnName) ->
+-    open(Server, ?TELNET_PORT, ?OPEN_TIMEOUT, true, ConnName).
++    open(Server, ?TELNET_PORT, ?OPEN_TIMEOUT, true, false, ConnName).
+ 
+ open(Server, Port, ConnName) ->
+-    open(Server, Port, ?OPEN_TIMEOUT, true, ConnName).
++    open(Server, Port, ?OPEN_TIMEOUT, true, false, ConnName).
+ 
+ open(Server, Port, Timeout, ConnName) ->
+-    open(Server, Port, Timeout, true, ConnName).
++    open(Server, Port, Timeout, true, false, ConnName).
+ 
+ open(Server, Port, Timeout, KeepAlive, ConnName) ->
++    open(Server, Port, Timeout, KeepAlive, false, ConnName).
++
++open(Server, Port, Timeout, KeepAlive, NoDelay, ConnName) ->
+     Self = self(),
+     Pid = spawn(fun() ->
+ 			init(Self, Server, Port, Timeout,
+-			     KeepAlive, ConnName)
++			     KeepAlive, NoDelay, ConnName)
+ 		end),
+     receive 
+ 	{open,Pid} ->
+@@ -114,8 +117,8 @@ get_data(Pid) ->
+ 
+ %%%-----------------------------------------------------------------
+ %%% Internal functions
+-init(Parent, Server, Port, Timeout, KeepAlive, ConnName) ->
+-    case gen_tcp:connect(Server, Port, [list,{packet,0},{nodelay,true}], Timeout) of
++init(Parent, Server, Port, Timeout, KeepAlive, NoDelay, ConnName) ->
++    case gen_tcp:connect(Server, Port, [list,{packet,0},{nodelay,NoDelay}], Timeout) of
+ 	{ok,Sock} ->
+ 	    dbg("~p connected to: ~p (port: ~w, keep_alive: ~w)\n",
+ 		[ConnName,Server,Port,KeepAlive]),
+--- a/lib/common_test/src/ct_testspec.erl
++++ b/lib/common_test/src/ct_testspec.erl
+@@ -1146,8 +1146,9 @@ should_be_added(Tag,Node,_Data,Spec) ->
+     if 
+ 	%% list terms *without* possible duplicates here
+ 	Tag == logdir;       Tag == logopts;
+-	Tag == basic_html;   Tag == label;
+-	Tag == auto_compile; Tag == abort_if_missing_suites;
++	Tag == basic_html;   Tag == esc_chars;
++	Tag == label;        Tag == auto_compile;
++	Tag == abort_if_missing_suites;
+ 	Tag == stylesheet;   Tag == verbosity;
+ 	Tag == silent_connections ->
+ 	    lists:keymember(ref2node(Node,Spec#testspec.nodes),1,
+@@ -1544,6 +1545,8 @@ valid_terms() ->
+      {logopts,3},
+      {basic_html,2},
+      {basic_html,3},
++     {esc_chars,2},
++     {esc_chars,3},
+      {verbosity,2},
+      {verbosity,3},
+      {silent_connections,2},
+--- a/lib/common_test/src/ct_util.erl
++++ b/lib/common_test/src/ct_util.erl
+@@ -459,6 +459,7 @@ loop(Mode,TestData,StartDir) ->
+ 		    error:badarg -> []
+ 		end,
+ 	    ct_hooks:terminate(Callbacks),
++
+ 	    close_connections(ets:tab2list(?conn_table)),
+ 	    ets:delete(?conn_table),
+ 	    ets:delete(?board_table),
+--- a/lib/common_test/src/ct_util.hrl
++++ b/lib/common_test/src/ct_util.hrl
+@@ -37,6 +37,7 @@
+ 		   logdir=["."],
+ 		   logopts=[],
+ 		   basic_html=[],
++		   esc_chars=[],
+ 		   verbosity=[],
+ 		   silent_connections=[],
+ 		   cover=[],
+--- a/lib/common_test/src/cth_log_redirect.erl
++++ b/lib/common_test/src/cth_log_redirect.erl
+@@ -130,7 +130,14 @@ handle_event(Event, #eh_state{log_func = LogFunc} = State) ->
+ 						tag_event(Event)),
+ 	    if is_list(SReport) ->
+ 		    SaslHeader = format_header(State),
+-		    ct_logs:LogFunc(sasl, ?STD_IMPORTANCE, SaslHeader, SReport, []);
++		    case LogFunc of
++			tc_log ->
++			    ct_logs:tc_log(sasl, ?STD_IMPORTANCE,
++					   SaslHeader, SReport, [], []);
++			tc_log_async ->
++			    ct_logs:tc_log_async(sasl, ?STD_IMPORTANCE,
++						 SaslHeader, SReport, [])
++		    end;
+ 	       true -> %% Report is an atom if no logging is to be done
+ 		    ignore
+ 	    end
+@@ -139,7 +146,14 @@ handle_event(Event, #eh_state{log_func = LogFunc} = State) ->
+ 		tag_event(Event),io_lib),
+     if is_list(EReport) ->
+ 	    ErrHeader = format_header(State),
+-	    ct_logs:LogFunc(error_logger, ?STD_IMPORTANCE, ErrHeader, EReport, []);
++	    case LogFunc of
++		tc_log ->
++		    ct_logs:tc_log(error_logger, ?STD_IMPORTANCE,
++				   ErrHeader, EReport, [], []);
++		tc_log_async ->
++		    ct_logs:tc_log_async(error_logger, ?STD_IMPORTANCE,
++					 ErrHeader, EReport, [])
++	    end;
+        true -> %% Report is an atom if no logging is to be done
+ 	    ignore
+     end,
+--- a/lib/common_test/src/cth_surefire.erl
++++ b/lib/common_test/src/cth_surefire.erl
+@@ -82,7 +82,8 @@ init(Path, Opts) ->
+ 	    url_base = proplists:get_value(url_base,Opts),
+ 	    timer = ?now }.
+ 
+-pre_init_per_suite(Suite,SkipOrFail,State) when is_tuple(SkipOrFail) ->
++pre_init_per_suite(Suite,SkipOrFail,#state{ test_cases = [] } = State)
++  when is_tuple(SkipOrFail) ->
+     {SkipOrFail, init_tc(State#state{curr_suite = Suite,
+ 				     curr_suite_ts = ?now},
+ 			 SkipOrFail) };
+--- a/lib/common_test/src/unix_telnet.erl
++++ b/lib/common_test/src/unix_telnet.erl
+@@ -27,7 +27,8 @@
+ %%%        {port,PortNum},                 % optional
+ %%%        {username,UserName},
+ %%%        {password,Password},
+-%%%        {keep_alive,Bool}]}.            % optional</pre>
++%%%        {keep_alive,Bool},              % optional
++%%%        {tcp_nodely,Bool}]}             % optional</pre>
+ %%%
+ %%% <p>To communicate via telnet to the host specified by
+ %%% <code>HostNameOrIpAddress</code>, use the interface functions in
+@@ -55,7 +56,7 @@
+ -compile(export_all).
+ 
+ %% Callbacks for ct_telnet.erl
+--export([connect/6,get_prompt_regexp/0]).
++-export([connect/7,get_prompt_regexp/0]).
+ -import(ct_telnet,[start_gen_log/1,log/4,end_gen_log/0]).
+ 
+ -define(username,"login: ").
+@@ -82,6 +83,7 @@ get_prompt_regexp() ->
+ %%%      Port = integer()
+ %%%      Timeout = integer()
+ %%%      KeepAlive = bool()
++%%%      TCPNoDelay = bool()
+ %%%      Extra = ct:target_name() | {Username,Password}
+ %%%      Username = string()
+ %%%      Password = string()
+@@ -91,25 +93,25 @@ get_prompt_regexp() ->
+ %%% @doc Callback for ct_telnet.erl.
+ %%%
+ %%% <p>Setup telnet connection to a unix host.</p>
+-connect(ConnName,Ip,Port,Timeout,KeepAlive,Extra) ->
++connect(ConnName,Ip,Port,Timeout,KeepAlive,TCPNoDelay,Extra) ->
+     case Extra of
+ 	{Username,Password} -> 
+-	    connect1(ConnName,Ip,Port,Timeout,KeepAlive,
++	    connect1(ConnName,Ip,Port,Timeout,KeepAlive,TCPNoDelay,
+ 		     Username,Password);
+ 	KeyOrName ->
+ 	    case get_username_and_password(KeyOrName) of
+ 		{ok,{Username,Password}} ->
+-		    connect1(ConnName,Ip,Port,Timeout,KeepAlive,
++		    connect1(ConnName,Ip,Port,Timeout,KeepAlive,TCPNoDelay,
+ 			     Username,Password);
+ 		Error ->
+ 		    Error
+ 	    end
+     end.
+ 
+-connect1(Name,Ip,Port,Timeout,KeepAlive,Username,Password) ->
++connect1(Name,Ip,Port,Timeout,KeepAlive,TCPNoDelay,Username,Password) ->
+     start_gen_log("unix_telnet connect"),
+     Result = 
+-	case ct_telnet_client:open(Ip,Port,Timeout,KeepAlive,Name) of
++	case ct_telnet_client:open(Ip,Port,Timeout,KeepAlive,TCPNoDelay,Name) of
+ 	    {ok,Pid} ->
+ 		case ct_telnet:silent_teln_expect(Name,Pid,[],
+ 						  [prompt],?prx,[]) of
+--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl
++++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl
+@@ -1,8 +1,8 @@
+-%%
+-%% %CopyrightBegin%
+-%%
+-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+-%%
++%%
++%% %CopyrightBegin%
++%%
++%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
++%%
+ %% Licensed under the Apache License, Version 2.0 (the "License");
+ %% you may not use this file except in compliance with the License.
+ %% You may obtain a copy of the License at
+@@ -14,46 +14,46 @@
+ %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ %% See the License for the specific language governing permissions and
+ %% limitations under the License.
+-%%
+-%% %CopyrightEnd%
+-%%
+-
+--module(ct_update_config_SUITE).
+-
+--suite_defaults([{timetrap, {minutes, 10}}]).
+-
+-%% Note: This directive should only be used in test suites.
+--compile(export_all).
+-
+--include("ct.hrl").
+-
+--define(now, os:timestamp()).
+-
+-%% Test server callback functions
+-init_per_suite(Config) ->
+-    [{init_per_suite,?now}|Config].
+-
+-end_per_suite(_Config) ->
+-    ok.
+-
+-init_per_testcase(_TestCase, Config) ->
+-    [{init_per_testcase,?now}|Config].
+-
+-end_per_testcase(_TestCase, _Config) ->
+-    ok.
+-
+-init_per_group(GroupName, Config) ->
+-    [{init_per_group,?now}|Config].
+-
+-end_per_group(GroupName, Config) ->
+-    ok.
+-
+-all() ->
+-    [{group,group1}].
+-
+-groups() ->
+-    [{group1,[],[test_case]}].
+-    
+-%% Test cases starts here.
+-test_case(Config) when is_list(Config) ->
+-    ok.
++%%
++%% %CopyrightEnd%
++%%
++
++-module(ct_update_config_SUITE).
++
++-suite_defaults([{timetrap, {minutes, 10}}]).
++
++%% Note: This directive should only be used in test suites.
++-compile(export_all).
++
++-include("ct.hrl").
++
++-define(now, ct_test_support:unique_timestamp()).
++
++%% Test server callback functions
++init_per_suite(Config) ->
++    [{init_per_suite,?now}|Config].
++
++end_per_suite(_Config) ->
++    ok.
++
++init_per_testcase(_TestCase, Config) ->
++    [{init_per_testcase,?now}|Config].
++
++end_per_testcase(_TestCase, _Config) ->
++    ok.
++
++init_per_group(GroupName, Config) ->
++    [{init_per_group,?now}|Config].
++
++end_per_group(GroupName, Config) ->
++    ok.
++
++all() ->
++    [{group,group1}].
++
++groups() ->
++    [{group1,[],[test_case]}].
++    
++%% Test cases starts here.
++test_case(Config) when is_list(Config) ->
++    ok.
+--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
++++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+@@ -90,7 +90,7 @@ id(Opts) ->
+     gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ 					    data = {?MODULE, id, [Opts]}}),
+     ct:log("~w:id called", [?MODULE]),
+-    os:timestamp().
++    ct_test_support:unique_timestamp().
+ 
+ %% @doc Called before init_per_suite is called. Note that this callback is
+ %% only called if the CTH is added before init_per_suite is run (eg. in a test
+--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl
++++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl
+@@ -25,7 +25,7 @@
+ -include_lib("common_test/src/ct_util.hrl").
+ -include_lib("common_test/include/ct_event.hrl").
+ 
+--define(now, os:timestamp()).
++-define(now, ct_test_support:unique_timestamp()).
+ 
+ %% CT Hooks
+ -compile(export_all).
+--- a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
++++ b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
+@@ -44,13 +44,29 @@
+ %% instance, the tests need to be performed on a separate node (or
+ %% there will be clashes with logging processes etc).
+ %%--------------------------------------------------------------------
++suite() ->
++    [{ct_hooks,[ts_install_cth]},
++     {timetrap,{seconds,120}}].
++
++all() ->
++    [
++     pre_post_io
++    ].
++
+ init_per_suite(Config) ->
+-    DataDir = ?config(data_dir, Config),
+-    CTH = filename:join(DataDir, "cth_ctrl.erl"),
+-    ct:pal("Compiling ~p: ~p",
+-	   [CTH,compile:file(CTH,[{outdir,DataDir},debug_info])]),
+-    ct_test_support:init_per_suite([{path_dirs,[DataDir]},
+-				    {start_sasl,true} | Config]).
++    TTInfo = {_T,{_Scaled,ScaleVal}} = ct:get_timetrap_info(),
++    ct:pal("Timetrap info = ~w", [TTInfo]),
++    if ScaleVal > 1 ->
++	    {skip,"Skip on systems running e.g. cover or debug!"};
++       ScaleVal =< 1 ->
++	    DataDir = ?config(data_dir, Config),
++	    CTH = filename:join(DataDir, "cth_ctrl.erl"),
++	    ct:pal("Compiling ~p: ~p",
++		   [CTH,compile:file(CTH,[{outdir,DataDir},
++					  debug_info])]),
++	    ct_test_support:init_per_suite([{path_dirs,[DataDir]},
++					    {start_sasl,true} | Config])
++    end.
+ 
+ end_per_suite(Config) ->
+     ct_test_support:end_per_suite(Config).
+@@ -61,13 +77,6 @@ init_per_testcase(TestCase, Config) ->
+ end_per_testcase(TestCase, Config) ->
+     ct_test_support:end_per_testcase(TestCase, Config).
+ 
+-suite() -> [{ct_hooks,[ts_install_cth]}].
+-
+-all() ->
+-    [
+-     pre_post_io
+-    ].
+-
+ %%--------------------------------------------------------------------
+ %% TEST CASES
+ %%--------------------------------------------------------------------
+@@ -90,31 +99,50 @@ pre_post_io(Config) ->
+     %%!--------------------------------------------------------------------
+ 
+     spawn(fun() ->
+-		  ct:pal("CONTROLLER: Started!", []),
++		  ct:pal("CONTROLLER: Starting test run #1...", []),
+ 		  %% --- test run 1 ---
+-		  ct:sleep(3000),
+-		  ct:pal("CONTROLLER: Handle remote events = true", []),
+-		  ok = ct_test_support:ct_rpc({cth_log_redirect,
+-					       handle_remote_events,
+-					       [true]}, Config),
+-		  ct:sleep(2000),
+-		  ct:pal("CONTROLLER: Proceeding with test run #1!", []),
++		  try_loop(ct_test_support, ct_rpc, [{cth_log_redirect,
++						      handle_remote_events,
++						      [true]}, Config], 3000),
++		  CTLoggerPid1 = ct_test_support:ct_rpc({erlang,whereis,
++							[ct_logs]}, Config),
++		  ct:pal("CONTROLLER: Logger = ~w~nHandle remote events = true",
++			 [CTLoggerPid1]),
++		  ct:sleep(5000),
++		  ct:pal("CONTROLLER: Proceeding with test run #1...", []),
+ 		  ok = ct_test_support:ct_rpc({cth_ctrl,proceed,[]}, Config),
+ 		  ct:sleep(6000),
+-		  ct:pal("CONTROLLER: Proceeding with shutdown #1!", []),
++		  ct:pal("CONTROLLER: Proceeding with shutdown #1...", []),
+ 		  ok = ct_test_support:ct_rpc({cth_ctrl,proceed,[]}, Config),
++		  try_loop(fun() ->
++				   false = ct_test_support:ct_rpc({erlang,
++								    is_process_alive,
++								    [CTLoggerPid1]},
++								   Config)
++			   end, 3000),
++		  ct:pal("CONTROLLER: Shutdown #1 complete!", []),
++		  ct:pal("CONTROLLER: Starting test run #2...", []),
+ 		  %% --- test run 2 ---
+-		  ct:sleep(3000),
+-		  ct:pal("CONTROLLER: Handle remote events = true", []),
+-		  ok = ct_test_support:ct_rpc({cth_log_redirect,
+-					       handle_remote_events,
+-					       [true]}, Config),
+-		  ct:sleep(2000),
+-		  ct:pal("CONTROLLER: Proceeding with test run #2!", []),
++		  try_loop(ct_test_support, ct_rpc, [{cth_log_redirect,
++						      handle_remote_events,
++						      [true]}, Config], 3000),
++		  CTLoggerPid2 = ct_test_support:ct_rpc({erlang,whereis,
++							[ct_logs]}, Config),
++		  ct:pal("CONTROLLER: Logger = ~w~nHandle remote events = true",
++			 [CTLoggerPid2]),
++		  ct:sleep(5000),
++		  ct:pal("CONTROLLER: Proceeding with test run #2...", []),
+ 		  ok = ct_test_support:ct_rpc({cth_ctrl,proceed,[]}, Config),
+ 		  ct:sleep(6000),
+-		  ct:pal("CONTROLLER: Proceeding with shutdown #2!", []),
+-		  ok = ct_test_support:ct_rpc({cth_ctrl,proceed,[]}, Config)
++		  ct:pal("CONTROLLER: Proceeding with shutdown #2...", []),
++		  ok = ct_test_support:ct_rpc({cth_ctrl,proceed,[]}, Config),
++		  try_loop(fun() ->
++				   false = ct_test_support:ct_rpc({erlang,
++								   is_process_alive,
++								   [CTLoggerPid2]},
++								  Config)
++			   end, 3000),
++		  ct:pal("CONTROLLER: Shutdown #2 complete!", [])
+ 	  end),
+     ct_test_support:run(Opts, Config),
+     Events = ct_test_support:get_events(ERPid, Config),
+@@ -157,7 +185,7 @@ pre_post_io(Config) ->
+ 				      Counters
+ 			      end, {pre,0,0,0,0}, Ts),
+ 	      [_|Counters] = tuple_to_list(PrePostIOEntries),
+-	      ct:log("Entries in the Pre/Post Test IO Log: ~p", [Counters]),
++	      ct:pal("Entries in the Pre/Post Test IO Log: ~w", [Counters]),
+ 	      case [C || C <- Counters, C < 2] of
+ 		  [] ->
+ 		      ok;
+@@ -183,7 +211,7 @@ pre_post_io(Config) ->
+ 				      [LogN,ErrN+1];
+ 				 (_, Counters) -> Counters
+ 			      end, [0,0], Ts),
+-	      ct:log("Entries in the Unexpected IO Log: ~p", [UnexpIOEntries]),
++	      ct:log("Entries in the Unexpected IO Log: ~w", [UnexpIOEntries]),
+ 	      case [N || N <- UnexpIOEntries, N < 2] of
+ 		  [] ->
+ 		      ok;
+@@ -208,6 +236,38 @@ setup(Test, Config) ->
+ reformat(Events, EH) ->
+     ct_test_support:reformat(Events, EH).
+ 
++try_loop(_Fun, 0) ->
++    ct:pal("WARNING! Fun never succeeded!", []),
++    gave_up;
++try_loop(Fun, N) ->
++    try Fun() of
++	{error,_} ->
++	    timer:sleep(10),
++	    try_loop(Fun, N-1);
++	Result ->
++	    Result
++    catch
++	_:_What ->
++	    timer:sleep(10),
++	    try_loop(Fun, N-1)
++    end.
++
++try_loop(M, F, _A, 0) ->
++    ct:pal("WARNING! ~w:~w never succeeded!", [M,F]),
++    gave_up;
++try_loop(M, F, A, N) ->
++    try apply(M, F, A) of
++	{error,_} ->
++	    timer:sleep(10),
++	    try_loop(M, F, A, N-1);
++	Result ->
++	    Result
++    catch
++	_:_ ->
++	    timer:sleep(10),
++	    try_loop(M, F, A, N-1)
++    end.
++
+ %%%-----------------------------------------------------------------
+ %%% TEST EVENTS
+ %%%-----------------------------------------------------------------
+--- a/lib/common_test/test/ct_pre_post_test_io_SUITE_data/cth_ctrl.erl
++++ b/lib/common_test/test/ct_pre_post_test_io_SUITE_data/cth_ctrl.erl
+@@ -53,8 +53,7 @@ init(_Id, _Opts) ->
+     receive
+ 	{?MODULE,proceed} -> ok
+     after
+-	10000 ->
+-	    ok
++	10000 -> ok
+     end,
+     {ok,[],ct_last}.
+ 
+@@ -66,8 +65,7 @@ terminate(_State) ->
+     receive
+ 	{?MODULE,proceed} -> ok
+     after
+-       10000 ->
+-	    ok
++       10000 -> ok
+     end,
+     stop_external_logger(cth_logger),
+     stop_dispatcher(),
+@@ -94,7 +92,7 @@ init_logger(Name) ->
+ logger_loop(N) ->
+     ct:log("Logger iteration: ~p", [N]),
+     error_logger:error_report(N),
+-    timer:sleep(250),
++    timer:sleep(100),
+     logger_loop(N+1).
+ 
+ %%%-----------------------------------------------------------------
+--- a/lib/common_test/test/ct_surefire_SUITE.erl
++++ b/lib/common_test/test/ct_surefire_SUITE.erl
+@@ -49,8 +49,11 @@
+ %% there will be clashes with logging processes etc).
+ %%--------------------------------------------------------------------
+ init_per_suite(Config) ->
+-    Config1 = ct_test_support:init_per_suite(Config),
+-    Config1.
++    DataDir = ?config(data_dir,Config),
++    Hook = "fail_pre_init_per_suite.erl",
++    io:format("Compiling ~p: ~p~n",
++        [Hook, compile:file(Hook,[{outdir,DataDir},debug_info])]),
++    ct_test_support:init_per_suite([{path_dirs,[DataDir]}|Config]).
+ 
+ end_per_suite(Config) ->
+     ct_test_support:end_per_suite(Config).
+@@ -69,7 +72,8 @@ all() ->
+      absolute_path,
+      relative_path,
+      url,
+-     logdir
++     logdir,
++     fail_pre_init_per_suite
+     ].
+ 
+ %%--------------------------------------------------------------------
+@@ -107,6 +111,14 @@ logdir(Config) when is_list(Config) ->
+     Path = "logdir.xml",
+     run(logdir,[{cth_surefire,[{path,Path}]}],Path,Config,[{logdir,MyLogDir}]).
+ 
++fail_pre_init_per_suite(Config) when is_list(Config) ->
++    DataDir = ?config(data_dir,Config),
++    Suites = [filename:join(DataDir,"pass_SUITE"),
++              filename:join(DataDir,"fail_SUITE")],
++    Path = "fail_pre_init_per_suite.xml",
++    run(fail_pre_init_per_suite,[fail_pre_init_per_suite,
++        {cth_surefire,[{path,Path}]}],Path,Config,[],Suites).
++
+ %%%-----------------------------------------------------------------
+ %%% HELP FUNCTIONS
+ %%%-----------------------------------------------------------------
+@@ -115,6 +127,8 @@ run(Case,CTHs,Report,Config) ->
+ run(Case,CTHs,Report,Config,ExtraOpts) ->
+     DataDir = ?config(data_dir, Config),
+     Suite = filename:join(DataDir, "surefire_SUITE"),
++    run(Case,CTHs,Report,Config,ExtraOpts,Suite).
++run(Case,CTHs,Report,Config,ExtraOpts,Suite) ->
+     {Opts,ERPid} = setup([{suite,Suite},{ct_hooks,CTHs},{label,Case}|ExtraOpts],
+ 			 Config),
+     ok = execute(Case, Opts, ERPid, Config),
+@@ -142,7 +156,6 @@ setup(Test, Config) ->
+ execute(Name, Opts, ERPid, Config) ->
+     ok = ct_test_support:run(Opts, Config),
+     Events = ct_test_support:get_events(ERPid, Config),
+-
+     ct_test_support:log_events(Name,
+ 			       reformat(Events, ?eh),
+ 			       ?config(priv_dir, Config),
+@@ -166,10 +179,30 @@ events_to_check(_, 0) ->
+ events_to_check(Test, N) ->
+     test_events(Test) ++ events_to_check(Test, N-1).
+ 
+-test_events(_) ->
+-    [{?eh,start_logging,'_'},
+-     {?eh,start_info,{1,1,9}},
+-     {?eh,tc_start,{surefire_SUITE,init_per_suite}},
++test_suite_events(fail_SUITE, TestStat) ->
++     [{?eh,tc_start,{ct_framework,init_per_suite}},
++     {?eh,tc_done,{ct_framework,init_per_suite,
++                   {failed,{error,pre_init_per_suite}}}},
++     {?eh,tc_auto_skip,
++      {fail_SUITE,test_case,
++       {failed,{ct_framework,init_per_suite,{failed,pre_init_per_suite}}}}},
++     {?eh,test_stats,TestStat},
++     {?eh,tc_auto_skip,
++      {ct_framework,end_per_suite,
++       {failed,{ct_framework,init_per_suite,{failed,pre_init_per_suite}}}}}].
++
++test_suite_events(fail_SUITE) ->
++    test_suite_events(fail_SUITE, {0,0,{0,1}});
++test_suite_events(pass_SUITE) ->
++     [{?eh,tc_start,{ct_framework,init_per_suite}},
++     {?eh,tc_done,{ct_framework,init_per_suite,ok}},
++     {?eh,tc_start,{pass_SUITE,test_case}},
++     {?eh,tc_done,{pass_SUITE,test_case,ok}},
++     {?eh,test_stats,{1,0,{0,0}}},
++     {?eh,tc_start,{ct_framework,end_per_suite}},
++     {?eh,tc_done,{ct_framework,end_per_suite,ok}}];
++test_suite_events(_) ->
++    [{?eh,tc_start,{surefire_SUITE,init_per_suite}},
+      {?eh,tc_done,{surefire_SUITE,init_per_suite,ok}},
+      {?eh,tc_start,{surefire_SUITE,tc_ok}},
+      {?eh,tc_done,{surefire_SUITE,tc_ok,ok}},
+@@ -216,9 +249,18 @@ test_events(_) ->
+ 			  {surefire_SUITE,init_per_group,
+ 			   {'EXIT',all_cases_should_be_skipped}}}}}],
+      {?eh,tc_start,{surefire_SUITE,end_per_suite}},
+-     {?eh,tc_done,{surefire_SUITE,end_per_suite,ok}},
+-     {?eh,stop_logging,[]}].
+-
++     {?eh,tc_done,{surefire_SUITE,end_per_suite,ok}}].
++
++test_events(fail_pre_init_per_suite) ->
++    [{?eh,start_logging,{'DEF','RUNDIR'}},
++     {?eh,start_info,{2,2,2}}] ++
++     test_suite_events(pass_SUITE) ++
++     test_suite_events(fail_SUITE, {1,0,{0,1}}) ++
++     [{?eh,stop_logging,[]}];
++test_events(Test) ->
++    [{?eh,start_logging,'_'}, {?eh,start_info,{1,1,9}}] ++
++    test_suite_events(Test) ++
++    [{?eh,stop_logging,[]}].
+ 
+ %%%-----------------------------------------------------------------
+ %%% Check generated xml log files
+@@ -251,9 +293,9 @@ do_check_xml(Case,[Xml|Xmls]) ->
+     {E,_} = xmerl_scan:file(Xml),
+     Expected = events_to_result(lists:flatten(test_events(Case))),
+     ParseResult = testsuites(Case,E),
+-    ct:log("Expecting: ~p~n",[[Expected]]),
++    ct:log("Expecting: ~p~n",[Expected]),
+     ct:log("Actual   : ~p~n",[ParseResult]),
+-    [Expected] = ParseResult,
++    Expected = ParseResult,
+     do_check_xml(Case,Xmls);
+ do_check_xml(_,[]) ->
+     ok.
+@@ -265,7 +307,8 @@ testsuites(Case,#xmlElement{name=testsuites,content=TS}) ->
+     testsuite(Case,TS).
+ 
+ testsuite(Case,[#xmlElement{name=testsuite,content=TC,attributes=A}|TS]) ->
+-    {ET,EF,ES} = events_to_numbers(lists:flatten(test_events(Case))),
++    TestSuiteEvents = test_suite_events(get_ts_name(A)),
++    {ET,EF,ES} = events_to_numbers(lists:flatten(TestSuiteEvents)),
+     {T,E,F,S} = get_numbers_from_attrs(A,false,false,false,false),
+     ct:log("Expecting total:~p, error:~p, failure:~p, skipped:~p~n",[ET,0,EF,ES]),
+     ct:log("Actual    total:~p, error:~p, failure:~p, skipped:~p~n",[T,E,F,S]),
+@@ -318,14 +361,32 @@ failed_or_skipped([]) ->
+ %% Testsuites = [Testsuite]
+ %% Testsuite = [Testcase]
+ %% Testcase = [] | [f] | [s], indicating ok, failed and skipped respectively
+-events_to_result([{?eh,tc_done,{_Suite,_Case,R}}|E]) ->
+-    [result(R)|events_to_result(E)];
+-events_to_result([{?eh,tc_auto_skip,_}|E]) ->
+-    [[s]|events_to_result(E)];
+-events_to_result([_|E]) ->
+-    events_to_result(E);
+-events_to_result([]) ->
+-    [].
++events_to_result(E) ->
++    events_to_result(E, []).
++
++events_to_result([{?eh,tc_auto_skip,{_Suite,init_per_suite,_}}|E], Result) ->
++    {Suite,Rest} = events_to_result1(E),
++    events_to_result(Rest, [[[s]|Suite]|Result]);
++events_to_result([{?eh,tc_done,{_Suite,init_per_suite,R}}|E], Result) ->
++    {Suite,Rest} = events_to_result1(E),
++    events_to_result(Rest, [[result(R)|Suite]|Result]);
++events_to_result([_|E], Result) ->
++    events_to_result(E, Result);
++events_to_result([], Result) ->
++    Result.
++
++events_to_result1([{?eh,tc_auto_skip,{_Suite, end_per_suite,_}}|E]) ->
++    {[[s]],E};
++events_to_result1([{?eh,tc_done,{_Suite, end_per_suite,R}}|E]) ->
++    {[result(R)],E};
++events_to_result1([{?eh,tc_done,{_Suite,_Case,R}}|E]) ->
++    {Suite,Rest} = events_to_result1(E),
++    {[result(R)|Suite],Rest};
++events_to_result1([{?eh,tc_auto_skip,_}|E]) ->
++    {Suite,Rest} = events_to_result1(E),
++    {[[s]|Suite],Rest};
++events_to_result1([_|E]) ->
++    events_to_result1(E).
+ 
+ result(ok) ->[];
+ result({skipped,_}) -> [s];
+@@ -374,3 +435,7 @@ del_files(Dir,[F0|Fs] ) ->
+     end;
+ del_files(_,[]) ->
+     ok.
++
++get_ts_name(Attributes) ->
++    {_,name,_,_,_,_,_,_,Name,_} = lists:keyfind(name, 2, Attributes),
++    list_to_atom(Name).
+--- /dev/null
++++ b/lib/common_test/test/ct_surefire_SUITE_data/fail_SUITE.erl
+@@ -0,0 +1,28 @@
++%% %CopyrightBegin%
++%%
++%% Copyright Ericsson AB 2016. All Rights Reserved.
++%%
++%% Licensed under the Apache License, Version 2.0 (the "License");
++%% you may not use this file except in compliance with the License.
++%% You may obtain a copy of the License at
++%%
++%%     http://www.apache.org/licenses/LICENSE-2.0
++%%
++%% Unless required by applicable law or agreed to in writing, software
++%% distributed under the License is distributed on an "AS IS" BASIS,
++%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++%% See the License for the specific language governing permissions and
++%% limitations under the License.
++%%
++%% %CopyrightEnd%
++%%
++-module(fail_SUITE).
++-include_lib("common_test/include/ct.hrl").
++
++-export([all/0, test_case/1]).
++
++all() ->
++    [test_case].
++
++test_case(_Config) ->
++    ok.
+--- /dev/null
++++ b/lib/common_test/test/ct_surefire_SUITE_data/fail_pre_init_per_suite.erl
+@@ -0,0 +1,47 @@
++%%
++%% %CopyrightBegin%
++%%
++%% Copyright Ericsson AB 2016. All Rights Reserved.
++%%
++%% Licensed under the Apache License, Version 2.0 (the "License");
++%% you may not use this file except in compliance with the License.
++%% You may obtain a copy of the License at
++%%
++%%     http://www.apache.org/licenses/LICENSE-2.0
++%%
++%% Unless required by applicable law or agreed to in writing, software
++%% distributed under the License is distributed on an "AS IS" BASIS,
++%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++%% See the License for the specific language governing permissions and
++%% limitations under the License.
++%%
++%% %CopyrightEnd%
++%%
++
++%%% This tests that the correct XML is produced when pre_init_per_suite
++%%% fails in a hook
++-module(fail_pre_init_per_suite).
++
++%% CT Hooks
++-export([init/2, pre_init_per_suite/3]).
++
++-type config() :: proplists:proplist().
++-type reason() :: term().
++-type skip_or_fail() :: skip | auto_skip | fail | 'EXIT'.
++
++-record(state, {}).
++
++-spec init(Id :: term(), Opts :: proplists:proplist()) ->
++    {ok, proplists:proplist()}.
++init(_Id, Opts) ->
++    {ok, Opts}.
++
++-spec pre_init_per_suite(Suite :: atom(),
++                         Config :: config(),
++                         State :: #state{}) ->
++    {config() | {skip_or_fail(), reason()}, NewState :: #state{}}.
++pre_init_per_suite(fail_SUITE, _Config, State) ->
++    {{fail, pre_init_per_suite}, State};
++pre_init_per_suite(_Suite, Config, State) ->
++    {Config, State}.
++
+--- /dev/null
++++ b/lib/common_test/test/ct_surefire_SUITE_data/pass_SUITE.erl
+@@ -0,0 +1,28 @@
++%% %CopyrightBegin%
++%%
++%% Copyright Ericsson AB 2016. All Rights Reserved.
++%%
++%% Licensed under the Apache License, Version 2.0 (the "License");
++%% you may not use this file except in compliance with the License.
++%% You may obtain a copy of the License at
++%%
++%%     http://www.apache.org/licenses/LICENSE-2.0
++%%
++%% Unless required by applicable law or agreed to in writing, software
++%% distributed under the License is distributed on an "AS IS" BASIS,
++%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++%% See the License for the specific language governing permissions and
++%% limitations under the License.
++%%
++%% %CopyrightEnd%
++%%
++-module(pass_SUITE).
++-include_lib("common_test/include/ct.hrl").
++
++-export([all/0, test_case/1]).
++
++all() ->
++    [test_case].
++
++test_case(_Config) ->
++    ok.
+--- a/lib/common_test/test/ct_test_support.erl
++++ b/lib/common_test/test/ct_test_support.erl
+@@ -43,6 +43,8 @@
+ 
+ -export([random_error/1]).
+ 
++-export([unique_timestamp/0]).
++
+ -include_lib("kernel/include/file.hrl").
+ 
+ %%%-----------------------------------------------------------------
+@@ -110,7 +112,8 @@ start_slave(NodeName, Config, Level) ->
+ 			      undefined -> [];
+ 			      Ds -> Ds
+ 			  end,
+-	    PathDirs = [PrivDir,TSDir | AddPathDirs],
++	    TestSupDir = filename:dirname(code:which(?MODULE)),
++	    PathDirs = [PrivDir,TSDir,TestSupDir | AddPathDirs],
+ 	    [true = rpc:call(CTNode, code, add_patha, [D]) || D <- PathDirs],
+ 	    test_server:format(Level, "Dirs added to code path (on ~w):~n",
+ 			       [CTNode]),
+@@ -1430,7 +1433,21 @@ rm_files([F | Fs]) ->
+     end;
+ rm_files([]) ->
+     ok.
+-    
++
++unique_timestamp() ->
++    unique_timestamp(os:timestamp(), 100000).
++
++unique_timestamp(TS, 0) ->
++    TS;
++unique_timestamp(TS0, N) ->
++    case os:timestamp() of
++	TS0 ->
++	    timer:sleep(1),
++	    unique_timestamp(TS0, N-1);
++	TS1 ->
++	    TS1
++    end.
++
+ %%%-----------------------------------------------------------------
+ %%%
+ slave_stop(Node) ->
+--- a/lib/common_test/vsn.mk
++++ b/lib/common_test/vsn.mk
+@@ -1 +1 @@
+-COMMON_TEST_VSN = 1.12
++COMMON_TEST_VSN = 1.12.1
+--- a/lib/inets/doc/src/notes.xml
++++ b/lib/inets/doc/src/notes.xml
+@@ -33,7 +33,40 @@
+     <file>notes.xml</file>
+   </header>
+   
+-  <section><title>Inets 6.2.2</title>
++  <section><title>Inets 6.2.4</title>
++
++    <section><title>Improvements and New Features</title>
++      <list>
++        <item>
++          <p>
++	    Handle multiple \t in mime types file</p>
++          <p>
++	    Own Id: OTP-13663 Aux Id: seq13132 </p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
++<section><title>Inets 6.2.3</title>
++
++    <section><title>Improvements and New Features</title>
++      <list>
++        <item>
++          <p>
++	    Put back unused module inets_regexp and remove it in OTP
++	    19 instead as it is an incompatibility, although it is an
++	    undocumented module and should not affect other
++	    applications.</p>
++          <p>
++	    Own Id: OTP-13533</p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
++<section><title>Inets 6.2.2</title>
+ 
+     <section><title>Improvements and New Features</title>
+       <list>
+--- a/lib/inets/src/http_server/httpd_conf.erl
++++ b/lib/inets/src/http_server/httpd_conf.erl
+@@ -1004,7 +1004,8 @@ read_config_file(Stream, SoFar) ->
+ 	    %% Ignore commented lines for efficiency later ..
+ 	    read_config_file(Stream, SoFar);
+ 	Line ->
+-	    NewLine = re:replace(clean(Line),"[\t\r\f ]"," ", [{return,list}]),
++	    NewLine = re:replace(white_space_clean(Line),
++				 "[\t\r\f ]"," ", [{return,list}, global]),
+ 	    case NewLine of
+ 		[] ->
+ 		    %% Also ignore empty lines ..
+@@ -1020,7 +1021,7 @@ parse_mime_types(Stream,MimeTypesList) ->
+ 	    eof ->
+ 		eof;
+ 	    String ->
+-		white_space_clean(String)
++		re:replace(white_space_clean(String), "[\t\r\f ]"," ", [{return,list}, global])	
+ 	end,
+     parse_mime_types(Stream, MimeTypesList, Line).
+ parse_mime_types(Stream, MimeTypesList, eof) ->
+@@ -1042,6 +1043,8 @@ parse_mime_types(Stream, MimeTypesList, Line) ->
+ 
+ suffixes(_MimeType,[]) ->
+     [];
++suffixes(MimeType,[""|Rest]) ->
++    suffixes(MimeType, Rest);
+ suffixes(MimeType,[Suffix|Rest]) ->
+     [{Suffix,MimeType}|suffixes(MimeType,Rest)].
+ 
+--- a/lib/inets/src/inets_app/Makefile
++++ b/lib/inets/src/inets_app/Makefile
+@@ -49,7 +49,8 @@ MODULES = \
+ 	inets_sup \
+ 	inets_trace \
+ 	inets_lib \
+-	inets_time_compat
++	inets_time_compat \
++	inets_regexp
+ 
+ INTERNAL_HRL_FILES = inets_internal.hrl
+ EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
+--- a/lib/inets/src/inets_app/inets.app.src
++++ b/lib/inets/src/inets_app/inets.app.src
+@@ -29,6 +29,7 @@
+ 	    inets_trace,
+             inets_lib,
+             inets_time_compat,
++	    inets_regexp,
+ 
+             %% FTP
+             ftp,
+--- a/lib/inets/src/inets_app/inets.appup.src
++++ b/lib/inets/src/inets_app/inets.appup.src
+@@ -18,16 +18,10 @@
+ %% %CopyrightEnd%
+ {"%VSN%",
+  [
+-  {<<"6.2.1">>, [{load_module, httpd_script_env, soft_purge, soft_purge, []}]},
+-  {<<"6.2">>,   [{load_module, httpd_script_env, soft_purge, soft_purge, []},
+-		 {load_module, httpc, soft_purge, soft_purge, []}]},
+   {<<"6\\..*">>,[{restart_application, inets}]},
+   {<<"5\\..*">>,[{restart_application, inets}]}
+  ],
+  [
+-  {<<"6.2.1">>, [{load_module, httpd_script_env, soft_purge, soft_purge, []}]},
+-  {<<"6.2">>,   [{load_module, httpd_script_env, soft_purge, soft_purge, []},
+-		 {load_module, httpc, soft_purge, soft_purge, []}]},
+   {<<"6\\..*">>,[{restart_application, inets}]},
+   {<<"5\\..*">>,[{restart_application, inets}]}
+  ]
+--- /dev/null
++++ b/lib/inets/src/inets_app/inets_regexp.erl
+@@ -0,0 +1,414 @@
++%%
++%% %CopyrightBegin%
++%% 
++%% Copyright Ericsson AB 2009. All Rights Reserved.
++%% 
++%% Licensed under the Apache License, Version 2.0 (the "License");
++%% you may not use this file except in compliance with the License.
++%% You may obtain a copy of the License at
++%%
++%%     http://www.apache.org/licenses/LICENSE-2.0
++%%
++%% Unless required by applicable law or agreed to in writing, software
++%% distributed under the License is distributed on an "AS IS" BASIS,
++%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++%% See the License for the specific language governing permissions and
++%% limitations under the License.
++%% 
++%% %CopyrightEnd%
++%%
++
++-module(inets_regexp).
++
++-export([parse/1, match/2, first_match/2, split/2, sub/3, gsub/3]).
++
++
++%%%=========================================================================
++%%%  API
++%%%=========================================================================
++
++%% parse(RegExp) -> {ok, RE} | {error, E}.
++%% Parse the regexp described in the string RegExp.
++
++parse(S) ->
++    case (catch reg(S)) of
++	{R, []} -> 
++	    {ok, R};
++	{_R, [C|_]} -> 
++	    {error, {illegal, [C]}};
++	{error, E} -> 
++	    {error, E}
++    end.
++
++
++%% Find the longest match of RegExp in String.
++
++match(S, RegExp) when is_list(RegExp) ->
++    case parse(RegExp) of
++	{ok,RE} -> match(S, RE);
++	{error,E} -> {error,E}
++    end;
++match(S, RE) ->
++    case match(RE, S, 1, 0, -1) of
++	{Start,Len} when Len >= 0 ->
++	    {match, Start, Len};
++	{_Start,_Len} -> 
++	    nomatch
++    end.
++
++%% Find the first match of RegExp in String.
++
++first_match(S, RegExp) when is_list(RegExp) ->
++    case parse(RegExp) of
++	{ok, RE} -> 
++	    first_match(S, RE);
++	{error, E} -> 
++	    {error, E}
++    end;
++first_match(S, RE) ->
++    case first_match(RE, S, 1) of
++	{Start,Len} when Len >= 0 ->
++	    {match, Start,Len};
++	nomatch -> 
++	    nomatch
++    end.
++
++first_match(RE, S, St) when S =/= [] ->
++    case re_apply(S, St, RE) of
++	{match, P, _Rest} -> 
++	    {St, P-St};
++	nomatch -> 
++	    first_match(RE, tl(S), St+1)
++    end;
++first_match(_RE, [], _St) -> 
++    nomatch.
++
++
++match(RE, S, St, Pos, L) ->
++    case first_match(RE, S, St) of
++	{St1, L1} ->
++	    Nst = St1 + 1,
++	    if L1 > L -> 
++		    match(RE, lists:nthtail(Nst-St, S), Nst, St1, L1);
++	       true -> 
++		    match(RE, lists:nthtail(Nst-St, S), Nst, Pos, L)
++	    end;
++	nomatch -> 
++	    {Pos, L}
++    end.
++
++
++%% Split a string into substrings where the RegExp describes the
++%% field seperator. The RegExp " " is specially treated.
++
++split(String, " ") ->				%This is really special
++    {ok, RE} = parse("[ \t]+"),
++    case split_apply(String, RE, true) of
++	[[]|Ss] -> 
++	    {ok,Ss};
++	Ss -> 
++	    {ok,Ss}
++    end;
++split(String, RegExp) when is_list(RegExp) ->
++    case parse(RegExp) of
++	{ok, RE} -> 
++	    {ok, split_apply(String, RE, false)};
++	{error, E} -> 
++	    {error,E}
++    end;
++split(String, RE) -> 
++    {ok, split_apply(String, RE, false)}.
++
++
++%% Substitute the first match of the regular expression RegExp 
++%% with the string Replace in String. Accept pre-parsed regular
++%% expressions.
++
++sub(String, RegExp, Rep) when is_list(RegExp) ->
++    case parse(RegExp) of
++	{ok, RE} -> 
++	    sub(String, RE, Rep);
++	{error, E} -> 
++	    {error, E}
++    end;
++sub(String, RE, Rep) ->
++    Ss = sub_match(String, RE, 1),
++    {ok, sub_repl(Ss, Rep, String, 1), length(Ss)}.
++
++
++%% Substitute every match of the regular expression RegExp with 
++%% the string New in String. Accept pre-parsed regular expressions.
++
++gsub(String, RegExp, Rep) when is_list(RegExp) ->
++    case parse(RegExp) of
++	{ok, RE} -> 
++	    gsub(String, RE, Rep);
++	{error, E} -> 
++	    {error, E}
++    end;
++gsub(String, RE, Rep) ->
++    Ss = matches(String, RE, 1),
++    {ok, sub_repl(Ss, Rep, String, 1), length(Ss)}.
++
++
++%%%========================================================================
++%%% Internal functions
++%%%========================================================================
++
++%% This is the regular expression grammar used. It is equivalent to the
++%% one used in AWK, except that we allow ^ $ to be used anywhere and fail
++%% in the matching.
++%%
++%% reg -> reg1 : '$1'.
++%% reg1 -> reg1 "|" reg2 : {'or','$1','$2'}.
++%% reg1 -> reg2 : '$1'.
++%% reg2 -> reg2 reg3 : {concat,'$1','$2'}.
++%% reg2 -> reg3 : '$1'.
++%% reg3 -> reg3 "*" : {kclosure,'$1'}.
++%% reg3 -> reg3 "+" : {pclosure,'$1'}.
++%% reg3 -> reg3 "?" : {optional,'$1'}.
++%% reg3 -> reg4 : '$1'.
++%% reg4 -> "(" reg ")" : '$2'.
++%% reg4 -> "\\" char : '$2'.
++%% reg4 -> "^" : bos.
++%% reg4 -> "$" : eos.
++%% reg4 -> "." : char.
++%% reg4 -> "[" class "]" : {char_class,char_class('$2')}
++%% reg4 -> "[" "^" class "]" : {comp_class,char_class('$3')}
++%% reg4 -> "\"" chars "\"" : char_string('$2')
++%% reg4 -> char : '$1'.
++%% reg4 -> empty : epsilon.
++%%  The grammar of the current regular expressions. The actual parser
++%%  is a recursive descent implementation of the grammar.
++
++reg(S) -> reg1(S).
++
++%% reg1 -> reg2 reg1'
++%% reg1' -> "|" reg2
++%% reg1' -> empty
++
++reg1(S0) ->
++    {L,S1} = reg2(S0),
++    reg1p(S1, L).
++
++reg1p([$||S0], L) ->
++    {R,S1} = reg2(S0),
++    reg1p(S1, {'or',L,R});
++reg1p(S, L) -> {L,S}.
++
++%% reg2 -> reg3 reg2'
++%% reg2' -> reg3
++%% reg2' -> empty
++
++reg2(S0) ->
++    {L,S1} = reg3(S0),
++    reg2p(S1, L).
++
++reg2p([C|S0], L) when (C =/= $|) andalso (C =/= $)) ->
++    {R,S1} = reg3([C|S0]),
++    reg2p(S1, {concat,L,R});
++reg2p(S, L) -> {L,S}.
++
++%% reg3 -> reg4 reg3'
++%% reg3' -> "*" reg3'
++%% reg3' -> "+" reg3'
++%% reg3' -> "?" reg3'
++%% reg3' -> empty
++
++reg3(S0) ->
++    {L,S1} = reg4(S0),
++    reg3p(S1, L).
++
++reg3p([$*|S], L) -> reg3p(S, {kclosure,L});
++reg3p([$+|S], L) -> reg3p(S, {pclosure,L});
++reg3p([$?|S], L) -> reg3p(S, {optional,L});
++reg3p(S, L) -> {L,S}.
++
++reg4([$(|S0]) ->
++    case reg(S0) of
++	{R,[$)|S1]} -> {R,S1};
++	{_R,_S} -> throw({error,{unterminated,"("}})
++    end;
++reg4([$\\,O1,O2,O3|S]) 
++  when ((O1 >= $0) andalso 
++	(O1 =< $7) andalso 
++	(O2 >= $0) andalso 
++	(O2 =< $7) andalso 
++	(O3 >= $0) andalso 
++	(O3 =< $7)) ->
++    {(O1*8 + O2)*8 + O3 - 73*$0,S};
++reg4([$\\,C|S]) -> 
++    {escape_char(C),S};
++reg4([$\\]) -> 
++    throw({error, {unterminated,"\\"}});
++reg4([$^|S]) -> 
++    {bos,S};
++reg4([$$|S]) -> 
++    {eos,S};
++reg4([$.|S]) -> 
++    {{comp_class,"\n"},S};
++reg4("[^" ++ S0) ->
++    case char_class(S0) of
++	{Cc,[$]|S1]} -> {{comp_class,Cc},S1};
++	{_Cc,_S} -> throw({error,{unterminated,"["}})
++    end;
++reg4([$[|S0]) ->
++    case char_class(S0) of
++	{Cc,[$]|S1]} -> {{char_class,Cc},S1};
++	{_Cc,_S1} -> throw({error,{unterminated,"["}})
++    end;
++reg4([C|S]) 
++  when (C =/= $*) andalso (C =/= $+) andalso (C =/= $?) andalso (C =/= $]) -> 
++    {C, S};
++reg4([C|_S]) -> 
++    throw({error,{illegal,[C]}});
++reg4([]) -> 
++    {epsilon,[]}.
++
++escape_char($n) -> $\n;				%\n = LF
++escape_char($r) -> $\r;				%\r = CR
++escape_char($t) -> $\t;				%\t = TAB
++escape_char($v) -> $\v;				%\v = VT
++escape_char($b) -> $\b;				%\b = BS
++escape_char($f) -> $\f;				%\f = FF
++escape_char($e) -> $\e;				%\e = ESC
++escape_char($s) -> $\s;				%\s = SPACE
++escape_char($d) -> $\d;				%\d = DEL
++escape_char(C) -> C.
++
++char_class([$]|S]) -> char_class(S, [$]]);
++char_class(S) -> char_class(S, []).
++
++char($\\, [O1,O2,O3|S]) when
++  O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
++    {(O1*8 + O2)*8 + O3 - 73*$0,S};
++char($\\, [C|S]) -> {escape_char(C),S};
++char(C, S) -> {C,S}.
++
++char_class([C1|S0], Cc) when C1 =/= $] ->
++    case char(C1, S0) of
++	{Cf,[$-,C2|S1]} when C2 =/= $] ->
++	    case char(C2, S1) of
++		{Cl,S2} when Cf < Cl -> char_class(S2, [{Cf,Cl}|Cc]); 
++		{Cl,_S2} -> throw({error,{char_class,[Cf,$-,Cl]}})
++	    end;
++	{C,S1} -> char_class(S1, [C|Cc])
++    end;
++char_class(S, Cc) -> {Cc,S}.
++
++
++%% re_apply(String, StartPos, RegExp) -> re_app_res().
++%%
++%%  Apply the (parse of the) regular expression RegExp to String.  If
++%%  there is a match return the position of the remaining string and
++%%  the string if else return 'nomatch'. BestMatch specifies if we want
++%%  the longest match, or just a match.
++%%
++%%  StartPos should be the real start position as it is used to decide
++%%  if we ae at the beginning of the string.
++%%
++%%  Pass two functions to re_apply_or so it can decide, on the basis
++%%  of BestMatch, whether to just any take any match or try both to
++%%  find the longest. This is slower but saves duplicatng code.
++
++re_apply(S, St, RE) -> re_apply(RE, [], S, St).
++
++re_apply(epsilon, More, S, P) ->		%This always matches
++    re_apply_more(More, S, P);
++re_apply({'or',RE1,RE2}, More, S, P) ->
++    re_apply_or(re_apply(RE1, More, S, P),
++		re_apply(RE2, More, S, P));
++re_apply({concat,RE1,RE2}, More, S0, P) ->
++    re_apply(RE1, [RE2|More], S0, P);
++re_apply({kclosure,CE}, More, S, P) ->
++    %% Be careful with the recursion, explicitly do one call before
++    %% looping.
++    re_apply_or(re_apply_more(More, S, P),
++		re_apply(CE, [{kclosure,CE}|More], S, P));
++re_apply({pclosure,CE}, More, S, P) ->
++    re_apply(CE, [{kclosure,CE}|More], S, P);
++re_apply({optional,CE}, More, S, P) ->
++    re_apply_or(re_apply_more(More, S, P),
++		re_apply(CE, More, S, P));
++re_apply(bos, More, S, 1) -> re_apply_more(More, S, 1);
++re_apply(eos, More, [$\n|S], P) -> re_apply_more(More, S, P);
++re_apply(eos, More, [], P) -> re_apply_more(More, [], P);
++re_apply({char_class,Cc}, More, [C|S], P) ->
++    case in_char_class(C, Cc) of
++	true -> re_apply_more(More, S, P+1);
++	false -> nomatch
++    end;
++re_apply({comp_class,Cc}, More, [C|S], P) ->
++    case in_char_class(C, Cc) of
++	true -> nomatch;
++	false -> re_apply_more(More, S, P+1)
++    end;
++re_apply(C, More, [C|S], P) when is_integer(C) ->
++    re_apply_more(More, S, P+1);
++re_apply(_RE, _More, _S, _P) -> nomatch.
++
++%% re_apply_more([RegExp], String, Length) -> re_app_res().
++
++re_apply_more([RE|More], S, P) -> re_apply(RE, More, S, P);
++re_apply_more([], S, P) -> {match,P,S}.
++
++%% in_char_class(Char, Class) -> bool().
++
++in_char_class(C, [{C1,C2}|_Cc]) when C >= C1, C =< C2 -> true;
++in_char_class(C, [C|_Cc]) -> true;
++in_char_class(C, [_|Cc]) -> in_char_class(C, Cc);
++in_char_class(_C, []) -> false.
++
++%% re_apply_or(Match1, Match2) -> re_app_res().
++%%  If we want the best match then choose the longest match, else just
++%%  choose one by trying sequentially.
++
++re_apply_or({match,P1,S1},   {match,P2,_S2}) when P1 >= P2 -> {match,P1,S1};
++re_apply_or({match,_P1,_S1}, {match,P2,S2}) -> {match,P2,S2};
++re_apply_or(nomatch, R2) -> R2;
++re_apply_or(R1, nomatch) -> R1.
++
++
++matches(S, RE, St) ->
++    case first_match(RE, S, St) of
++	{St1,0} -> 
++	    [{St1,0}|matches(string:substr(S, St1+2-St), RE, St1+1)];
++	{St1,L1} -> 
++	    [{St1,L1}|matches(string:substr(S, St1+L1+1-St), RE, St1+L1)];
++	nomatch -> 
++	    []
++    end.
++
++sub_match(S, RE, St) ->
++    case first_match(RE, S, St) of
++	{St1,L1} -> [{St1,L1}];
++	nomatch -> []
++    end.
++
++sub_repl([{St,L}|Ss], Rep, S, Pos) ->
++    Rs = sub_repl(Ss, Rep, S, St+L),
++    string:substr(S, Pos, St-Pos) ++ 
++	sub_repl(Rep, string:substr(S, St, L), Rs);
++sub_repl([], _Rep, S, Pos) -> 
++    string:substr(S, Pos).
++
++sub_repl([$&|Rep], M, Rest) -> M ++ sub_repl(Rep, M, Rest);
++sub_repl("\\&" ++ Rep, M, Rest) -> [$&|sub_repl(Rep, M, Rest)];
++sub_repl([C|Rep], M, Rest) -> [C|sub_repl(Rep, M, Rest)];
++sub_repl([], _M, Rest) -> Rest.
++
++split_apply(S, RE, Trim) -> split_apply(S, 1, RE, Trim, []).
++
++split_apply([], _P, _RE, true, []) -> 
++    [];
++split_apply([], _P, _RE, _T, Sub) -> 
++    [lists:reverse(Sub)];
++split_apply(S, P, RE, T, Sub) ->
++    case re_apply(S, P, RE) of
++	{match,P,_Rest} ->
++	    split_apply(tl(S), P+1, RE, T, [hd(S)|Sub]);
++	{match,P1,Rest} ->
++	    [lists:reverse(Sub)|split_apply(Rest, P1, RE, T, [])];
++	nomatch ->
++	    split_apply(tl(S), P+1, RE, T, [hd(S)|Sub])
++    end.
+--- a/lib/inets/test/httpd_SUITE.erl
++++ b/lib/inets/test/httpd_SUITE.erl
+@@ -70,7 +70,8 @@ all() ->
+      {group, https_security},
+      {group, http_reload},
+      {group, https_reload},
+-     {group, http_mime_types} 
++     {group, http_mime_types},
++     mime_types_format
+     ].
+ 
+ groups() ->
+@@ -1291,6 +1292,115 @@ non_disturbing(Config) when is_list(Config)->
+     inets_test_lib:close(Type, Socket),
+     [{server_name, "httpd_non_disturbing_" ++ Version}] =  httpd:info(Server, [server_name]).
+ 
++%%-------------------------------------------------------------------------
++mime_types_format(Config) when is_list(Config) -> 
++    DataDir = proplists:get_value(data_dir, Config),
++    MimeTypes = filename:join(DataDir, "mime_types.txt"),
++    {ok,[{"wrl","x-world/x-vrml"},
++     {"vrml","x-world/x-vrml"},
++     {"ice","x-conference/x-cooltalk"},
++     {"movie","video/x-sgi-movie"},
++     {"avi","video/x-msvideo"},
++     {"qt","video/quicktime"},
++     {"mov","video/quicktime"},
++     {"mpeg","video/mpeg"},
++     {"mpg","video/mpeg"},
++     {"mpe","video/mpeg"},
++     {"sgml","text/x-sgml"},
++     {"sgm","text/x-sgml"},
++     {"etx","text/x-setext"},
++     {"tsv","text/tab-separated-values"},
++     {"rtx","text/richtext"},
++     {"txt","text/plain"},
++     {"html","text/html"},
++     {"htm","text/html"},
++     {"css","text/css"},
++     {"xwd","image/x-xwindowdump"},
++     {"xpm","image/x-xpixmap"},
++     {"xbm","image/x-xbitmap"},
++     {"rgb","image/x-rgb"},
++     {"ppm","image/x-portable-pixmap"},
++     {"pgm","image/x-portable-graymap"},
++     {"pbm","image/x-portable-bitmap"},
++     {"pnm","image/x-portable-anymap"},
++     {"ras","image/x-cmu-raster"},
++     {"tiff","image/tiff"},
++     {"tif","image/tiff"},
++     {"png","image/png"},
++     {"jpeg","image/jpeg"},
++     {"jpg","image/jpeg"},
++     {"jpe","image/jpeg"},
++     {"ief","image/ief"},
++     {"gif","image/gif"},
++     {"pdb","chemical/x-pdb"},
++     {"xyz","chemical/x-pdb"},
++     {"wav","audio/x-wav"},
++     {"ra","audio/x-realaudio"},
++     {"rpm","audio/x-pn-realaudio-plugin"},
++     {"ram","audio/x-pn-realaudio"},
++     {"aif","audio/x-aiff"},
++     {"aiff","audio/x-aiff"},
++     {"aifc","audio/x-aiff"},
++     {"mpga","audio/mpeg"},
++     {"mp2","audio/mpeg"},
++     {"au","audio/basic"},
++     {"snd","audio/basic"},
++     {"zip","application/zip"},
++     {"src","application/x-wais-source"},
++     {"ustar","application/x-ustar"},
++     {"ms","application/x-troff-ms"},
++     {"me","application/x-troff-me"},
++     {"man","application/x-troff-man"},
++     {"t","application/x-troff"},
++     {"tr","application/x-troff"},
++     {"roff","application/x-troff"},
++     {"texinfo","application/x-texinfo"},
++     {"texi","application/x-texinfo"},
++     {"tex","application/x-tex"},
++     {"tcl","application/x-tcl"},
++     {"tar","application/x-tar"},
++     {"sv4crc","application/x-sv4crc"},
++     {"sv4cpio","application/x-sv4cpio"},
++     {"sit","application/x-stuffit"},
++     {"shar","application/x-shar"},
++     {"sh","application/x-sh"},
++     {"nc","application/x-netcdf"},
++     {"cdf","application/x-netcdf"},
++     {"mif","application/x-mif"},
++     {"latex","application/x-latex"},
++     {"skp","application/x-koan"},
++     {"skd","application/x-koan"},
++     {"skt","application/x-koan"},
++     {"skm","application/x-koan"},
++     {"cgi","application/x-httpd-cgi"},
++     {"hdf","application/x-hdf"},
++     {"gz","application/x-gzip"},
++     {"gtar","application/x-gtar"},
++     {"dvi","application/x-dvi"},
++     {"dcr","application/x-director"},
++     {"dir","application/x-director"},
++     {"dxr","application/x-director"},
++     {"csh","application/x-csh"},
++     {"cpio","application/x-cpio"},
++     {"Z","application/x-compress"},
++     {"vcd","application/x-cdlink"},
++     {"bcpio","application/x-bcpio"},
++     {"rtf","application/rtf"},
++     {"ppt","application/powerpoint"},
++     {"ai","application/postscript"},
++     {"eps","application/postscript"},
++     {"ps","application/postscript"},
++     {"pdf","application/pdf"},
++     {"oda","application/oda"},
++     {"bin","application/octet-stream"},
++     {"dms","application/octet-stream"},
++     {"lha","application/octet-stream"},
++     {"lzh","application/octet-stream"},
++     {"exe","application/octet-stream"},
++     {"class","application/octet-stream"},
++     {"doc","application/msword"},
++     {"cpt","application/mac-compactpro"},
++     {"hqx","application/mac-binhex40"}]} = httpd_conf:load_mime_types(MimeTypes).
+ 
+ %%--------------------------------------------------------------------
+ %% Internal functions -----------------------------------
+--- /dev/null
++++ b/lib/inets/test/httpd_SUITE_data/mime_types.txt
+@@ -0,0 +1,100 @@
++# This is a comment. I love comments.
++
++
++application/activemessage
++application/andrew-inset
++application/applefile
++application/atomicmail
++application/dca-rft
++application/dec-dx
++application/mac-binhex40	hqx
++application/mac-compactpro	cpt
++application/macwriteii
++application/msword		doc
++application/news-message-id
++application/news-transmission
++application/octet-stream	bin dms lha lzh exe class
++application/oda			oda
++application/pdf			pdf
++application/postscript		ai eps ps
++application/powerpoint		ppt
++application/remote-printing
++application/rtf			rtf
++application/slate
++application/wita
++application/wordperfect5.1
++application/x-bcpio		bcpio
++application/x-cdlink		vcd
++application/x-compress		Z
++application/x-cpio		cpio
++application/x-csh		csh
++application/x-director		dcr dir dxr
++application/x-dvi		dvi
++application/x-gtar		gtar
++application/x-gzip		gz
++application/x-hdf		hdf
++application/x-httpd-cgi		cgi
++application/x-koan		skp skd skt skm
++application/x-latex		latex
++application/x-mif		mif
++application/x-netcdf		nc cdf
++application/x-sh		sh
++application/x-shar		shar
++application/x-stuffit		sit
++application/x-sv4cpio		sv4cpio
++application/x-sv4crc		sv4crc
++application/x-tar		tar
++application/x-tcl		tcl
++application/x-tex		tex
++application/x-texinfo		texinfo texi
++application/x-troff		t tr roff
++application/x-troff-man		man
++application/x-troff-me		me
++application/x-troff-ms		ms
++application/x-ustar		ustar
++application/x-wais-source	src
++application/zip			zip
++audio/basic			au snd
++audio/mpeg			mpga mp2
++audio/x-aiff			aif aiff aifc
++audio/x-pn-realaudio		ram
++audio/x-pn-realaudio-plugin	rpm
++audio/x-realaudio		ra
++audio/x-wav			wav
++chemical/x-pdb			pdb xyz
++image/gif			gif
++image/ief			ief
++image/jpeg			jpeg jpg jpe
++image/png			png
++image/tiff			tiff tif
++image/x-cmu-raster		ras
++image/x-portable-anymap		pnm
++image/x-portable-bitmap		pbm
++image/x-portable-graymap	pgm
++image/x-portable-pixmap		ppm
++image/x-rgb			rgb
++image/x-xbitmap			xbm
++image/x-xpixmap			xpm
++image/x-xwindowdump		xwd
++message/external-body
++message/news
++message/partial
++message/rfc822
++multipart/alternative
++multipart/appledouble
++multipart/digest
++multipart/mixed
++multipart/parallel
++text/css			css
++text/html			html htm
++text/plain			txt
++text/richtext			rtx
++text/tab-separated-values	tsv
++text/x-setext			etx
++text/x-sgml			sgml sgm
++video/mpeg			mpeg mpg mpe
++video/quicktime			qt mov
++video/x-msvideo			avi
++video/x-sgi-movie		movie
++x-conference/x-cooltalk		ice
++x-world/x-vrml			wrl vrml
+--- a/lib/inets/vsn.mk
++++ b/lib/inets/vsn.mk
+@@ -19,6 +19,6 @@
+ # %CopyrightEnd%
+ 
+ APPLICATION = inets
+-INETS_VSN   = 6.2.2
++INETS_VSN   = 6.2.4
+ PRE_VSN     =
+ APP_VSN     = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
+--- a/lib/ssl/doc/src/notes.xml
++++ b/lib/ssl/doc/src/notes.xml
+@@ -28,6 +28,68 @@
+   <p>This document describes the changes made to the SSL application.</p>
+ 
+ 
++<section><title>SSL 7.3.3</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    Correct ssl:prf/5 to use the negotiated cipher suite's
++	    prf function in ssl:prf/5 instead of the default prf.</p>
++          <p>
++	    Own Id: OTP-13546</p>
++        </item>
++        <item>
++          <p>
++	    Timeouts may have the value 0, guards have been corrected
++	    to allow this</p>
++          <p>
++	    Own Id: OTP-13635</p>
++        </item>
++        <item>
++          <p>
++	    Change of internal handling of hash sign pairs as the
++	    used one enforced to much restrictions making some valid
++	    combinations unavailable.</p>
++          <p>
++	    Own Id: OTP-13670</p>
++        </item>
++      </list>
++    </section>
++
++
++    <section><title>Improvements and New Features</title>
++      <list>
++        <item>
++          <p>
++	    Create a little randomness in sending of session
++	    invalidation messages, to mitigate load when whole table
++	    is invalidated.</p>
++          <p>
++	    Own Id: OTP-13490</p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
++<section><title>SSL 7.3.2</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    Correct cipher suites conversion and gaurd expression.
++	    Caused problems with GCM cipher suites and client side
++	    option to set signature_algorithms extention values.</p>
++          <p>
++	    Own Id: OTP-13525</p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>SSL 7.3.1</title>
+ 
+     <section><title>Fixed Bugs and Malfunctions</title>
+--- a/lib/ssl/src/ssl.erl
++++ b/lib/ssl/src/ssl.erl
+@@ -97,7 +97,7 @@ connect(Socket, SslOptions) when is_port(Socket) ->
+     connect(Socket, SslOptions, infinity).
+ 
+ connect(Socket, SslOptions0, Timeout) when is_port(Socket),
+-					    (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->
++					    (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions0,
+ 					      {gen_tcp, tcp, tcp_closed, tcp_error}),
+     EmulatedOptions = ssl_socket:emulated_options(),
+@@ -123,7 +123,7 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket),
+ connect(Host, Port, Options) ->
+     connect(Host, Port, Options, infinity).
+ 
+-connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->
++connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     try handle_options(Options, client) of
+ 	{ok, Config} ->
+ 	    do_connect(Host,Port,Config,Timeout)
+@@ -173,7 +173,7 @@ transport_accept(#sslsocket{pid = {ListenSocket,
+ 				   #config{transport_info =  {Transport,_,_, _} =CbInfo,
+ 					   connection_cb = ConnectionCb,
+ 					   ssl = SslOpts,
+-					   emulated = Tracker}}}, Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->   
++					   emulated = Tracker}}}, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     case Transport:accept(ListenSocket, Timeout) of
+ 	{ok, Socket} ->
+ 	    {ok, EmOpts} = ssl_socket:get_emulated_opts(Tracker),
+@@ -206,25 +206,25 @@ transport_accept(#sslsocket{pid = {ListenSocket,
+ ssl_accept(ListenSocket) ->
+     ssl_accept(ListenSocket, infinity).
+ 
+-ssl_accept(#sslsocket{} = Socket, Timeout) when  (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->
++ssl_accept(#sslsocket{} = Socket, Timeout) when  (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     ssl_connection:handshake(Socket, Timeout);
+-    
+-ssl_accept(ListenSocket, SslOptions)  when is_port(ListenSocket) -> 
++
++ssl_accept(ListenSocket, SslOptions)  when is_port(ListenSocket) ->
+     ssl_accept(ListenSocket, SslOptions, infinity).
+ 
+-ssl_accept(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)->
++ssl_accept(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
+     ssl_accept(#sslsocket{} = Socket, Timeout);
+-ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) when 
+-      (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)->
+-    try 
+-	{ok, EmOpts, InheritedSslOpts} = ssl_socket:get_all_opts(Tracker),	
++ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts0, Timeout) when
++      (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
++    try
++	{ok, EmOpts, InheritedSslOpts} = ssl_socket:get_all_opts(Tracker),
+ 	SslOpts = handle_options(SslOpts0, InheritedSslOpts),
+ 	ssl_connection:handshake(Socket, {SslOpts, emulated_socket_options(EmOpts, #socket_options{})}, Timeout)
+     catch
+ 	Error = {error, _Reason} -> Error
+     end;
+ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket),
+-					     (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) -> 
++					     (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     {Transport,_,_,_} =
+ 	proplists:get_value(cb_info, SslOptions, {gen_tcp, tcp, tcp_closed, tcp_error}),
+     EmulatedOptions = ssl_socket:emulated_options(),
+@@ -252,17 +252,17 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}
+     Transport:close(ListenSocket).
+ 
+ %%--------------------------------------------------------------------
+--spec  close(#sslsocket{}, integer() | {pid(), integer()}) -> term().
++-spec  close(#sslsocket{}, timeout() | {pid(), integer()}) -> term().
+ %%
+ %% Description: Close an ssl connection
+ %%--------------------------------------------------------------------
+-close(#sslsocket{pid = TLSPid}, 
+-      {Pid, Timeout} = DownGrade) when is_pid(TLSPid), 
+-				       is_pid(Pid), 
+-				       (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->
++close(#sslsocket{pid = TLSPid},
++      {Pid, Timeout} = DownGrade) when is_pid(TLSPid),
++				       is_pid(Pid),
++				       (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     ssl_connection:close(TLSPid, {close, DownGrade});
+-close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid), 
+-					      (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity) ->
++close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid),
++					      (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+     ssl_connection:close(TLSPid, {close, Timeout});
+ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) ->
+     Transport:close(ListenSocket).
+@@ -286,7 +286,7 @@ send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _}
+ recv(Socket, Length) ->
+     recv(Socket, Length, infinity).
+ recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid),
+-						  (is_integer(Timeout) andalso Timeout > 0) or (Timeout == infinity)->
++						  (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
+     ssl_connection:recv(Pid, Length, Timeout);
+ recv(#sslsocket{pid = {Listen,
+ 		       #config{transport_info = {Transport, _, _, _}}}}, _,_) when is_port(Listen)->
+--- a/lib/ssl/src/ssl_cipher.erl
++++ b/lib/ssl/src/ssl_cipher.erl
+@@ -979,21 +979,21 @@ suite({ecdh_rsa, aes_256_cbc, sha384, sha384}) ->
+ %% RFC 5288 AES-GCM Cipher Suites
+ suite({rsa, aes_128_gcm, null, sha256}) ->
+     ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+-suite({rsa, aes_256_gcm, null}) ->
++suite({rsa, aes_256_gcm, null, sha384}) ->
+     ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+-suite({dhe_rsa, aes_128_gcm, null, sha384}) ->
++suite({dhe_rsa, aes_128_gcm, null, sha256}) ->
+     ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+-suite({dhe_rsa, aes_256_gcm, null, sha256}) ->
++suite({dhe_rsa, aes_256_gcm, null, sha384}) ->
+     ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+-suite({dh_rsa, aes_128_gcm, null, sha384}) ->
++suite({dh_rsa, aes_128_gcm, null, sha256}) ->
+     ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+-suite({dh_rsa, aes_256_gcm, null, sha256}) ->
++suite({dh_rsa, aes_256_gcm, null, sha384}) ->
+     ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+-suite({dhe_dss, aes_128_gcm, null, sha384}) ->
++suite({dhe_dss, aes_128_gcm, null, sha256}) ->
+     ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+-suite({dhe_dss, aes_256_gcm, null, sha256}) ->
++suite({dhe_dss, aes_256_gcm, null, sha384}) ->
+     ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+-suite({dh_dss, aes_128_gcm, null, sha384}) ->
++suite({dh_dss, aes_128_gcm, null, sha256}) ->
+     ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+ suite({dh_dss, aes_256_gcm, null, sha384}) ->
+     ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+--- a/lib/ssl/src/ssl_connection.erl
++++ b/lib/ssl/src/ssl_connection.erl
+@@ -821,7 +821,8 @@ handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName,
+     SecParams = ConnectionState#connection_state.security_parameters,
+     #security_parameters{master_secret = MasterSecret,
+ 			 client_random = ClientRandom,
+-			 server_random = ServerRandom} = SecParams,
++			 server_random = ServerRandom,
++			 prf_algorithm = PRFAlgorithm} = SecParams,
+     Reply = try
+ 		SecretToUse = case Secret of
+ 				  _ when is_binary(Secret) -> Secret;
+@@ -832,7 +833,7 @@ handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName,
+ 					     (client_random, Acc) -> [ClientRandom|Acc];
+ 					     (server_random, Acc) -> [ServerRandom|Acc]
+ 					  end, [], Seed)),
+-		ssl_handshake:prf(Version, SecretToUse, Label, SeedToUse, WantedLength)
++		ssl_handshake:prf(Version, PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength)
+ 	    catch
+ 		exit:_ -> {error, badarg};
+ 		error:Reason -> {error, Reason}
+--- a/lib/ssl/src/ssl_handshake.erl
++++ b/lib/ssl/src/ssl_handshake.erl
+@@ -74,7 +74,7 @@
+ 	]).
+ 
+ %% MISC
+--export([select_version/3, prf/5, select_hashsign/5, 
++-export([select_version/3, prf/6, select_hashsign/5,
+ 	 select_hashsign_algs/3,
+ 	 premaster_secret/2, premaster_secret/3, premaster_secret/4]).
+ 
+@@ -564,17 +564,15 @@ server_key_exchange_hash(md5sha, Value) ->
+ server_key_exchange_hash(Hash, Value) ->
+     crypto:hash(Hash, Value).
+ %%--------------------------------------------------------------------
+--spec prf(ssl_record:ssl_version(), binary(), binary(), [binary()], non_neg_integer()) ->
++-spec prf(ssl_record:ssl_version(), non_neg_integer(), binary(), binary(), [binary()], non_neg_integer()) ->
+ 		 {ok, binary()} | {error, undefined}.
+ %%
+ %% Description: use the TLS PRF to generate key material
+ %%--------------------------------------------------------------------
+-prf({3,0}, _, _, _, _) ->
++prf({3,0}, _, _, _, _, _) ->
+     {error, undefined};
+-prf({3,1}, Secret, Label, Seed, WantedLength) ->
+-    {ok, tls_v1:prf(?MD5SHA, Secret, Label, Seed, WantedLength)};
+-prf({3,_N}, Secret, Label, Seed, WantedLength) ->
+-    {ok, tls_v1:prf(?SHA256, Secret, Label, Seed, WantedLength)}.
++prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) ->
++    {ok, tls_v1:prf(PRFAlgo, Secret, Label, Seed, WantedLength)}.
+ 
+ 
+ %%--------------------------------------------------------------------
+--- a/lib/ssl/src/ssl_manager.erl
++++ b/lib/ssl/src/ssl_manager.erl
+@@ -67,6 +67,7 @@
+ -define(CLEAN_SESSION_DB, 60000).
+ -define(CLEAN_CERT_DB, 500).
+ -define(DEFAULT_MAX_SESSION_CACHE, 1000).
++-define(LOAD_MITIGATION, 10).
+ 
+ %%====================================================================
+ %% API
+@@ -196,10 +197,12 @@ register_session(Port, Session) ->
+ %%--------------------------------------------------------------------
+ -spec invalidate_session(host(), inet:port_number(), #session{}) -> ok.
+ invalidate_session(Host, Port, Session) ->
++    load_mitigation(),
+     cast({invalidate_session, Host, Port, Session}).
+ 
+ -spec invalidate_session(inet:port_number(), #session{}) -> ok.
+ invalidate_session(Port, Session) ->
++    load_mitigation(),
+     cast({invalidate_session, Port, Session}).
+ 
+ -spec invalidate_pem(File::binary()) -> ok.
+@@ -719,3 +722,11 @@ invalidate_session_cache(undefined, CacheCb, Cache) ->
+     start_session_validator(Cache, CacheCb, {invalidate_before, erlang:monotonic_time()}, undefined);
+ invalidate_session_cache(Pid, _CacheCb, _Cache) ->
+     Pid.
++
++load_mitigation() ->
++    MSec = rand:uniform(?LOAD_MITIGATION),
++    receive 
++    after 
++	MSec ->
++	    continue
++    end.
+--- a/lib/ssl/src/tls_handshake.erl
++++ b/lib/ssl/src/tls_handshake.erl
+@@ -278,11 +278,13 @@ handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
+ 	    {Version, SessionId, ConnectionStates, ProtoExt, Protocol}
+     end.
+ 
+-available_signature_algs(undefined, SupportedHashSigns, _, {Major, Minor}) when (Major < 3) andalso (Minor < 3) ->
++available_signature_algs(undefined, SupportedHashSigns, _, {Major, Minor}) when 
++      (Major >= 3) andalso (Minor >= 3) ->
+     SupportedHashSigns;
+ available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns, 
+-		     _, {Major, Minor}) when (Major < 3) andalso (Minor < 3) ->
+-    ordsets:intersection(ClientHashSigns, SupportedHashSigns);
++		     _, {Major, Minor}) when (Major >= 3) andalso (Minor >= 3) ->
++    sets:to_list(sets:intersection(sets:from_list(ClientHashSigns), 
++				   sets:from_list(SupportedHashSigns)));
+ available_signature_algs(_, _, _, _) -> 
+     undefined.
+ 
+--- a/lib/ssl/test/ssl_basic_SUITE.erl
++++ b/lib/ssl/test/ssl_basic_SUITE.erl
+@@ -88,7 +88,8 @@ basic_tests() ->
+      connect_dist,
+      clear_pem_cache,
+      defaults,
+-     fallback
++     fallback,
++     cipher_format
+     ].
+ 
+ options_tests() ->
+@@ -144,7 +145,8 @@ api_tests() ->
+      versions_option,
+      server_name_indication_option,
+      accept_pool,
+-     new_options_in_accept
++     new_options_in_accept,
++     prf
+     ].
+ 
+ session_tests() ->
+@@ -323,6 +325,31 @@ init_per_testcase(rizzo, Config) ->
+     ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
+     ct:timetrap({seconds, 40}),
+     Config;
++init_per_testcase(prf, Config) ->
++    ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
++    ct:timetrap({seconds, 40}),
++    case ?config(tc_group_path, Config) of
++        [] -> Prop = [];
++        [Prop] -> Prop
++    end,
++    case ?config(name, Prop) of
++        undefined -> TlsVersions = [sslv3, tlsv1, 'tlsv1.1', 'tlsv1.2'];
++        TlsVersion when is_atom(TlsVersion) ->
++            TlsVersions = [TlsVersion]
++    end,
++    PRFS=[md5, sha, sha256, sha384, sha512],
++    %All are the result of running tls_v1:prf(PrfAlgo, <<>>, <<>>, <<>>, 16)
++    %with the specified PRF algorithm
++    ExpectedPrfResults=
++    [{md5, <<96,139,180,171,236,210,13,10,28,32,2,23,88,224,235,199>>},
++     {sha, <<95,3,183,114,33,169,197,187,231,243,19,242,220,228,70,151>>},
++     {sha256, <<166,249,145,171,43,95,158,232,6,60,17,90,183,180,0,155>>},
++     {sha384, <<153,182,217,96,186,130,105,85,65,103,123,247,146,91,47,106>>},
++     {sha512, <<145,8,98,38,243,96,42,94,163,33,53,49,241,4,127,28>>},
++     %TLS 1.0 and 1.1 PRF:
++     {md5sha, <<63,136,3,217,205,123,200,177,251,211,17,229,132,4,173,80>>}],
++    TestPlan = prf_create_plan(TlsVersions, PRFS, ExpectedPrfResults),
++    [{prf_test_plan, TestPlan} | Config];
+ 
+ init_per_testcase(TestCase, Config) when TestCase == ssl_accept_timeout;
+ 					 TestCase == client_closes_socket;
+@@ -428,6 +455,25 @@ new_options_in_accept(Config) when is_list(Config) ->
+     ssl_test_lib:close(Server),
+     ssl_test_lib:close(Client).
+ %%--------------------------------------------------------------------
++prf() ->
++    [{doc,"Test that ssl:prf/5 uses the negotiated PRF."}].
++prf(Config) when is_list(Config) ->
++    TestPlan = ?config(prf_test_plan, Config),
++    case TestPlan of
++        [] -> ct:fail({error, empty_prf_test_plan});
++        _ -> lists:foreach(fun(Suite) ->
++                                   lists:foreach(
++                                     fun(Test) ->
++                                             V = ?config(tls_ver, Test),
++                                             C = ?config(ciphers, Test),
++                                             E = ?config(expected, Test),
++                                             P = ?config(prf, Test),
++                                             prf_run_test(Config, V, C, E, P)
++                                     end, Suite)
++                           end, TestPlan)
++    end.
++
++%%--------------------------------------------------------------------
+ 
+ connection_info() ->
+     [{doc,"Test the API function ssl:connection_information/1"}].
+@@ -762,6 +808,14 @@ fallback(Config) when is_list(Config) ->
+ 			      Client, {error,{tls_alert,"inappropriate fallback"}}).
+ 
+ %%--------------------------------------------------------------------
++cipher_format() ->
++    [{doc, "Test that cipher conversion from tuples to binarys works"}].
++cipher_format(Config) when is_list(Config) ->
++    {ok, Socket} = ssl:listen(0, [{ciphers, ssl:cipher_suites()}]),
++    ssl:close(Socket).
++
++%%--------------------------------------------------------------------
++
+ peername() ->
+     [{doc,"Test API function peername/1"}].
+ 
+@@ -3653,8 +3707,84 @@ basic_test(Config) ->
+     ssl_test_lib:close(Server),
+     ssl_test_lib:close(Client).
+ 
++prf_create_plan(TlsVersions, PRFs, Results) ->
++    lists:foldl(fun(Ver, Acc) ->
++                        A = prf_ciphers_and_expected(Ver, PRFs, Results),
++                        [A|Acc]
++                end, [], TlsVersions).
++prf_ciphers_and_expected(TlsVer, PRFs, Results) ->
++    case TlsVer of
++        TlsVer when TlsVer == sslv3 orelse TlsVer == tlsv1
++                    orelse TlsVer == 'tlsv1.1' ->
++            Ciphers = ssl:cipher_suites(),
++            {_, Expected} = lists:keyfind(md5sha, 1, Results),
++            [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, {prf, md5sha}]];
++        'tlsv1.2' ->
++            lists:foldl(
++              fun(PRF, Acc) ->
++                      Ciphers = prf_get_ciphers(TlsVer, PRF),
++                      case Ciphers of
++                          [] ->
++                              ct:log("No ciphers for PRF algorithm ~p. Skipping.", [PRF]),
++                              Acc;
++                          Ciphers ->
++                              {_, Expected} = lists:keyfind(PRF, 1, Results),
++                              [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected},
++                                {prf, PRF}] | Acc]
++                      end
++              end, [], PRFs)
++    end.
++prf_get_ciphers(TlsVer, PRF) ->
++    case TlsVer of
++        'tlsv1.2' ->
++            lists:filter(
++              fun(C) when tuple_size(C) == 4 andalso
++                          element(4, C) == PRF -> 
++			  true;
++                 (_) -> false
++              end, ssl:cipher_suites())
++    end.
++prf_run_test(_, TlsVer, [], _, Prf) ->
++    ct:fail({error, cipher_list_empty, TlsVer, Prf});
++prf_run_test(Config, TlsVer, Ciphers, Expected, Prf) ->
++    {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
++    BaseOpts = [{active, true}, {versions, [TlsVer]}, {ciphers, Ciphers}],
++    ServerOpts = BaseOpts ++ ?config(server_opts, Config),
++    ClientOpts = BaseOpts ++ ?config(client_opts, Config),
++    Server = ssl_test_lib:start_server(
++               [{node, ServerNode}, {port, 0}, {from, self()},
++                {mfa, {?MODULE, prf_verify_value, [TlsVer, Expected, Prf]}},
++                {options, ServerOpts}]),
++    Port = ssl_test_lib:inet_port(Server),
++    Client = ssl_test_lib:start_client(
++               [{node, ClientNode}, {port, Port},
++                {host, Hostname}, {from, self()},
++                {mfa, {?MODULE, prf_verify_value, [TlsVer, Expected, Prf]}},
++                {options, ClientOpts}]),
++    ssl_test_lib:check_result(Server, ok, Client, ok),
++    ssl_test_lib:close(Server),
++    ssl_test_lib:close(Client).
++prf_verify_value(Socket, TlsVer, Expected, Algo) ->
++    Ret = ssl:prf(Socket, <<>>, <<>>, [<<>>], 16),
++    case TlsVer of
++        sslv3 ->
++            case Ret of
++                {error, undefined} -> ok;
++                _ ->
++                    {error, {expected, {error, undefined},
++                             got, Ret, tls_ver, TlsVer, prf_algorithm, Algo}}
++            end;
++        _ ->
++            case Ret of
++                {ok, Expected} -> ok;
++                {ok, Val} -> {error, {expected, Expected, got, Val, tls_ver, TlsVer,
++                                      prf_algorithm, Algo}}
++            end
++    end.
++
+ send_recv_result_timeout_client(Socket) ->
+     {error, timeout} = ssl:recv(Socket, 11, 500),
++    {error, timeout} = ssl:recv(Socket, 11, 0),
+     ssl:send(Socket, "Hello world"),
+     receive
+ 	Msg ->
+--- a/lib/ssl/vsn.mk
++++ b/lib/ssl/vsn.mk
+@@ -1 +1 @@
+-SSL_VSN = 7.3.1
++SSL_VSN = 7.3.3
+--- a/lib/test_server/src/test_server.erl
++++ b/lib/test_server/src/test_server.erl
+@@ -2165,10 +2165,19 @@ get_timetrap_info(TCPid, SendToServer) ->
+ 	Timers ->
+ 	    case [Info || {Handle,Pid,Info} <- Timers, 
+ 			  Pid == TCPid, Handle /= infinity] of
+-		[I|_] ->
+-		    I;
++		[{TVal,true}|_] ->
++		    {TVal,{true,test_server:timetrap_scale_factor()}};
++		[{TVal,false}|_] ->
++		    {TVal,{false,1}};
+ 		[] when SendToServer == true ->
+-		    tc_supervisor_req({get_timetrap_info,TCPid});
++		    case tc_supervisor_req({get_timetrap_info,TCPid}) of
++			{TVal,true} ->
++			    {TVal,{true,test_server:timetrap_scale_factor()}};
++			{TVal,false} ->
++			    {TVal,{false,1}};
++			Error ->
++			    Error
++		    end;
+ 		[] ->
+ 		    undefined
+ 	    end
+--- a/lib/test_server/src/test_server_gl.erl
++++ b/lib/test_server/src/test_server_gl.erl
+@@ -131,6 +131,10 @@ set_props(GL, PropList) ->
+ %%% Internal functions.
+ 
+ init([]) ->
++    EscChars = case application:get_env(test_server, esc_chars) of
++		   {ok,ECBool} -> ECBool;
++		   _           -> true
++	       end,
+     {ok,#st{tc_supervisor=none,
+ 	    minor=none,
+ 	    minor_monitor=none,
+@@ -139,7 +143,7 @@ init([]) ->
+ 	    permit_io=gb_sets:empty(),
+ 	    auto_nl=true,
+ 	    levels={1,19,10},
+-	    escape_chars=true
++	    escape_chars=EscChars
+ 	   }}.
+ 
+ req(GL, Req) ->
+--- a/otp_versions.table
++++ b/otp_versions.table
+@@ -1,3 +1,5 @@
++OTP-18.3.4 : inets-6.2.4 ssl-7.3.3 # asn1-4.0.2 common_test-1.12.1 compiler-6.0.3 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2.1 cosProperty-1.2 cosTime-1.2.1 cosTransactions-1.3.1 crypto-3.6.3 debugger-4.1.2 dialyzer-2.9 diameter-1.11.2 edoc-0.7.18 eldap-1.2.1 erl_docgen-0.4.2 erl_interface-3.8.2 erts-7.3.1 et-1.5.1 eunit-2.2.13 gs-1.6 hipe-3.15 ic-4.4 jinterface-1.6.1 kernel-4.2 megaco-3.18 mnesia-4.13.4 observer-2.1.2 odbc-2.11.1 orber-3.8.1 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1.1 percept-0.8.11 public_key-1.1.1 reltool-0.7 runtime_tools-1.9.3 sasl-2.7 snmp-5.2.2 ssh-4.2.2 stdlib-2.8 syntax_tools-1.7 test_server-3.10 tools-2.8.3 typer-0.9.10 webtool-0.9.1 wx-1.6.1 xmerl-1.3.10 :
++OTP-18.3.3 : common_test-1.12.1 inets-6.2.3 ssl-7.3.2 # asn1-4.0.2 compiler-6.0.3 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2.1 cosProperty-1.2 cosTime-1.2.1 cosTransactions-1.3.1 crypto-3.6.3 debugger-4.1.2 dialyzer-2.9 diameter-1.11.2 edoc-0.7.18 eldap-1.2.1 erl_docgen-0.4.2 erl_interface-3.8.2 erts-7.3.1 et-1.5.1 eunit-2.2.13 gs-1.6 hipe-3.15 ic-4.4 jinterface-1.6.1 kernel-4.2 megaco-3.18 mnesia-4.13.4 observer-2.1.2 odbc-2.11.1 orber-3.8.1 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1.1 percept-0.8.11 public_key-1.1.1 reltool-0.7 runtime_tools-1.9.3 sasl-2.7 snmp-5.2.2 ssh-4.2.2 stdlib-2.8 syntax_tools-1.7 test_server-3.10 tools-2.8.3 typer-0.9.10 webtool-0.9.1 wx-1.6.1 xmerl-1.3.10 :
+ OTP-18.3.2 : inets-6.2.2 ssl-7.3.1 # asn1-4.0.2 common_test-1.12 compiler-6.0.3 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2.1 cosProperty-1.2 cosTime-1.2.1 cosTransactions-1.3.1 crypto-3.6.3 debugger-4.1.2 dialyzer-2.9 diameter-1.11.2 edoc-0.7.18 eldap-1.2.1 erl_docgen-0.4.2 erl_interface-3.8.2 erts-7.3.1 et-1.5.1 eunit-2.2.13 gs-1.6 hipe-3.15 ic-4.4 jinterface-1.6.1 kernel-4.2 megaco-3.18 mnesia-4.13.4 observer-2.1.2 odbc-2.11.1 orber-3.8.1 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1.1 percept-0.8.11 public_key-1.1.1 reltool-0.7 runtime_tools-1.9.3 sasl-2.7 snmp-5.2.2 ssh-4.2.2 stdlib-2.8 syntax_tools-1.7 test_server-3.10 tools-2.8.3 typer-0.9.10 webtool-0.9.1 wx-1.6.1 xmerl-1.3.10 :
+ OTP-18.3.1 : erts-7.3.1 inets-6.2.1 mnesia-4.13.4 # asn1-4.0.2 common_test-1.12 compiler-6.0.3 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2.1 cosProperty-1.2 cosTime-1.2.1 cosTransactions-1.3.1 crypto-3.6.3 debugger-4.1.2 dialyzer-2.9 diameter-1.11.2 edoc-0.7.18 eldap-1.2.1 erl_docgen-0.4.2 erl_interface-3.8.2 et-1.5.1 eunit-2.2.13 gs-1.6 hipe-3.15 ic-4.4 jinterface-1.6.1 kernel-4.2 megaco-3.18 observer-2.1.2 odbc-2.11.1 orber-3.8.1 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1.1 percept-0.8.11 public_key-1.1.1 reltool-0.7 runtime_tools-1.9.3 sasl-2.7 snmp-5.2.2 ssh-4.2.2 ssl-7.3 stdlib-2.8 syntax_tools-1.7 test_server-3.10 tools-2.8.3 typer-0.9.10 webtool-0.9.1 wx-1.6.1 xmerl-1.3.10 :
+ OTP-18.3 : asn1-4.0.2 common_test-1.12 compiler-6.0.3 cosNotification-1.2.1 cosTime-1.2.1 cosTransactions-1.3.1 crypto-3.6.3 debugger-4.1.2 dialyzer-2.9 diameter-1.11.2 edoc-0.7.18 eldap-1.2.1 erl_docgen-0.4.2 erl_interface-3.8.2 erts-7.3 eunit-2.2.13 hipe-3.15 inets-6.2 kernel-4.2 mnesia-4.13.3 observer-2.1.2 orber-3.8.1 public_key-1.1.1 runtime_tools-1.9.3 sasl-2.7 snmp-5.2.2 ssh-4.2.2 ssl-7.3 stdlib-2.8 test_server-3.10 tools-2.8.3 webtool-0.9.1 wx-1.6.1 xmerl-1.3.10 # cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosProperty-1.2 et-1.5.1 gs-1.6 ic-4.4 jinterface-1.6.1 megaco-3.18 odbc-2.11.1 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1.1 percept-0.8.11 reltool-0.7 syntax_tools-1.7 typer-0.9.10 :
diff --git a/community/erlang/APKBUILD b/community/erlang/APKBUILD
index 34424f4..57fc384 100644
--- a/community/erlang/APKBUILD
+++ b/community/erlang/APKBUILD
@@ -2,7 +2,7 @@
 # Maintainer: Marlus Saraiva <[email-masked]>
 
 pkgname=erlang
-pkgver=18.3.2
+pkgver=18.3.4
 _srcver=18.3
 pkgrel=0
 pkgdesc="General-purpose programming language and runtime environment"
@@ -75,7 +75,8 @@ source="http://www.erlang.org/download/otp_src_$_srcver.tar.gz
         0007-Split-off-webtool-dependency-from-tools.patch
         0010-fix-nteventlog-remove.patch
         0060-set-disksup_posix_only-to-true.patch
-        0070-otp-update-version-18.3.2.patch"
+        0070-otp-update-version-18.3.2.patch
+        0080-otp-update-version-18.3.4.patch"
 
 _builddir="$srcdir"/otp_src_$_srcver
 
@@ -219,7 +220,8 @@ a8e9e58c2444ac3994a6b418fd387369  0006-Do-not-install-erlang-sources.patch
 b438c37818b5c82443682c3693dd7e53  0007-Split-off-webtool-dependency-from-tools.patch
 0dd300003ff68fc46dc3c839c2541d53  0010-fix-nteventlog-remove.patch
 d17fbaafa9f7820ade09b239c00aede6  0060-set-disksup_posix_only-to-true.patch
-b0d5cf3bac335964a1c8ffd98d9f105d  0070-otp-update-version-18.3.2.patch"
+b0d5cf3bac335964a1c8ffd98d9f105d  0070-otp-update-version-18.3.2.patch
+96d85db0efbac64be3ca3f9158766e59  0080-otp-update-version-18.3.4.patch"
 sha256sums="fdab8129a1cb935db09f1832e3a7d511a4aeb2b9bb3602ca6a7ccb9730d5c9c3  otp_src_18.3.tar.gz
 536e78192f915733cbbb264883af6d9b11c9e70c2c4d3d825b58c4dbec36db86  0001-Do-not-format-man-pages-and-do-not-install-miscellan.patch
 b2e5844215d7f5f5026a77342dd698d16103cc726d23f8265bcc8399d1a82bb9  0002-Remove-rpath.patch
@@ -230,7 +232,8 @@ fcf2c37b3eaddd3e1bea2880c1b80f010623743ab2f43e144e0ecc7be874d4ff  0006-Do-not-in
 9704a53bc4bd6f5624f9ce3f201128204011f4579f19b547df74d92ae22777cf  0007-Split-off-webtool-dependency-from-tools.patch
 019c62ea3fee60068caa8c3152d7f96e76591fc5dc096abfcea48ec1593eb758  0010-fix-nteventlog-remove.patch
 3ffda0b3acbde755b496c1a974c20e1ca580432c403944c1c16836f48e248429  0060-set-disksup_posix_only-to-true.patch
-ec32540b798d2b3a7b8271cf95c63423dda864b24c8765368835295bf4575c61  0070-otp-update-version-18.3.2.patch"
+ec32540b798d2b3a7b8271cf95c63423dda864b24c8765368835295bf4575c61  0070-otp-update-version-18.3.2.patch
+9f9091b9eaa84e0b07b0f849e6311720b4cf2fed2ea1314e1470e5e65f8959a1  0080-otp-update-version-18.3.4.patch"
 sha512sums="f4a69bb14743d9f913d7060cfb6426f7c54693d07ed439506ede5160a0ba5a79a81cf08a56aaa02c68b3377cd22fed66a0fbeb216378330d7ad5c6348ed82014  otp_src_18.3.tar.gz
 172f9b0f61748bf2f04737df0451bcc9c0812db0f365f0ef7c7c244fceb991987f79a5274eea578a89cc7d077f84645d1395d9dbcbf14010268b896a080c2ccf  0001-Do-not-format-man-pages-and-do-not-install-miscellan.patch
 97c40c185b71b23ffcb924639af390b9a0be897070e396a9413e193e6d43048dfe3b86bcd0c5598b81a66ce1349de9e09f5228a452b51b6612cd947bbafb6377  0002-Remove-rpath.patch
@@ -241,4 +244,5 @@ ef9045ec689e2a6517dba7626c1225a9a265f14675d704effd324529c3d5128260ba64cebfd41185
 d65fcfc3a9441941c6292c33d354964a82da11cc7a411dd0440719e490075ed588c1e70690e80650561749010d737394567f12ff73bd460f0d00c792c77cfae3  0007-Split-off-webtool-dependency-from-tools.patch
 b7387f92f8c27a0565c7885bba4b357183c62d422616e073bc5ffad338a0e22cb5165dcb3b95bf0b920ba00831599f2216027883f4be255aa6f6150b68b7a37c  0010-fix-nteventlog-remove.patch
 f3c50f8610e08173c365a575737079b0259db6fc0dfa5b1be63c281b52358bbce9e2595132a8f6a06772785d7d38d108f8da8515e2f7706cd03b6585aab4d071  0060-set-disksup_posix_only-to-true.patch
-e472bdb4b322d66b9c0ad9627abc469b8c648145ffad1dd7f645b38b2fad43492f475d2fd4d0bab159be6110db5043bb6d792d72e8276b3c3869be46129c6616  0070-otp-update-version-18.3.2.patch"
+e472bdb4b322d66b9c0ad9627abc469b8c648145ffad1dd7f645b38b2fad43492f475d2fd4d0bab159be6110db5043bb6d792d72e8276b3c3869be46129c6616  0070-otp-update-version-18.3.2.patch
+84ee0512b5abad52f102c9696dd9ceec344f50a395078684ba01adba4efb2b287fc0c1f5e982898b0aa29c77a789b06eace156e20e8774ce07e8297f85479cd3  0080-otp-update-version-18.3.4.patch"
-- 
2.9.0

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---