diff options
Diffstat (limited to 'lib/inets')
188 files changed, 5848 insertions, 3902 deletions
diff --git a/lib/inets/doc/src/book.xml b/lib/inets/doc/src/book.xml index 51cbb2d963..eca0c319ef 100644 --- a/lib/inets/doc/src/book.xml +++ b/lib/inets/doc/src/book.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE book SYSTEM "book.dtd"> <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/fascicules.xml b/lib/inets/doc/src/fascicules.xml index ea3b988882..c075478967 100644 --- a/lib/inets/doc/src/fascicules.xml +++ b/lib/inets/doc/src/fascicules.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE fascicules SYSTEM "fascicules.dtd"> <fascicules> diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml index 4d559817c4..0cd75ff645 100644 --- a/lib/inets/doc/src/ftp.xml +++ b/lib/inets/doc/src/ftp.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2011</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml index b44674d997..e46b354e45 100644 --- a/lib/inets/doc/src/ftp_client.xml +++ b/lib/inets/doc/src/ftp_client.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml index 4542211d71..1c7f76ec28 100644 --- a/lib/inets/doc/src/http_client.xml +++ b/lib/inets/doc/src/http_client.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2010</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml index f29b505bc7..e3b763b4f3 100644 --- a/lib/inets/doc/src/http_server.xml +++ b/lib/inets/doc/src/http_server.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2011</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index d9e8587bbf..e64c375bba 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index db68cc3116..37eb7ba718 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -387,7 +387,7 @@ Receiver(ReplyInfo) </pre> </item> - <tag><c><![CDATA[{Module, Funcion, Args}]]></c></tag> + <tag><c><![CDATA[{Module, Function, Args}]]></c></tag> <item> <p>Information will be delivered to the receiver via calls to the callback function: </p> diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml index 4210aea3ec..3830b2e5ab 100644 --- a/lib/inets/doc/src/httpd.xml +++ b/lib/inets/doc/src/httpd.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> diff --git a/lib/inets/doc/src/httpd_conf.xml b/lib/inets/doc/src/httpd_conf.xml index fc34f14ec3..3ef03966a7 100644 --- a/lib/inets/doc/src/httpd_conf.xml +++ b/lib/inets/doc/src/httpd_conf.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/httpd_socket.xml b/lib/inets/doc/src/httpd_socket.xml index 58cd2ec575..70b4a4a842 100644 --- a/lib/inets/doc/src/httpd_socket.xml +++ b/lib/inets/doc/src/httpd_socket.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml index 9218ee91e2..1236576ca8 100644 --- a/lib/inets/doc/src/httpd_util.xml +++ b/lib/inets/doc/src/httpd_util.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml index 079f60779d..8c3a677966 100644 --- a/lib/inets/doc/src/inets.xml +++ b/lib/inets/doc/src/inets.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>2007</year><year>2011</year> + <year>2007</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/inets_services.xml b/lib/inets/doc/src/inets_services.xml index e282050b12..8cd0794ff2 100644 --- a/lib/inets/doc/src/inets_services.xml +++ b/lib/inets/doc/src/inets_services.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml index b38be5db28..e4c78a5b15 100644 --- a/lib/inets/doc/src/mod_alias.xml +++ b/lib/inets/doc/src/mod_alias.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml index a176242a72..e941b799a1 100644 --- a/lib/inets/doc/src/mod_auth.xml +++ b/lib/inets/doc/src/mod_auth.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml index 9906ae0895..5afe5835c7 100644 --- a/lib/inets/doc/src/mod_esi.xml +++ b/lib/inets/doc/src/mod_esi.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1997</year><year>2011</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml index a3c91dca5b..e67111a73d 100644 --- a/lib/inets/doc/src/mod_security.xml +++ b/lib/inets/doc/src/mod_security.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1998</year><year>2011</year> + <year>1998</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index a6f2933f6a..e29144f014 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -32,7 +32,114 @@ <file>notes.xml</file> </header> - <section><title>Inets 5.9.7</title> + <section><title>Inets 5.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a spelling mistake in httpc doc (Thanks to Wasif + Riaz Malik)</p> + <p> + Own Id: OTP-11538</p> + </item> + <item> + <p> + Application upgrade (appup) files are corrected for the + following applications: </p> + <p> + <c>asn1, common_test, compiler, crypto, debugger, + dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, + inets, observer, odbc, os_mon, otp_mibs, parsetools, + percept, public_key, reltool, runtime_tools, ssh, + syntax_tools, test_server, tools, typer, webtool, wx, + xmerl</c></p> + <p> + A new test utility for testing appup files is added to + test_server. This is now used by most applications in + OTP.</p> + <p> + (Thanks to Tobias Schlager)</p> + <p> + Own Id: OTP-11744</p> + </item> + <item> + <p> + ftp now sanitize file name, user name and passwords from + <CR> and <LF> tags (Thanks to Sergei Golovan)</p> + <p> + Own Id: OTP-11750</p> + </item> + <item> + <p> + Corrected error handling in the HTTP client, making it + behave more graceful.</p> + <p> + Thanks to Kirilll Zaborsky</p> + <p> + Own Id: OTP-11794</p> + </item> + <item> + <p> + Support identity transfer-encoding in httpc.</p> + <p> + Thanks to Anthony Ramine</p> + <p> + Own Id: OTP-11802</p> + </item> + <item> + <p> + Ignore empty Set-Cookie headers to increase + interoperability with servers that violate the RFC. </p> + <p> + Thanks to Kirilll Zaborsky</p> + <p> + Own Id: OTP-11803</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The commit 6189bc07 "inets: httpc improve pipelining" has + been reverted, as it turned out to break things rather + than improve pipelining utilization. It is instead up to + the user to configure httpc and use it wisely to be able + to get the most out of pipelining.</p> + <p> + Own Id: OTP-11756</p> + </item> + <item> + <p> + Handle all response codes in httpd_util:message/3</p> + <p> + Own Id: OTP-11838</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 5.9.8</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Mend max_clients check that was broken and avoid too + extensive logging that could cause memory problems.</p> + <p> + Own Id: OTP-11557 Aux Id: seq12478 </p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 5.9.7</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml index 4162ab97bb..2903b753a1 100644 --- a/lib/inets/doc/src/notes_history.xml +++ b/lib/inets/doc/src/notes_history.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/part.xml b/lib/inets/doc/src/part.xml index 3b6734a9b8..6ebca1f87f 100644 --- a/lib/inets/doc/src/part.xml +++ b/lib/inets/doc/src/part.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/part_notes.xml b/lib/inets/doc/src/part_notes.xml index 81b0dedbfa..35d645e299 100644 --- a/lib/inets/doc/src/part_notes.xml +++ b/lib/inets/doc/src/part_notes.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2002</year><year>2012</year> + <year>2002</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/part_notes_history.xml b/lib/inets/doc/src/part_notes_history.xml index f714a6d2e3..d699f5f60a 100644 --- a/lib/inets/doc/src/part_notes_history.xml +++ b/lib/inets/doc/src/part_notes_history.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml index e44829827c..aaedf330b4 100644 --- a/lib/inets/doc/src/ref_man.xml +++ b/lib/inets/doc/src/ref_man.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE application SYSTEM "application.dtd"> <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1997</year><year>2012</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml index 0b3e93a153..42a65ed0c5 100644 --- a/lib/inets/doc/src/tftp.xml +++ b/lib/inets/doc/src/tftp.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>2006</year><year>2012</year> + <year>2006</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl index 520db1b457..5674599ac5 100644 --- a/lib/inets/src/ftp/ftp.erl +++ b/lib/inets/src/ftp/ftp.erl @@ -192,7 +192,12 @@ do_open(Pid, OpenOptions, TLSOpts) -> 'ok' | {'error', Reason :: 'euser' | common_reason()}. user(Pid, User, Pass) -> - call(Pid, {user, User, Pass}, atom). + case {is_name_sane(User), is_name_sane(Pass)} of + {true, true} -> + call(Pid, {user, User, Pass}, atom); + _ -> + {error, euser} + end. -spec user(Pid :: pid(), User :: string(), @@ -201,7 +206,12 @@ user(Pid, User, Pass) -> 'ok' | {'error', Reason :: 'euser' | common_reason()}. user(Pid, User, Pass, Acc) -> - call(Pid, {user, User, Pass, Acc}, atom). + case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of + {true, true, true} -> + call(Pid, {user, User, Pass, Acc}, atom); + _ -> + {error, euser} + end. %%-------------------------------------------------------------------------- @@ -216,7 +226,12 @@ user(Pid, User, Pass, Acc) -> 'ok' | {'error', Reason :: 'eacct' | common_reason()}. account(Pid, Acc) -> - call(Pid, {account, Acc}, atom). + case is_name_sane(Acc) of + true -> + call(Pid, {account, Acc}, atom); + _ -> + {error, eacct} + end. %%-------------------------------------------------------------------------- @@ -262,7 +277,12 @@ lpwd(Pid) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. cd(Pid, Dir) -> - call(Pid, {cd, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {cd, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -305,7 +325,12 @@ ls(Pid) -> {'error', Reason :: restriction_reason() | common_reason()}. ls(Pid, Dir) -> - call(Pid, {dir, long, Dir}, string). + case is_name_sane(Dir) of + true -> + call(Pid, {dir, long, Dir}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -333,7 +358,12 @@ nlist(Pid) -> {'error', Reason :: restriction_reason() | common_reason()}. nlist(Pid, Dir) -> - call(Pid, {dir, short, Dir}, string). + case is_name_sane(Dir) of + true -> + call(Pid, {dir, short, Dir}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -349,7 +379,12 @@ nlist(Pid, Dir) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. rename(Pid, Old, New) -> - call(Pid, {rename, Old, New}, string). + case {is_name_sane(Old), is_name_sane(New)} of + {true, true} -> + call(Pid, {rename, Old, New}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -365,7 +400,12 @@ rename(Pid, Old, New) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. delete(Pid, File) -> - call(Pid, {delete, File}, string). + case is_name_sane(File) of + true -> + call(Pid, {delete, File}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -380,7 +420,12 @@ delete(Pid, File) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. mkdir(Pid, Dir) -> - call(Pid, {mkdir, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {mkdir, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -395,7 +440,12 @@ mkdir(Pid, Dir) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. rmdir(Pid, Dir) -> - call(Pid, {rmdir, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {rmdir, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -437,7 +487,12 @@ recv(Pid, RemotFileName) -> 'ok' | {'error', Reason :: term()}. recv(Pid, RemotFileName, LocalFileName) -> - call(Pid, {recv, RemotFileName, LocalFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {recv, RemotFileName, LocalFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -456,7 +511,12 @@ recv(Pid, RemotFileName, LocalFileName) -> {'error', Reason :: restriction_reason() | common_reason()}. recv_bin(Pid, RemoteFile) -> - call(Pid, {recv_bin, RemoteFile}, bin). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {recv_bin, RemoteFile}, bin); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -473,7 +533,12 @@ recv_bin(Pid, RemoteFile) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. recv_chunk_start(Pid, RemoteFile) -> - call(Pid, {recv_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {recv_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -521,7 +586,12 @@ send(Pid, LocalFileName) -> shortage_reason()}. send(Pid, LocalFileName, RemotFileName) -> - call(Pid, {send, LocalFileName, RemotFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {send, LocalFileName, RemotFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -541,7 +611,12 @@ send(Pid, LocalFileName, RemotFileName) -> shortage_reason()}. send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) -> - call(Pid, {send_bin, Bin, RemoteFile}, atom); + case is_name_sane(RemoteFile) of + true -> + call(Pid, {send_bin, Bin, RemoteFile}, atom); + _ -> + {error, efnamena} + end; send_bin(_Pid, _Bin, _RemoteFile) -> {error, enotbinary}. @@ -559,7 +634,12 @@ send_bin(_Pid, _Bin, _RemoteFile) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. send_chunk_start(Pid, RemoteFile) -> - call(Pid, {send_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {send_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -575,7 +655,12 @@ send_chunk_start(Pid, RemoteFile) -> 'ok' | {'error', Reason :: term()}. append_chunk_start(Pid, RemoteFile) -> - call(Pid, {append_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {append_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -683,7 +768,12 @@ append(Pid, LocalFileName) -> 'ok' | {'error', Reason :: term()}. append(Pid, LocalFileName, RemotFileName) -> - call(Pid, {append, LocalFileName, RemotFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {append, LocalFileName, RemotFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -705,7 +795,12 @@ append(Pid, LocalFileName, RemotFileName) -> shortage_reason()}. append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) -> - call(Pid, {append_bin, Bin, RemoteFile}, atom); + case is_name_sane(RemoteFile) of + true -> + call(Pid, {append_bin, Bin, RemoteFile}, atom); + _ -> + {error, efnamena} + end; append_bin(_Pid, _Bin, _RemoteFile) -> {error, enotbinary}. @@ -2302,6 +2397,15 @@ send_bin(State, Bin) -> mk_cmd(Fmt, Args) -> [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok. +is_name_sane([]) -> + true; +is_name_sane([?CR| _]) -> + false; +is_name_sane([?LF| _]) -> + false; +is_name_sane([_| Rest]) -> + is_name_sane(Rest). + pwd_result(Lines) -> {_, [?DOUBLE_QUOTE | Rest]} = lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines), diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl index 69900bae65..134115bdfa 100644 --- a/lib/inets/src/http_client/httpc_cookie.erl +++ b/lib/inets/src/http_client/httpc_cookie.erl @@ -335,7 +335,8 @@ add_domain(Str, #http_cookie{domain = Domain}) -> Str ++ "; $Domain=" ++ Domain. parse_set_cookies(CookieHeaders, DefaultPathDomain) -> - SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders], + %% empty Set-Cookie header is invalid according to RFC but some sites violate it + SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders, Value /= ""], Cookies = [parse_set_cookie(SetCookieHeader, DefaultPathDomain) || SetCookieHeader <- SetCookieHeaders], %% print_cookies("Parsed Cookies", Cookies), diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 80c8b2439e..612eb05358 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -55,8 +55,8 @@ headers, % #http_response_h{} body, % binary() mfa, % {Module, Function, Args} - pipeline = queue:new(), % queue() - keep_alive = queue:new(), % queue() + pipeline = queue:new(), % queue:queue() + keep_alive = queue:new(), % queue:queue() status, % undefined | new | pipeline | keep_alive | close | {ssl_tunnel, Request} canceled = [], % [RequestId] max_header_size = nolimit, % nolimit | integer() @@ -1116,18 +1116,19 @@ handle_http_body(Body, #state{headers = Headers, {new_body, NewBody}]), NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders), - handle_response(State#state{headers = NewHeaders, - body = NewBody}) + case Body of + <<>> -> + handle_response(State#state{headers = NewHeaders, + body = NewBody}); + _ -> + {NewBody2, NewRequest} = + stream(NewBody, Request, Code), + handle_response(State#state{headers = NewHeaders, + body = NewBody2}) + end end; - Encoding when is_list(Encoding) -> - ?hcrt("handle_http_body - encoding", [{encoding, Encoding}]), - NewState = answer_request(Request, - httpc_response:error(Request, - unknown_encoding), - State), - {stop, normal, NewState}; - _ -> - ?hcrt("handle_http_body - other", []), + Enc when Enc =:= "identity"; Enc =:= undefined -> + ?hcrt("handle_http_body - identity", []), Length = list_to_integer(Headers#http_response_h.'content-length'), case ((Length =< MaxBodySize) orelse (MaxBodySize =:= nolimit)) of @@ -1149,12 +1150,19 @@ handle_http_body(Body, #state{headers = Headers, body_too_big), State), {stop, normal, NewState} - end + end; + Encoding when is_list(Encoding) -> + ?hcrt("handle_http_body - other", [{encoding, Encoding}]), + NewState = answer_request(Request, + httpc_response:error(Request, + unknown_encoding), + State), + {stop, normal, NewState} end. handle_response(#state{status = new} = State) -> ?hcrd("handle response - status = new", []), - handle_response(check_persistent(State)); + handle_response(try_to_enable_pipeline_or_keep_alive(State)); handle_response(#state{request = Request, status = Status, @@ -1429,22 +1437,39 @@ is_keep_alive_enabled_server(_,_) -> is_keep_alive_connection(Headers, #session{client_close = ClientClose}) -> (not ((ClientClose) orelse httpc_response:is_server_closing(Headers))). -check_persistent( - #state{session = #session{type = Type} = Session, +try_to_enable_pipeline_or_keep_alive( + #state{session = Session, + request = #request{method = Method}, status_line = {Version, _, _}, headers = Headers, - profile_name = ProfileName} = State) -> + profile_name = ProfileName} = State) -> + ?hcrd("try to enable pipeline or keep-alive", + [{version, Version}, + {headers, Headers}, + {session, Session}]), case is_keep_alive_enabled_server(Version, Headers) andalso - is_keep_alive_connection(Headers, Session) of + is_keep_alive_connection(Headers, Session) of true -> - mark_persistent(ProfileName, Session), - State#state{status = Type}; + case (is_pipeline_enabled_client(Session) andalso + httpc_request:is_idempotent(Method)) of + true -> + insert_session(Session, ProfileName), + State#state{status = pipeline}; + false -> + insert_session(Session, ProfileName), + %% Make sure type is keep_alive in session + %% as it in this case might be pipeline + NewSession = Session#session{type = keep_alive}, + State#state{status = keep_alive, + session = NewSession} + end; false -> State#state{status = close} end. answer_request(#request{id = RequestId, from = From} = Request, Msg, - #state{timers = Timers, + #state{session = Session, + timers = Timers, profile_name = ProfileName} = State) -> ?hcrt("answer request", [{request, Request}, {msg, Msg}]), httpc_response:send(From, Msg), @@ -1454,14 +1479,19 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg, Timer = {RequestId, TimerRef}, cancel_timer(TimerRef, {timeout, Request#request.id}), httpc_manager:request_done(RequestId, ProfileName), + NewSession = maybe_make_session_available(ProfileName, Session), Timers2 = Timers#timers{request_timers = lists:delete(Timer, RequestTimers)}, State#state{request = Request#request{from = answer_sent}, + session = NewSession, timers = Timers2}. -mark_persistent(ProfileName, Session) -> - update_session(ProfileName, Session, #session.persistent, true), - Session#session{persistent = true}. +maybe_make_session_available(ProfileName, + #session{available = false} = Session) -> + update_session(ProfileName, Session, #session.available, true), + Session#session{available = true}; +maybe_make_session_available(_ProfileName, Session) -> + Session. cancel_timers(#timers{request_timers = ReqTmrs, queue_timer = QTmr}) -> cancel_timer(QTmr, timeout_queue), @@ -1829,7 +1859,7 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) -> [ProfileName, SessionId, Pos, Value, (catch httpc_manager:which_session_info(ProfileName)), Session, - (catch httpc_manager:lookup_session(ProfileName, SessionId)), + (catch httpc_manager:lookup_session(SessionId, ProfileName)), T, E]), exit({failed_updating_session, [{profile, ProfileName}, diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl index d5b3dd2a2a..add5d11dfa 100644 --- a/lib/inets/src/http_client/httpc_internal.hrl +++ b/lib/inets/src/http_client/httpc_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -143,8 +143,8 @@ %% true | false %% This will be true, when a response has been received for - %% the first request and the server has not closed the connection - persistent = false + %% the first request. See type above. + available = false }). diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index a3ed371e61..48a9c32454 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -451,7 +451,7 @@ do_init(ProfileName, CookiesDir) -> %%-------------------------------------------------------------------- handle_call({request, Request}, _, State) -> ?hcri("request", [{request, Request}]), - case (catch handle_request(Request, State, false)) of + case (catch handle_request(Request, State)) of {reply, Msg, NewState} -> {reply, Msg, NewState}; Error -> @@ -511,7 +511,7 @@ handle_cast({retry_or_redirect_request, {Time, Request}}, {noreply, State}; handle_cast({retry_or_redirect_request, Request}, State) -> - case (catch handle_request(Request, State, true)) of + case (catch handle_request(Request, State)) of {reply, {ok, _}, NewState} -> {noreply, NewState}; Error -> @@ -724,7 +724,7 @@ get_handler_info(Tab) -> handle_request(#request{settings = #http_options{version = "HTTP/0.9"}} = Request, - State, _) -> + State) -> %% Act as an HTTP/0.9 client that does not know anything %% about persistent connections @@ -737,7 +737,7 @@ handle_request(#request{settings = handle_request(#request{settings = #http_options{version = "HTTP/1.0"}} = Request, - State, _) -> + State) -> %% Act as an HTTP/1.0 client that does not %% use persistent connections @@ -748,13 +748,13 @@ handle_request(#request{settings = start_handler(NewRequest#request{headers = NewHeaders}, State), {reply, {ok, NewRequest#request.id}, State}; -handle_request(Request, State = #state{options = Options}, Retry) -> +handle_request(Request, State = #state{options = Options}) -> NewRequest = handle_cookies(generate_request_id(Request), State), SessionType = session_type(Options), case select_session(Request#request.method, Request#request.address, - Request#request.scheme, SessionType, State, Retry) of + Request#request.scheme, SessionType, State) of {ok, HandlerPid} -> pipeline_or_keep_alive(NewRequest, HandlerPid, State); no_connection -> @@ -778,7 +778,6 @@ start_handler(#request{id = Id, #state{profile_name = ProfileName, handler_db = HandlerDb, options = Options}) -> - ClientClose = httpc_request:is_client_closing(Request#request.headers), {ok, Pid} = case is_inets_manager() of true -> @@ -789,18 +788,13 @@ start_handler(#request{id = Id, end, HandlerInfo = {Id, Pid, From}, ets:insert(HandlerDb, HandlerInfo), - insert_session(#session{id = {Request#request.address, Pid}, - scheme = Request#request.scheme, - client_close = ClientClose, - type = session_type(Options) - }, ProfileName), erlang:monitor(process, Pid). select_session(Method, HostPort, Scheme, SessionType, #state{options = #options{max_pipeline_length = MaxPipe, max_keep_alive_length = MaxKeepAlive}, - session_db = SessionDb}, Retry) -> + session_db = SessionDb}) -> ?hcrd("select session", [{session_type, SessionType}, {max_pipeline_length, MaxPipe}, {max_keep_alive_length, MaxKeepAlive}]), @@ -813,23 +807,13 @@ select_session(Method, HostPort, Scheme, SessionType, %% client_close, scheme and type specified. %% The fields id (part of: HandlerPid) and queue_length %% specified. - Pattern = case (Retry andalso SessionType == pipeline) of - true -> - #session{id = {HostPort, '$1'}, - client_close = false, - scheme = Scheme, - queue_length = '$2', - type = SessionType, - persistent = true, - _ = '_'}; - false -> - #session{id = {HostPort, '$1'}, - client_close = false, - scheme = Scheme, - queue_length = '$2', - type = SessionType, - _ = '_'} - end, + Pattern = #session{id = {HostPort, '$1'}, + client_close = false, + scheme = Scheme, + queue_length = '$2', + type = SessionType, + available = true, + _ = '_'}, %% {'_', {HostPort, '$1'}, false, Scheme, '_', '$2', SessionTyp}, Candidates = ets:match(SessionDb, Pattern), ?hcrd("select session", [{host_port, HostPort}, diff --git a/lib/inets/src/http_lib/http_request.erl b/lib/inets/src/http_lib/http_request.erl index aa9f9f6774..f295453bdd 100644 --- a/lib/inets/src/http_lib/http_request.erl +++ b/lib/inets/src/http_lib/http_request.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,9 +40,6 @@ headers([Header | Tail], Headers) -> headers(Tail, headers(http_util:to_lower(string:strip(Key)), string:strip(Value), Headers)); {_, []} -> - Report = io_lib:format("Ignored invalid HTTP-header: ~p~n", - [Header]), - error_logger:error_report(Report), headers(Tail, Headers) end. diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile index 67555d5f1c..2660d04d16 100644 --- a/lib/inets/src/http_server/Makefile +++ b/lib/inets/src/http_server/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2005-2012. All Rights Reserved. +# Copyright Ericsson AB 2005-2013. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -43,6 +43,7 @@ MODULES = \ httpd \ httpd_acceptor \ httpd_acceptor_sup \ + httpd_connection_sup\ httpd_cgi \ httpd_conf \ httpd_example \ diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl index 93608dbf96..e8148ea362 100644 --- a/lib/inets/src/http_server/httpd.erl +++ b/lib/inets/src/http_server/httpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,13 +36,6 @@ %% API -export([parse_query/1, reload_config/2, info/1, info/2, info/3]). -%% Internal debugging and status info stuff... --export([ - get_status/1, get_status/2, get_status/3, - get_admin_state/0, get_admin_state/1, get_admin_state/2, - get_usage_state/0, get_usage_state/1, get_usage_state/2 - ]). - %%%======================================================================== %%% API %%%======================================================================== @@ -296,227 +289,22 @@ make_name(Addr, Port) -> httpd_util:make_name("httpd", Addr, Port). -%%%-------------------------------------------------------------- -%%% Internal debug functions - Do we want these functions here!? -%%%-------------------------------------------------------------------- - -%%% ========================================================= -%%% Function: get_admin_state/0, get_admin_state/1, get_admin_state/2 -%%% get_admin_state() -%%% get_admin_state(Port) -%%% get_admin_state(Addr,Port) -%%% -%%% Returns: {ok,State} | {error,Reason} -%%% -%%% Description: This function is used to retrieve the administrative -%%% state of the HTTP server. -%%% -%%% Types: Port -> integer() -%%% Addr -> {A,B,C,D} | string() | undefined -%%% State -> unblocked | shutting_down | blocked -%%% Reason -> term() -%%% -get_admin_state() -> get_admin_state(undefined,8888). -get_admin_state(Port) when is_integer(Port) -> get_admin_state(undefined,Port); - -get_admin_state(ConfigFile) when is_list(ConfigFile) -> - case get_addr_and_port(ConfigFile) of - {ok,Addr,Port} -> - unblock(Addr,Port); - Error -> - Error - end. - -get_admin_state(Addr,Port) when is_integer(Port) -> - Name = make_name(Addr,Port), - case whereis(Name) of - Pid when is_pid(Pid) -> - httpd_manager:get_admin_state(Pid); - _ -> - {error,not_started} - end. - - - -%%% ========================================================= -%%% Function: get_usage_state/0, get_usage_state/1, get_usage_state/2 -%%% get_usage_state() -%%% get_usage_state(Port) -%%% get_usage_state(Addr,Port) -%%% -%%% Returns: {ok,State} | {error,Reason} -%%% -%%% Description: This function is used to retrieve the usage -%%% state of the HTTP server. -%%% -%%% Types: Port -> integer() -%%% Addr -> {A,B,C,D} | string() | undefined -%%% State -> idle | active | busy -%%% Reason -> term() -%%% -get_usage_state() -> get_usage_state(undefined,8888). -get_usage_state(Port) when is_integer(Port) -> get_usage_state(undefined,Port); - -get_usage_state(ConfigFile) when is_list(ConfigFile) -> - case get_addr_and_port(ConfigFile) of - {ok,Addr,Port} -> - unblock(Addr,Port); - Error -> - Error - end. - -get_usage_state(Addr,Port) when is_integer(Port) -> - Name = make_name(Addr,Port), - case whereis(Name) of - Pid when is_pid(Pid) -> - httpd_manager:get_usage_state(Pid); - _ -> - {error,not_started} - end. - - - -%%% ========================================================= -%% Function: get_status(ConfigFile) -> Status -%% get_status(Port) -> Status -%% get_status(Addr,Port) -> Status -%% get_status(Port,Timeout) -> Status -%% get_status(Addr,Port,Timeout) -> Status -%% -%% Arguments: ConfigFile -> string() -%% Configuration file from which Port and -%% BindAddress will be extracted. -%% Addr -> {A,B,C,D} | string() -%% Bind Address of the http server -%% Port -> integer() -%% Port number of the http server -%% Timeout -> integer() -%% Timeout time for the call -%% -%% Returns: Status -> list() -%% -%% Description: This function is used when the caller runs in the -%% same node as the http server or if calling with a -%% program such as erl_call (see erl_interface). -%% - -get_status(ConfigFile) when is_list(ConfigFile) -> - case get_addr_and_port(ConfigFile) of - {ok,Addr,Port} -> - get_status(Addr,Port); - Error -> - Error - end; - -get_status(Port) when is_integer(Port) -> - get_status(undefined,Port,5000). - -get_status(Port,Timeout) when is_integer(Port) andalso is_integer(Timeout) -> - get_status(undefined,Port,Timeout); - -get_status(Addr,Port) -> - get_status(Addr,Port,5000). - -get_status(Addr,Port,Timeout) when is_integer(Port) -> - Name = make_name(Addr,Port), - case whereis(Name) of - Pid when is_pid(Pid) -> - httpd_manager:get_status(Pid,Timeout); - _ -> - not_started - end. - do_reload_config(ConfigList, Mode) -> case (catch httpd_conf:validate_properties(ConfigList)) of {ok, Config} -> Address = proplists:get_value(bind_address, Config, any), Port = proplists:get_value(port, Config, 80), - block(Address, Port, Mode), - reload(Config, Address, Port), - unblock(Address, Port); + case block(Address, Port, Mode) of + ok -> + reload(Config, Address, Port), + unblock(Address, Port); + Error -> + Error + end; Error -> Error end. - %%%-------------------------------------------------------------- %%% Deprecated %%%-------------------------------------------------------------- - -%% start() -> -%% start("/var/tmp/server_root/conf/8888.conf"). - -%% start(ConfigFile) -> -%% {ok, Pid} = inets:start(httpd, ConfigFile, stand_alone), -%% unlink(Pid), -%% {ok, Pid}. - -%% start_link() -> -%% start("/var/tmp/server_root/conf/8888.conf"). - -%% start_link(ConfigFile) when is_list(ConfigFile) -> -%% inets:start(httpd, ConfigFile, stand_alone). - -%% stop() -> -%% stop(8888). - -%% stop(Port) when is_integer(Port) -> -%% stop(undefined, Port); -%% stop(Pid) when is_pid(Pid) -> -%% old_stop(Pid); -%% stop(ConfigFile) when is_list(ConfigFile) -> -%% old_stop(ConfigFile). - -%% stop(Addr, Port) when is_integer(Port) -> -%% old_stop(Addr, Port). - -%% start_child() -> -%% start_child("/var/tmp/server_root/conf/8888.conf"). - -%% start_child(ConfigFile) -> -%% httpd_sup:start_child(ConfigFile). - -%% stop_child() -> -%% stop_child(8888). - -%% stop_child(Port) -> -%% stop_child(undefined, Port). - -%% stop_child(Addr, Port) when is_integer(Port) -> -%% httpd_sup:stop_child(Addr, Port). - -%% restart() -> reload(undefined, 8888). - -%% restart(Port) when is_integer(Port) -> -%% reload(undefined, Port). -%% restart(Addr, Port) -> -%% reload(Addr, Port). - -%% old_stop(Pid) when is_pid(Pid) -> -%% do_stop(Pid); -%% old_stop(ConfigFile) when is_list(ConfigFile) -> -%% case get_addr_and_port(ConfigFile) of -%% {ok, Addr, Port} -> -%% old_stop(Addr, Port); - -%% Error -> -%% Error -%% end; -%% old_stop(_StartArgs) -> -%% ok. - -%% old_stop(Addr, Port) when is_integer(Port) -> -%% Name = old_make_name(Addr, Port), -%% case whereis(Name) of -%% Pid when is_pid(Pid) -> -%% do_stop(Pid), -%% ok; -%% _ -> -%% not_started -%% end. - -%% do_stop(Pid) -> -%% exit(Pid, shutdown). - -%% old_make_name(Addr,Port) -> -%% httpd_util:make_name("httpd_instance_sup",Addr,Port). diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl index 1bffcc1f12..e812bc76f5 100644 --- a/lib/inets/src/http_server/httpd_acceptor.erl +++ b/lib/inets/src/http_server/httpd_acceptor.erl @@ -21,13 +21,13 @@ -include("httpd.hrl"). -include("httpd_internal.hrl"). --include("inets_internal.hrl"). +%%-include("inets_internal.hrl"). %% Internal application API --export([start_link/6, start_link/7]). +-export([start_link/7, start_link/8]). %% Other exports (for spawn's etc.) --export([acceptor_init/7, acceptor_init/8, acceptor_loop/6]). +-export([acceptor_init/8, acceptor_init/9, acceptor_loop/8]). %% %% External API @@ -36,51 +36,52 @@ %% start_link start_link(Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) -> - ?hdrd("start link", - [{manager, Manager}, - {socket_type, SocketType}, - {address, Addr}, - {port, Port}, - {timeout, AcceptTimeout}]), + %% ?hdrd("start link", + %% [{manager, Manager}, + %% {socket_type, SocketType}, + %% {address, Addr}, + %% {port, Port}, + %% {timeout, AcceptTimeout}]), Args = [self(), Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout], proc_lib:start_link(?MODULE, acceptor_init, Args). -start_link(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) -> - ?hdrd("start link", - [{manager, Manager}, - {socket_type, SocketType}, - {listen_socket, ListenSocket}, - {timeout, AcceptTimeout}]), - Args = [self(), Manager, SocketType, ListenSocket, IpFamily, +start_link(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) -> + %% ?hdrd("start link", + %% [{manager, Manager}, + %% {socket_type, SocketType}, + %% {listen_socket, ListenSocket}, + %% {timeout, AcceptTimeout}]), + Args = [self(), Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout], proc_lib:start_link(?MODULE, acceptor_init, Args). -acceptor_init(Parent, Manager, SocketType, {ListenOwner, ListenSocket}, IpFamily, +acceptor_init(Parent, Manager, SocketType, Addr, Port, {ListenOwner, ListenSocket}, IpFamily, ConfigDb, AcceptTimeout) -> - ?hdrd("acceptor init", - [{parent, Parent}, - {manager, Manager}, - {socket_type, SocketType}, - {listen_owner, ListenOwner}, - {listen_socket, ListenSocket}, - {timeout, AcceptTimeout}]), + %% ?hdrd("acceptor init", + %% [{parent, Parent}, + %% {manager, Manager}, + %% {socket_type, SocketType}, + %% {listen_owner, ListenOwner}, + %% {listen_socket, ListenSocket}, + %% {timeout, AcceptTimeout}]), link(ListenOwner), proc_lib:init_ack(Parent, {ok, self()}), - acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout). + acceptor_loop(Manager, SocketType, Addr, Port, + ListenSocket, IpFamily, ConfigDb, AcceptTimeout). acceptor_init(Parent, Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) -> - ?hdrd("acceptor init", - [{parent, Parent}, - {manager, Manager}, - {socket_type, SocketType}, - {address, Addr}, - {port, Port}, - {timeout, AcceptTimeout}]), + %% ?hdrd("acceptor init", + %% [{parent, Parent}, + %% {manager, Manager}, + %% {socket_type, SocketType}, + %% {address, Addr}, + %% {port, Port}, + %% {timeout, AcceptTimeout}]), case (catch do_init(SocketType, Addr, Port, IpFamily)) of {ok, ListenSocket} -> proc_lib:init_ack(Parent, {ok, self()}), - acceptor_loop(Manager, SocketType, + acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily,ConfigDb, AcceptTimeout); Error -> proc_lib:init_ack(Parent, Error), @@ -88,67 +89,68 @@ acceptor_init(Parent, Manager, SocketType, Addr, Port, IpFamily, end. do_init(SocketType, Addr, Port, IpFamily) -> - ?hdrt("do init", []), + %% ?hdrt("do init", []), do_socket_start(SocketType), ListenSocket = do_socket_listen(SocketType, Addr, Port, IpFamily), {ok, ListenSocket}. do_socket_start(SocketType) -> - ?hdrt("do socket start", []), + %% ?hdrt("do socket start", []), case http_transport:start(SocketType) of ok -> ok; {error, Reason} -> - ?hdrv("failed starting transport", [{reason, Reason}]), + %% ?hdrv("failed starting transport", [{reason, Reason}]), throw({error, {socket_start_failed, Reason}}) end. do_socket_listen(SocketType, Addr, Port, IpFamily) -> - ?hdrt("do socket listen", []), + %% ?hdrt("do socket listen", []), case http_transport:listen(SocketType, Addr, Port, IpFamily) of {ok, ListenSocket} -> ListenSocket; {error, Reason} -> - ?hdrv("listen failed", [{reason, Reason}, - {socket_type, SocketType}, - {addr, Addr}, - {port, Port}]), + %% ?hdrv("listen failed", [{reason, Reason}, + %% {socket_type, SocketType}, + %% {addr, Addr}, + %% {port, Port}]), throw({error, {listen, Reason}}) end. %% acceptor -acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) -> - ?hdrd("awaiting accept", - [{manager, Manager}, - {socket_type, SocketType}, - {listen_socket, ListenSocket}, - {timeout, AcceptTimeout}]), +acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) -> + %% ?hdrd("awaiting accept", + %% [{manager, Manager}, + %% {socket_type, SocketType}, + %% {listen_socket, ListenSocket}, + %% {timeout, AcceptTimeout}]), case (catch http_transport:accept(SocketType, ListenSocket, 50000)) of {ok, Socket} -> - ?hdrv("accepted", [{socket, Socket}]), - handle_connection(Manager, ConfigDb, AcceptTimeout, + %% ?hdrv("accepted", [{socket, Socket}]), + handle_connection(Addr, Port, Manager, ConfigDb, AcceptTimeout, SocketType, Socket), - ?MODULE:acceptor_loop(Manager, SocketType, + ?MODULE:acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb,AcceptTimeout); {error, Reason} -> - ?hdri("accept failed", [{reason, Reason}]), + %% ?hdri("accept failed", [{reason, Reason}]), handle_error(Reason, ConfigDb), - ?MODULE:acceptor_loop(Manager, SocketType, ListenSocket, + ?MODULE:acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout); {'EXIT', Reason} -> - ?hdri("accept exited", [{reason, Reason}]), + %% ?hdri("accept exited", [{reason, Reason}]), ReasonString = lists:flatten(io_lib:format("Accept exit: ~p", [Reason])), accept_failed(ConfigDb, ReasonString) end. -handle_connection(Manager, ConfigDb, AcceptTimeout, SocketType, Socket) -> - {ok, Pid} = httpd_request_handler:start(Manager, ConfigDb, AcceptTimeout), +handle_connection(Address, Port, Manager, ConfigDb, AcceptTimeout, SocketType, Socket) -> + Sup = httpd_connection_sup:connection_sup(Address, Port), + {ok, Pid} = httpd_connection_sup:start_child(Sup, [Manager, ConfigDb, AcceptTimeout]), http_transport:controlling_process(SocketType, Socket, Pid), httpd_request_handler:socket_ownership_transfered(Pid, SocketType, Socket). diff --git a/lib/inets/src/http_server/httpd_acceptor_sup.erl b/lib/inets/src/http_server/httpd_acceptor_sup.erl index df837b5a24..cc2b582b52 100644 --- a/lib/inets/src/http_server/httpd_acceptor_sup.erl +++ b/lib/inets/src/http_server/httpd_acceptor_sup.erl @@ -27,7 +27,8 @@ -behaviour(supervisor). %% API --export([start_link/2, start_acceptor/6, start_acceptor/7, stop_acceptor/2]). +-export([start_link/1]). +%%, start_acceptor/6, start_acceptor/7, stop_acceptor/2]). %% Supervisor callback -export([init/1]). @@ -35,63 +36,48 @@ %%%========================================================================= %%% API %%%========================================================================= -start_link(Addr, Port) -> +start_link([Addr, Port| _] = Args) -> SupName = make_name(Addr, Port), - supervisor:start_link({local, SupName}, ?MODULE, []). - -%%---------------------------------------------------------------------- -%% Function: [start|stop]_acceptor/5 -%% Description: Starts/stops an [auth | security] worker (child) process -%%---------------------------------------------------------------------- -start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) -> - start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily, - ConfigDb, AcceptTimeout, self(), []). -start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout, ListenSocket) -> - start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily, - ConfigDb, AcceptTimeout, ListenSocket, self(), []). - - -stop_acceptor(Addr, Port) -> - stop_worker(httpd_acceptor, Addr, Port). + supervisor:start_link({local, SupName}, ?MODULE, [Args]). %%%========================================================================= %%% Supervisor callback %%%========================================================================= -init(_) -> - Flags = {one_for_one, 500, 100}, - Workers = [], - {ok, {Flags, Workers}}. +init([Args]) -> + RestartStrategy = one_for_one, + MaxR = 10, + MaxT = 3600, + Children = [child_spec(Args)], + {ok, {{RestartStrategy, MaxR, MaxT}, Children}}. %%%========================================================================= %%% Internal functions %%%========================================================================= +child_spec([Address, Port, ConfigList, AcceptTimeout, ListenInfo]) -> + Name = id(Address, Port), + Manager = httpd_util:make_name("httpd", Address, Port), + SockType = proplists:get_value(socket_type, ConfigList, ip_comm), + IpFamily = proplists:get_value(ipfamily, ConfigList, inet), + StartFunc = case ListenInfo of + undefined -> + {httpd_acceptor, start_link, [Manager, SockType, Address, Port, IpFamily, + httpd_util:make_name("httpd_conf", Address, Port), + AcceptTimeout]}; + _ -> + {httpd_acceptor, start_link, [Manager, SockType, Address, Port, ListenInfo, + IpFamily, + httpd_util:make_name("httpd_conf", Address, Port), + AcceptTimeout]} + end, + Restart = transient, + Shutdown = brutal_kill, + Modules = [httpd_acceptor], + Type = worker, + {Name, StartFunc, Restart, Shutdown, Type, Modules}. -make_name(Addr,Port) -> - httpd_util:make_name("httpd_acc_sup", Addr, Port). +id(Address, Port) -> + {httpd_acceptor_sup, Address, Port}. -start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, Manager, Modules) -> - SupName = make_name(Addr, Port), - Args = [Manager, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout], - Spec = {{M, Addr, Port}, - {M, start_link, Args}, - permanent, timer:seconds(1), worker, [M] ++ Modules}, - supervisor:start_child(SupName, Spec). - -start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, ListenSocket, - Manager, Modules) -> - SupName = make_name(Addr, Port), - Args = [Manager, SocketType, ListenSocket, IpFamily, ConfigDB, AcceptTimeout], - Spec = {{M, Addr, Port}, - {M, start_link, Args}, - permanent, timer:seconds(1), worker, [M] ++ Modules}, - supervisor:start_child(SupName, Spec). +make_name(Addr,Port) -> + httpd_util:make_name("httpd_acceptor_sup", Addr, Port). -stop_worker(M, Addr, Port) -> - SupName = make_name(Addr, Port), - Name = {M, Addr, Port}, - case supervisor:terminate_child(SupName, Name) of - ok -> - supervisor:delete_child(SupName, Name); - Error -> - Error - end. diff --git a/lib/inets/src/http_server/httpd_connection_sup.erl b/lib/inets/src/http_server/httpd_connection_sup.erl new file mode 100644 index 0000000000..48c2d8f076 --- /dev/null +++ b/lib/inets/src/http_server/httpd_connection_sup.erl @@ -0,0 +1,68 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% Purpose: Ssh connection supervisor. +%%---------------------------------------------------------------------- + +-module(httpd_connection_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/1]). +-export([start_child/2, connection_sup/2]). + +%% Supervisor callback +-export([init/1]). + +%%%========================================================================= +%%% API +%%%========================================================================= +start_link(Args) -> + supervisor:start_link(?MODULE, [Args]). + +start_child(Sup, Args) -> + supervisor:start_child(Sup, Args). + +connection_sup(Addr, Port) -> + httpd_util:make_name("httpd_connection_sup", Addr, Port). + +%%%========================================================================= +%%% Supervisor callback +%%%========================================================================= +init([[Addr, Port]]) -> + RegName = connection_sup(Addr, Port), + register(RegName, self()), + RestartStrategy = simple_one_for_one, + MaxR = 0, + MaxT = 3600, + + Name = undefined, % As simple_one_for_one is used. + StartFunc = {httpd_request_handler, start_link, []}, + Restart = temporary, % E.g. should not be restarted + Shutdown = 4000, + Modules = [httpd_request_handler], + Type = worker, + + ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules}, + {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}. + + + diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl index 16a080f8e2..6fc07f033c 100644 --- a/lib/inets/src/http_server/httpd_example.erl +++ b/lib/inets/src/http_server/httpd_example.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -66,7 +66,7 @@ get_bin(_Env,_Input) -> <INPUT TYPE=\"text\" NAME=\"input2\"> <INPUT TYPE=\"submit\"><BR> </FORM>" ++ "\n"), - footer()]. + list_to_binary(footer())]. post(_Env,[]) -> [header(), diff --git a/lib/inets/src/http_server/httpd_instance_sup.erl b/lib/inets/src/http_server/httpd_instance_sup.erl index baa60d318c..b95be44b2a 100644 --- a/lib/inets/src/http_server/httpd_instance_sup.erl +++ b/lib/inets/src/http_server/httpd_instance_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -100,7 +100,9 @@ start_link(ConfigFile, AcceptTimeout, ListenInfo, Debug) -> init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port]) -> httpd_util:enable_debug(Debug), Flags = {one_for_one, 0, 1}, - Children = [sup_spec(httpd_acceptor_sup, Address, Port), + Children = [httpd_connection_sup_spec(Address, Port), + httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, + undefined), sup_spec(httpd_misc_sup, Address, Port), worker_spec(httpd_manager, Address, Port, ConfigFile, ConfigList,AcceptTimeout)], @@ -108,7 +110,9 @@ init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port]) -> init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo]) -> httpd_util:enable_debug(Debug), Flags = {one_for_one, 0, 1}, - Children = [sup_spec(httpd_acceptor_sup, Address, Port), + Children = [httpd_connection_sup_spec(Address, Port), + httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, + ListenInfo), sup_spec(httpd_misc_sup, Address, Port), worker_spec(httpd_manager, Address, Port, ListenInfo, ConfigFile, ConfigList, AcceptTimeout)], @@ -118,6 +122,24 @@ init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo]) %%%========================================================================= %%% Internal functions %%%========================================================================= +httpd_connection_sup_spec(Address, Port) -> + Name = {httpd_connection_sup, Address, Port}, + StartFunc = {httpd_connection_sup, start_link, [[Address, Port]]}, + Restart = permanent, + Shutdown = 5000, + Modules = [httpd_connection_sup], + Type = supervisor, + {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, ListenInfo) -> + Name = {httpd_acceptor_sup, Address, Port}, + StartFunc = {httpd_acceptor_sup, start_link, [[Address, Port, ConfigList, AcceptTimeout, ListenInfo]]}, + Restart = permanent, + Shutdown = infinity, + Modules = [httpd_acceptor_sup], + Type = supervisor, + {Name, StartFunc, Restart, Shutdown, Type, Modules}. + sup_spec(SupModule, Address, Port) -> Name = {SupModule, Address, Port}, StartFunc = {SupModule, start_link, [Address, Port]}, @@ -167,5 +189,3 @@ file_2_config(ConfigFile) -> Error -> Error end. - - diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl index 00384fa108..3da0343401 100644 --- a/lib/inets/src/http_server/httpd_manager.erl +++ b/lib/inets/src/http_server/httpd_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,11 +25,11 @@ -behaviour(gen_server). %% Application internal API --export([start/2, start_link/2, start_link/3, start_link/4, stop/1, reload/2]). --export([new_connection/1, done_connection/1]). --export([config_lookup/2, config_lookup/3, - config_multi_lookup/2, config_multi_lookup/3, - config_match/2, config_match/3]). +-export([start/2, start_link/2, start_link/3, start_link/4, + stop/1, reload/2]). +-export([new_connection/1]). +-export([config_match/2, config_match/3]). +-export([block/2, block/3, unblock/1]). %% gen_server exports -export([init/1, @@ -37,34 +37,19 @@ terminate/2, code_change/3]). - -%% Management exports --export([block/2, block/3, unblock/1]). --export([get_admin_state/1, get_usage_state/1]). --export([is_busy/1,is_busy/2,is_busy_or_blocked/1,is_blocked/1]). %% ??????? --export([get_status/1, get_status/2]). - --export([c/1]). - -record(state,{socket_type = ip_comm, config_file, config_db = null, - connections, %% Current request handlers + connection_sup, admin_state = unblocked, blocker_ref = undefined, - blocking_tmr = undefined, + blocking_from = undefined, + shutdown_poller = undefined, status = []}). +%%%-------------------------------------------------------------------- +%%% Application internal API +%%%-------------------------------------------------------------------- - -%%TODO: Clean up this module! - -c(Port) -> - Ref = httpd_util:make_name("httpd",undefined,Port), - call(Ref, fake_close). - -%% -%% External API -%% %% Deprecated start(ConfigFile, ConfigList) -> Port = proplists:get_value(port,ConfigList,80), @@ -83,7 +68,8 @@ start_link(ConfigFile, ConfigList, AcceptTimeout) -> Name = make_name(Addr, Port), gen_server:start_link({local, Name},?MODULE, - [ConfigFile, ConfigList, AcceptTimeout, Addr, Port],[]). + [ConfigFile, ConfigList, + AcceptTimeout, Addr, Port],[]). start_link(ConfigFile, ConfigList, AcceptTimeout, ListenSocket) -> Port = proplists:get_value(port, ConfigList, 80), @@ -93,146 +79,33 @@ start_link(ConfigFile, ConfigList, AcceptTimeout, ListenSocket) -> gen_server:start_link({local, Name},?MODULE, [ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenSocket],[]). - stop(ServerRef) -> call(ServerRef, stop). reload(ServerRef, Conf) -> call(ServerRef, {reload, Conf}). - -%%%---------------------------------------------------------------- - -block(ServerRef, disturbing) -> - call(ServerRef,block); - -block(ServerRef, non_disturbing) -> - do_block(ServerRef, non_disturbing, infinity). +block(ServerRef, Method) -> + block(ServerRef, Method, infinity). block(ServerRef, Method, Timeout) -> - do_block(ServerRef, Method, Timeout). - - -%% The reason for not using call here, is that the manager cannot -%% _wait_ for completion of the requests. It must be able to do -%% do other things at the same time as the blocking goes on. -do_block(ServerRef, Method, infinity) -> - Ref = make_ref(), - cast(ServerRef, {block, Method, infinity, self(), Ref}), - receive - {block_reply, Reply, Ref} -> - Reply - end; -do_block(ServerRef,Method,Timeout) when Timeout > 0 -> - Ref = make_ref(), - cast(ServerRef,{block,Method,Timeout,self(),Ref}), - receive - {block_reply,Reply,Ref} -> - Reply - end. - - -%%%---------------------------------------------------------------- - -%% unblock + call(ServerRef, {block, self(), Method, Timeout}). unblock(ServerRef) -> - call(ServerRef,unblock). - -%% get admin/usage state - -get_admin_state(ServerRef) -> - call(ServerRef,get_admin_state). - -get_usage_state(ServerRef) -> - call(ServerRef,get_usage_state). - - -%% get_status - -get_status(ServerRef) -> - gen_server:call(ServerRef,get_status). - -get_status(ServerRef,Timeout) -> - gen_server:call(ServerRef,get_status,Timeout). - -%% -%% Internal API -%% - - -%% new_connection + call(ServerRef,{unblock, self()}). new_connection(Manager) -> - gen_server:call(Manager, {new_connection, self()}, infinity). - -%% done - -done_connection(Manager) -> - gen_server:cast(Manager, {done_connection, self()}). - - -%% is_busy(ServerRef) -> true | false -%% -%% Tests if the server is (in usage state) busy, -%% i.e. has rached the heavy load limit. -%% - -is_busy(ServerRef) -> - gen_server:call(ServerRef,is_busy). - -is_busy(ServerRef,Timeout) -> - gen_server:call(ServerRef,is_busy,Timeout). - - -%% is_busy_or_blocked(ServerRef) -> busy | blocked | false -%% -%% Tests if the server is busy (usage state), i.e. has rached, -%% the heavy load limit, or blocked (admin state) . -%% - -is_busy_or_blocked(ServerRef) -> - gen_server:call(ServerRef,is_busy_or_blocked). - - -%% is_blocked(ServerRef) -> true | false -%% -%% Tests if the server is blocked (admin state) . -%% - -is_blocked(ServerRef) -> - gen_server:call(ServerRef,is_blocked). - - -%% -%% Module API. Theese functions are intended for use from modules only. -%% - -config_lookup(Port, Query) -> - config_lookup(undefined, Port, Query). -config_lookup(Addr, Port, Query) -> - Name = httpd_util:make_name("httpd",Addr,Port), - gen_server:call(whereis(Name), {config_lookup, Query}). - -config_multi_lookup(Port, Query) -> - config_multi_lookup(undefined,Port,Query). -config_multi_lookup(Addr,Port, Query) -> - Name = httpd_util:make_name("httpd",Addr,Port), - gen_server:call(whereis(Name), {config_multi_lookup, Query}). + call(Manager, {new_connection, self()}). config_match(Port, Pattern) -> config_match(undefined,Port,Pattern). config_match(Addr, Port, Pattern) -> Name = httpd_util:make_name("httpd",Addr,Port), - gen_server:call(whereis(Name), {config_match, Pattern}). - - -%% -%% Server call-back functions -%% - -%% init + call(whereis(Name), {config_match, Pattern}). +%%%-------------------------------------------------------------------- +%%% gen_server callbacks functions +%%%-------------------------------------------------------------------- init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port]) -> process_flag(trap_exit, true), case (catch do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port)) of @@ -263,47 +136,35 @@ init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo]) -> {ok, State} end. -do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) -> - IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4), +do_init(ConfigFile, ConfigList, _AcceptTimeout, Addr, Port) -> + Sup = httpd_util:make_name("httpd_connection_sup", Addr, Port), NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile), ConfigDB = do_initial_store(ConfigList), SocketType = httpd_conf:lookup_socket_type(ConfigDB), - case httpd_acceptor_sup:start_acceptor(SocketType, Addr, - Port, IpFamily, ConfigDB, AcceptTimeout) of - {ok, _Pid} -> - Status = [{max_conn, 0}, - {last_heavy_load, never}, - {last_connection, never}], + Status = [{max_conn, 0}, + {last_heavy_load, never}, + {last_connection, never}], State = #state{socket_type = SocketType, config_file = NewConfigFile, config_db = ConfigDB, - connections = [], + connection_sup = Sup, status = Status}, - {ok, State}; - Else -> - Else - end. + {ok, State}. -do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo) -> - IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4), +do_init(ConfigFile, ConfigList, _AcceptTimeout, Addr, Port, _ListenInfo) -> + Sup = httpd_util:make_name("httpd_connection_sup", Addr, Port), NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile), ConfigDB = do_initial_store(ConfigList), SocketType = httpd_conf:lookup_socket_type(ConfigDB), - case httpd_acceptor_sup:start_acceptor(SocketType, Addr, - Port, IpFamily, ConfigDB, - AcceptTimeout, ListenInfo) of - {ok, _Pid} -> - Status = [{max_conn,0}, {last_heavy_load,never}, - {last_connection,never}], + Status = [{max_conn,0}, {last_heavy_load,never}, + {last_connection,never}], State = #state{socket_type = SocketType, config_file = NewConfigFile, config_db = ConfigDB, - connections = [], + connection_sup = Sup, status = Status}, - {ok, State}; - Else -> - Else - end. + {ok, State}. + do_initial_store(ConfigList) -> case httpd_conf:store(ConfigList) of @@ -313,75 +174,14 @@ do_initial_store(ConfigList) -> throw({error, Reason}) end. - - -%% handle_call - handle_call(stop, _From, State) -> {stop, normal, ok, State}; -handle_call({config_lookup, Query}, _From, State) -> - Res = httpd_util:lookup(State#state.config_db, Query), - {reply, Res, State}; - -handle_call({config_multi_lookup, Query}, _From, State) -> - Res = httpd_util:multi_lookup(State#state.config_db, Query), - {reply, Res, State}; - handle_call({config_match, Query}, _From, State) -> Res = ets:match_object(State#state.config_db, Query), {reply, Res, State}; -handle_call(get_status, _From, State) -> - ManagerStatus = manager_status(self()), - S1 = [{current_conn,length(State#state.connections)}|State#state.status]++ - [ManagerStatus], - {reply,S1,State}; - -handle_call(is_busy, _From, State) -> - Reply = case get_ustate(State) of - busy -> - true; - _ -> - false - end, - {reply,Reply,State}; - -handle_call(is_busy_or_blocked, _From, State) -> - Reply = - case get_astate(State) of - unblocked -> - case get_ustate(State) of - busy -> - busy; - _ -> - false - end; - _ -> - blocked - end, - {reply,Reply,State}; - -handle_call(is_blocked, _From, State) -> - Reply = - case get_astate(State) of - unblocked -> - false; - _ -> - true - end, - {reply,Reply,State}; - -handle_call(get_admin_state, _From, State) -> - Reply = get_astate(State), - {reply,Reply,State}; - -handle_call(get_usage_state, _From, State) -> - Reply = get_ustate(State), - {reply,Reply,State}; - -handle_call({reload, Conf}, _From, State) - when State#state.admin_state =:= blocked -> +handle_call({reload, Conf}, _From, #state{admin_state = blocked} = State) -> case handle_reload(Conf, State) of {stop, Reply,S1} -> {stop, Reply, S1}; @@ -392,13 +192,33 @@ handle_call({reload, Conf}, _From, State) handle_call({reload, _}, _From, State) -> {reply,{error,{invalid_admin_state,State#state.admin_state}},State}; -handle_call(block, _From, State) -> - {Reply,S1} = handle_block(State), - {reply,Reply,S1}; +handle_call({block , Blocker, Mode, Timeout}, From, + #state{admin_state = unblocked, + connection_sup = CSup} = State) -> + Monitor = erlang:monitor(process, Blocker), + case count_children(CSup) of + 0 -> + %% Already in idle usage state => go directly to blocked + {reply, ok, State#state{admin_state = blocked, + blocker_ref = {Blocker, Monitor}, + blocking_from = From}}; + _ -> + handle_block(Mode, Timeout, + State#state{blocker_ref = {Blocker, Monitor}, + blocking_from = From}) + end; +handle_call({block , _, _, _}, _, State) -> + {reply, {error, blocked}, State}; -handle_call(unblock, {From,_Tag}, State) -> - {Reply,S1} = handle_unblock(State,From), - {reply, Reply, S1}; +handle_call({unblock, Blocker}, _, #state{blocker_ref = {Blocker, Monitor}, + admin_state = blocked} = State) -> + + erlang:demonitor(Monitor), + {reply, ok, + State#state{admin_state = unblocked, blocker_ref = undefined}}; + +handle_call({unblock, _}, _, State) -> + {reply, {error, only_blocker_may_unblock}, State}; handle_call({new_connection, Pid}, _From, State) -> {Status, NewState} = handle_new_connection(State, Pid), @@ -415,21 +235,6 @@ handle_call(Request, From, State) -> report_error(State,String), {reply, ok, State}. - -%% handle_cast - -handle_cast({done_connection, Pid}, State) -> - S1 = handle_done_connection(State, Pid), - {noreply, S1}; - -handle_cast({block, disturbing, Timeout, From, Ref}, State) -> - S1 = handle_block(State, Timeout, From, Ref), - {noreply,S1}; - -handle_cast({block, non_disturbing, Timeout, From, Ref}, State) -> - S1 = handle_nd_block(State, Timeout, From, Ref), - {noreply,S1}; - handle_cast(Message, State) -> String = lists:flatten( @@ -440,32 +245,50 @@ handle_cast(Message, State) -> report_error(State, String), {noreply, State}. -%% handle_info - -handle_info({block_timeout, Method}, State) -> - S1 = handle_block_timeout(State,Method), - {noreply, S1}; +handle_info(connections_terminated, #state{admin_state = shutting_down, + blocking_from = From} = State) -> + gen_server:reply(From, ok), + {noreply, State#state{admin_state = blocked, blocking_from = undefined}}; +handle_info(connections_terminated, State) -> + {noreply, State}; -handle_info({'DOWN', Ref, process, _Object, _Info}, State) -> - S1 = - case State#state.blocker_ref of - Ref -> - handle_blocker_exit(State); - _ -> - %% Not our blocker, so ignore - State - end, - {noreply, S1}; +handle_info({block_timeout, non_disturbing, Blocker}, + #state{admin_state = shutting_down, + blocking_from = From, + blocker_ref = {_, Monitor} = Blocker} = State) -> + erlang:demonitor(Monitor), + gen_server:reply(From, {error, timeout}), + {noreply, State#state{admin_state = unblocked, blocking_from = undefined, + blocker_ref = undefined}}; +handle_info({block_timeout, disturbing, Blocker}, + #state{admin_state = shutting_down, + blocking_from = From, + blocker_ref = Blocker, + connection_sup = Sup} = State) -> + SupPid = whereis(Sup), + shutdown_connections(SupPid), + gen_server:reply(From, ok), + {noreply, State#state{admin_state = blocked, + blocking_from = undefined}}; +handle_info({block_timeout, _, _}, State) -> + {noreply, State}; + +handle_info({'DOWN', _, process, Pid, _Info}, + #state{admin_state = Admin, + blocker_ref = {Pid, Monitor}} = State) when + Admin =/= unblocked -> + erlang:demonitor(Monitor), + {noreply, State#state{admin_state = unblocked, + blocking_from = undefined, + blocker_ref = undefined}}; +handle_info({'DOWN', _, process, _, _}, State) -> + {noreply, State}; handle_info({'EXIT', _, normal}, State) -> {noreply, State}; -handle_info({'EXIT', _, blocked}, S) -> - {noreply, S}; - -handle_info({'EXIT', Pid, Reason}, State) -> - S1 = check_connections(State, Pid, Reason), - {noreply, S1}; +handle_info({'EXIT', _, shutdown}, State) -> + {stop, shutdown, State}; handle_info(Info, State) -> String = @@ -477,217 +300,64 @@ handle_info(Info, State) -> report_error(State, String), {noreply, State}. - -%% terminate - terminate(_, #state{config_db = Db}) -> httpd_conf:remove_all(Db), ok. - -%% code_change({down,ToVsn}, State, Extra) -%% - code_change({down,_ToVsn}, State, _Extra) -> {ok,State}; -%% code_change(FromVsn, State, Extra) -%% code_change(_FromVsn, State, _Extra) -> {ok,State}. - - -%% ------------------------------------------------------------------------- -%% check_connection -%% -%% -%% -%% - -check_connections(#state{connections = []} = State, _Pid, _Reason) -> - State; -check_connections(#state{connections = Connections} = State, Pid, _Reason) -> - State#state{connections = lists:delete(Pid, Connections)}. - - -%% ------------------------------------------------------------------------- -%% handle_[new | done]_connection -%% -%% -%% -%% - -handle_new_connection(State, Handler) -> +%%%-------------------------------------------------------------------- +%%% Internal functions +%%%-------------------------------------------------------------------- +handle_new_connection(#state{admin_state = AdminState} = State, Handler) -> UsageState = get_ustate(State), - AdminState = get_astate(State), handle_new_connection(UsageState, AdminState, State, Handler). -handle_new_connection(busy, unblocked, State, _Handler) -> - Status = update_heavy_load_status(State#state.status), - {{reject, busy}, - State#state{status = Status}}; - -handle_new_connection(_UsageState, unblocked, State, Handler) -> - Connections = State#state.connections, - Status = update_connection_status(State#state.status, - length(Connections)+1), - link(Handler), - {{ok, accept}, - State#state{connections = [Handler|Connections], status = Status}}; - -handle_new_connection(_UsageState, _AdminState, State, _Handler) -> - {{reject, blocked}, - State}. - -handle_done_connection(#state{admin_state = shutting_down, - connections = Connections} = State, Handler) -> - unlink(Handler), - case lists:delete(Handler, Connections) of - [] -> % Ok, block complete - demonitor_blocker(State#state.blocker_ref), - {Tmr,From,Ref} = State#state.blocking_tmr, - stop_block_tmr(Tmr), - From ! {block_reply,ok,Ref}, - State#state{admin_state = blocked, connections = [], - blocker_ref = undefined}; - Connections1 -> - State#state{connections = Connections1} - end; - -handle_done_connection(#state{connections = Connections} = State, Handler) -> - State#state{connections = lists:delete(Handler, Connections)}. - - -%% ------------------------------------------------------------------------- -%% handle_block -%% -%% -%% -%% -handle_block(#state{admin_state = AdminState} = S) -> - handle_block(S, AdminState). - -handle_block(S,unblocked) -> - %% Kill all connections - [kill_handler(Pid) || Pid <- S#state.connections], - {ok,S#state{connections = [], admin_state = blocked}}; -handle_block(S,blocked) -> - {ok,S}; -handle_block(S,shutting_down) -> - {{error,shutting_down},S}. - - -kill_handler(Pid) -> - exit(Pid, blocked). - -handle_block(S,Timeout,From,Ref) when Timeout >= 0 -> - do_block(S,Timeout,From,Ref); - -handle_block(S,Timeout,From,Ref) -> - Reply = {error,{invalid_block_request,Timeout}}, - From ! {block_reply,Reply,Ref}, - S. - -do_block(S,Timeout,From,Ref) -> - case S#state.connections of - [] -> - %% Already in idle usage state => go directly to blocked - From ! {block_reply,ok,Ref}, - S#state{admin_state = blocked}; - _ -> - %% Active or Busy usage state => go to shutting_down - %% Make sure we get to know if blocker dies... - MonitorRef = monitor_blocker(From), - Tmr = {start_block_tmr(Timeout,disturbing),From,Ref}, - S#state{admin_state = shutting_down, - blocker_ref = MonitorRef, blocking_tmr = Tmr} - end. - -handle_nd_block(S,infinity,From,Ref) -> - do_nd_block(S,infinity,From,Ref); - -handle_nd_block(S,Timeout,From,Ref) when Timeout >= 0 -> - do_nd_block(S,Timeout,From,Ref); - -handle_nd_block(S,Timeout,From,Ref) -> - Reply = {error,{invalid_block_request,Timeout}}, - From ! {block_reply,Reply,Ref}, - S. - -do_nd_block(S,Timeout,From,Ref) -> - case S#state.connections of - [] -> - %% Already in idle usage state => go directly to blocked - From ! {block_reply,ok,Ref}, - S#state{admin_state = blocked}; +handle_new_connection(_UsageState, unblocked, + #state{config_db = Db, connection_sup = CSup} = + State, _) -> + Max = httpd_util:lookup(Db, max_clients), + case count_children(CSup) of + Count when Count =< Max -> + {{ok, accept}, State}; _ -> - %% Active or Busy usage state => go to shutting_down - %% Make sure we get to know if blocker dies... - MonitorRef = monitor_blocker(From), - Tmr = {start_block_tmr(Timeout,non_disturbing),From,Ref}, - S#state{admin_state = shutting_down, - blocker_ref = MonitorRef, blocking_tmr = Tmr} - end. + {{reject, busy}, State} + end; -handle_block_timeout(S,Method) -> - %% Time to take this to the road... - demonitor_blocker(S#state.blocker_ref), - handle_block_timeout1(S,Method,S#state.blocking_tmr). - -handle_block_timeout1(S,non_disturbing,{_,From,Ref}) -> - From ! {block_reply,{error,timeout},Ref}, - S#state{admin_state = unblocked, - blocker_ref = undefined, blocking_tmr = undefined}; - -handle_block_timeout1(S,disturbing,{_,From,Ref}) -> - [exit(Pid,blocked) || Pid <- S#state.connections], - - From ! {block_reply,ok,Ref}, - S#state{admin_state = blocked, connections = [], - blocker_ref = undefined, blocking_tmr = undefined}; - -handle_block_timeout1(S,Method,{_,From,Ref}) -> - From ! {block_reply,{error,{unknown_block_method,Method}},Ref}, - S#state{admin_state = blocked, connections = [], - blocker_ref = undefined, blocking_tmr = undefined}; - -handle_block_timeout1(S, _Method, _TmrInfo) -> - S#state{admin_state = unblocked, - blocker_ref = undefined, blocking_tmr = undefined}. - -handle_unblock(S, FromA) -> - handle_unblock(S, FromA, S#state.admin_state). - -handle_unblock(S, _FromA, unblocked) -> - {ok,S}; -handle_unblock(S, FromA, _AdminState) -> - case S#state.blocking_tmr of - {Tmr,FromB,Ref} -> - %% Another process is trying to unblock - %% Inform the blocker - stop_block_tmr(Tmr), - FromB ! {block_reply, {error,{unblocked,FromA}},Ref}; - _ -> - ok - end, - {ok,S#state{admin_state = unblocked, blocking_tmr = undefined}}. - -%% The blocker died so we give up on the block. -handle_blocker_exit(S) -> - {Tmr,_From,_Ref} = S#state.blocking_tmr, - stop_block_tmr(Tmr), - S#state{admin_state = unblocked, - blocker_ref = undefined, blocking_tmr = undefined}. +handle_new_connection(_UsageState, _AdminState, State, _Handler) -> + {{reject, blocked}, State}. + +handle_block(disturbing, infinity, + #state{connection_sup = CSup, + blocking_from = From} = State) -> + SupPid = whereis(CSup), + shutdown_connections(SupPid), + gen_server:reply(From, ok), + {noreply, State#state{admin_state = blocked, + blocking_from = undefined}}; +handle_block(disturbing, Timeout, #state{connection_sup = CSup, blocker_ref = Blocker} = State) -> + Manager = self(), + spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end), + erlang:send_after(Timeout, self(), {block_timeout, disturbing, Blocker}), + {noreply, State#state{admin_state = shutting_down}}; + +handle_block(non_disturbing, infinity, + #state{connection_sup = CSup} = State) -> + Manager = self(), + spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end), + {noreply, State#state{admin_state = shutting_down}}; + +handle_block(non_disturbing, Timeout, + #state{connection_sup = CSup, blocker_ref = Blocker} = State) -> + Manager = self(), + spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end), + erlang:send_after(Timeout, self(), {block_timeout, non_disturbing, Blocker}), + {noreply, State#state{admin_state = shutting_down}}. - - -%% ------------------------------------------------------------------------- -%% handle_reload -%% -%% -%% -%% handle_reload(undefined, #state{config_file = undefined} = State) -> {continue, {error, undefined_config_file}, State}; handle_reload(undefined, #state{config_file = ConfigFile} = State) -> @@ -763,7 +433,7 @@ check_constant_values(Db, Config) -> %% Otherwise -> active %% get_ustate(State) -> - get_ustate(length(State#state.connections),State). + get_ustate(count_children(State#state.connection_sup),State). get_ustate(0,_State) -> idle; @@ -776,76 +446,6 @@ get_ustate(ConnectionCnt,State) -> active end. - -get_astate(S) -> S#state.admin_state. - - -%% Timer handling functions -start_block_tmr(infinity,_) -> - undefined; -start_block_tmr(T,M) -> - erlang:send_after(T,self(),{block_timeout,M}). - -stop_block_tmr(undefined) -> - ok; -stop_block_tmr(Ref) -> - erlang:cancel_timer(Ref). - - -%% Monitor blocker functions -monitor_blocker(Pid) when is_pid(Pid) -> - case (catch erlang:monitor(process,Pid)) of - {'EXIT', _Reason} -> - undefined; - MonitorRef -> - MonitorRef - end; -monitor_blocker(_) -> - undefined. - -demonitor_blocker(undefined) -> - ok; -demonitor_blocker(Ref) -> - (catch erlang:demonitor(Ref)). - - -%% Some status utility functions - -update_heavy_load_status(Status) -> - update_status_with_time(Status,last_heavy_load). - -update_connection_status(Status,ConnCount) -> - S1 = case lists:keysearch(max_conn,1,Status) of - {value, {max_conn, C1}} when ConnCount > C1 -> - lists:keyreplace(max_conn,1,Status,{max_conn,ConnCount}); - {value, {max_conn, _C2}} -> - Status; - false -> - [{max_conn, ConnCount} | Status] - end, - update_status_with_time(S1,last_connection). - -update_status_with_time(Status,Key) -> - lists:keyreplace(Key,1,Status,{Key,universal_time()}). - -universal_time() -> calendar:universal_time(). - -manager_status(P) -> - Items = [status, message_queue_len, reductions, - heap_size, stack_size], - {manager_status, process_status(P,Items,[])}. - - -process_status(P,[],L) -> - [{pid,P}|lists:reverse(L)]; -process_status(P,[H|T],L) -> - case (catch process_info(P,H)) of - {H, Value} -> - process_status(P,T,[{H,Value}|L]); - _ -> - process_status(P,T,[{H,undefined}|L]) - end. - make_name(Addr,Port) -> httpd_util:make_name("httpd",Addr,Port). @@ -856,10 +456,31 @@ report_error(State,String) -> mod_log:report_error(Cdb,String), mod_disk_log:report_error(Cdb,String). -%% -call(ServerRef,Request) -> - gen_server:call(ServerRef,Request). +call(ServerRef, Request) -> + try gen_server:call(ServerRef, Request, infinity) + catch + exit:_ -> + {error, closed} + end. + +count_children(Sup) -> + Children = supervisor:count_children(whereis(Sup)), + proplists:get_value(workers, Children). -cast(ServerRef,Message) -> - gen_server:cast(ServerRef,Message). +shutdown_connections(Sup) -> + Children = [Child || {_,Child,_,_} <- supervisor:which_children(Sup)], + lists:foreach(fun(Pid) -> exit(Pid, kill) end, + Children). + +wait_for_shutdown(CSup, Manager) -> + case count_children(CSup) of + 0 -> + Manager ! connections_terminated; + _ -> + receive + after 500 -> + ok + end, + wait_for_shutdown(CSup, Manager) + end. diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index ea7a17e40d..bd37066ff6 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,7 +25,7 @@ -behaviour(gen_server). %% Application internal API --export([start/2, start/3, socket_ownership_transfered/3]). +-export([start_link/2, start_link/3, socket_ownership_transfered/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -57,10 +57,10 @@ %% Description: Starts a httpd-request handler process. Intended to be %% called by the httpd acceptor process. %%-------------------------------------------------------------------- -start(Manager, ConfigDB) -> - start(Manager, ConfigDB, 15000). -start(Manager, ConfigDB, AcceptTimeout) -> - proc_lib:start(?MODULE, init, [[Manager, ConfigDB,AcceptTimeout]]). +start_link(Manager, ConfigDB) -> + start_link(Manager, ConfigDB, 15000). +start_link(Manager, ConfigDB, AcceptTimeout) -> + proc_lib:start_link(?MODULE, init, [[Manager, ConfigDB,AcceptTimeout]]). %%-------------------------------------------------------------------- @@ -87,34 +87,27 @@ socket_ownership_transfered(Pid, SocketType, Socket) -> %% gen_server provides is needed. %%-------------------------------------------------------------------- init([Manager, ConfigDB, AcceptTimeout]) -> - ?hdrd("initiate", - [{manager, Manager}, {cdb, ConfigDB}, {timeout, AcceptTimeout}]), + process_flag(trap_exit, true), %% Make sure this process terminates if the httpd manager process %% should die! - link(Manager), + %%link(Manager), %% At this point the function httpd_request_handler:start/2 will return. proc_lib:init_ack({ok, self()}), {SocketType, Socket} = await_socket_ownership_transfer(AcceptTimeout), - ?hdrd("socket ownership transfered", - [{socket_type, SocketType}, {socket, Socket}]), - + TimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000), Then = erlang:now(), - ?hdrd("negotiate", []), case http_transport:negotiate(SocketType, Socket, TimeOut) of - {error, Error} -> - ?hdrd("negotiation failed", [{error, Error}]), + {error, _Error} -> exit(shutdown); %% Can be 'normal'. ok -> - ?hdrt("negotiation successfull", []), NewTimeout = TimeOut - timer:now_diff(now(),Then) div 1000, continue_init(Manager, ConfigDB, SocketType, Socket, NewTimeout) end. continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) -> - ?hdrt("continue init", [{timeout, TimeOut}]), Resolve = http_transport:resolve(), Peername = httpd_socket:peername(SocketType, Socket), @@ -139,14 +132,10 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) -> max_keep_alive_request = NrOfRequest, mfa = MFA}, - ?hdrt("activate request timeout", []), - - ?hdrt("set socket options (binary, packet & active)", []), http_transport:setopts(SocketType, Socket, [binary, {packet, 0}, {active, once}]), NewState = data_receive_counter(activate_request_timeout(State), httpd_util:lookup(ConfigDB, minimum_bytes_per_second, false)), - ?hdrt("init done", []), - gen_server:enter_loop(?MODULE, [], NewState). + gen_server:enter_loop(?MODULE, [], NewState). %%==================================================================== @@ -195,18 +184,13 @@ handle_cast(Msg, #state{mod = ModData} = State) -> %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- handle_info({Proto, Socket, Data}, - #state{mfa = {Module, Function, Args} = MFA, + #state{mfa = {Module, Function, Args}, mod = #mod{socket_type = SockType, socket = Socket} = ModData} = State) when (((Proto =:= tcp) orelse (Proto =:= ssl) orelse (Proto =:= dummy)) andalso is_binary(Data)) -> - ?hdrd("received data", - [{data, Data}, {proto, Proto}, - {socket, Socket}, {socket_type, SockType}, {mfa, MFA}]), - -%% case (catch Module:Function([Data | Args])) of PROCESSED = (catch Module:Function([Data | Args])), NewDataSize = case State#state.byte_limit of undefined -> @@ -214,10 +198,8 @@ handle_info({Proto, Socket, Data}, _ -> State#state.data + byte_size(Data) end, - ?hdrt("data processed", [{processing_result, PROCESSED}]), case PROCESSED of {ok, Result} -> - ?hdrd("data processed", [{result, Result}]), NewState = case NewDataSize of undefined -> cancel_request_timeout(State); @@ -227,7 +209,6 @@ handle_info({Proto, Socket, Data}, handle_http_msg(Result, NewState); {error, {uri_too_long, MaxSize}, Version} -> - ?hdrv("uri too long", [{max_size, MaxSize}, {version, Version}]), NewModData = ModData#mod{http_version = Version}, httpd_response:send_status(NewModData, 414, "URI too long"), Reason = io_lib:format("Uri too long, max size is ~p~n", @@ -236,8 +217,6 @@ handle_info({Proto, Socket, Data}, {stop, normal, State#state{response_sent = true, mod = NewModData}}; {error, {header_too_long, MaxSize}, Version} -> - ?hdrv("header too long", - [{max_size, MaxSize}, {version, Version}]), NewModData = ModData#mod{http_version = Version}, httpd_response:send_status(NewModData, 413, "Header too long"), Reason = io_lib:format("Header too long, max size is ~p~n", @@ -246,7 +225,6 @@ handle_info({Proto, Socket, Data}, {stop, normal, State#state{response_sent = true, mod = NewModData}}; NewMFA -> - ?hdrd("data processed - reactivate socket", [{new_mfa, NewMFA}]), http_transport:setopts(SockType, Socket, [{active, once}]), case NewDataSize of undefined -> @@ -293,6 +271,10 @@ handle_info(check_data, #state{data = Data, byte_limit = Byte_Limit} = State) -> _ -> {stop, normal, State#state{response_sent = true}} end; + +handle_info({'EXIT', _, Reason}, State) -> + {stop, Reason, State}; + %% Default case handle_info(Info, #state{mod = ModData} = State) -> Error = lists:flatten( @@ -324,10 +306,8 @@ terminate(Reason, #state{response_sent = false, mod = ModData} = State) -> terminate(_Reason, State) -> do_terminate(State). -do_terminate(#state{mod = ModData, manager = Manager} = State) -> - catch httpd_manager:done_connection(Manager), +do_terminate(#state{mod = ModData} = State) -> cancel_request_timeout(State), - %% receive after 5000 -> ok end, httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket). @@ -355,30 +335,24 @@ await_socket_ownership_transfer(AcceptTimeout) -> handle_http_msg({_, _, Version, {_, _}, _}, #state{status = busy, mod = ModData} = State) -> - ?hdrt("handle http msg when manager busy", [{mod, ModData}]), handle_manager_busy(State#state{mod = ModData#mod{http_version = Version}}), {stop, normal, State}; handle_http_msg({_, _, Version, {_, _}, _}, #state{status = blocked, mod = ModData} = State) -> - ?hdrt("handle http msg when manager blocket", [{mod, ModData}]), handle_manager_blocked(State#state{mod = ModData#mod{http_version = Version}}), {stop, normal, State}; handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body}, #state{status = accept, mod = ModData} = State) -> - ?hdrt("handle http msg when manager accepting", - [{method, Method}, {mod, ModData}]), case httpd_request:validate(Method, Uri, Version) of ok -> - ?hdrt("request validated", []), {ok, NewModData} = httpd_request:update_mod_data(ModData, Method, Uri, Version, Headers), - ?hdrt("new mod data", [{mod, NewModData}]), case is_host_specified_if_required(NewModData#mod.absolute_uri, RecordHeaders, Version) of true -> @@ -392,23 +366,18 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body}, {stop, normal, State#state{response_sent = true}} end; {error, {not_supported, What}} -> - ?hdrd("validation failed: not supported", [{what, What}]), httpd_response:send_status(ModData#mod{http_version = Version}, 501, {Method, Uri, Version}), Reason = io_lib:format("Not supported: ~p~n", [What]), error_log(Reason, ModData), {stop, normal, State#state{response_sent = true}}; {error, {bad_request, {forbidden, URI}}} -> - ?hdrd("validation failed: bad request - forbidden", - [{uri, URI}]), httpd_response:send_status(ModData#mod{http_version = Version}, 403, URI), Reason = io_lib:format("Forbidden URI: ~p~n", [URI]), error_log(Reason, ModData), {stop, normal, State#state{response_sent = true}}; {error, {bad_request, {malformed_syntax, URI}}} -> - ?hdrd("validation failed: bad request - malformed syntax", - [{uri, URI}]), httpd_response:send_status(ModData#mod{http_version = Version}, 400, URI), Reason = io_lib:format("Malformed syntax in URI: ~p~n", [URI]), @@ -417,12 +386,9 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body}, end; handle_http_msg({ChunkedHeaders, Body}, State = #state{headers = Headers}) -> - ?hdrt("handle http msg", - [{chunked_headers, ChunkedHeaders}, {body, Body}]), NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders), handle_response(State#state{headers = NewHeaders, body = Body}); handle_http_msg(Body, State) -> - ?hdrt("handle http msg", [{body, Body}]), handle_response(State#state{body = Body}). handle_manager_busy(#state{mod = #mod{config_db = ConfigDB}} = State) -> @@ -445,7 +411,6 @@ is_host_specified_if_required(_, _, _) -> true. handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) -> - ?hdrt("handle body", []), MaxHeaderSize = max_header_size(ConfigDB), MaxBodySize = max_body_size(ConfigDB), @@ -459,34 +424,22 @@ handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) -> handle_body(#state{headers = Headers, body = Body, mod = ModData} = State, MaxHeaderSize, MaxBodySize) -> - ?hdrt("handle body", [{headers, Headers}, {body, Body}]), case Headers#http_request_h.'transfer-encoding' of "chunked" -> - ?hdrt("chunked - attempt decode", []), case http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of {Module, Function, Args} -> - ?hdrt("chunk decoded", - [{module, Module}, - {function, Function}, - {args, Args}]), http_transport:setopts(ModData#mod.socket_type, ModData#mod.socket, [{active, once}]), {noreply, State#state{mfa = {Module, Function, Args}}}; {ok, {ChunkedHeaders, NewBody}} -> - ?hdrt("chunk decoded", - [{chunked_headers, ChunkedHeaders}, - {new_body, NewBody}]), NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders), - ?hdrt("chunked - headers handled", - [{new_headers, NewHeaders}]), handle_response(State#state{headers = NewHeaders, body = NewBody}) end; Encoding when is_list(Encoding) -> - ?hdrt("not chunked - encoding", [{encoding, Encoding}]), httpd_response:send_status(ModData, 501, "Unknown Transfer-Encoding"), Reason = io_lib:format("Unknown Transfer-Encoding: ~p~n", @@ -494,17 +447,12 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State, error_log(Reason, ModData), {stop, normal, State#state{response_sent = true}}; _ -> - ?hdrt("not chunked", []), Length = list_to_integer(Headers#http_request_h.'content-length'), case ((Length =< MaxBodySize) or (MaxBodySize == nolimit)) of true -> case httpd_request:whole_body(Body, Length) of {Module, Function, Args} -> - ?hdrt("whole body", - [{module, Module}, - {function, Function}, - {args, Args}]), http_transport:setopts(ModData#mod.socket_type, ModData#mod.socket, [{active, once}]), @@ -512,15 +460,11 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State, {Module, Function, Args}}}; {ok, NewBody} -> - ?hdrt("whole body", - [{new_body, NewBody}]), handle_response( State#state{headers = Headers, body = NewBody}) end; false -> - ?hdrd("body too long", - [{length, Length}, {max_body_size, MaxBodySize}]), httpd_response:send_status(ModData, 413, "Body too long"), error_log("Body too long", ModData), {stop, normal, State#state{response_sent = true}} @@ -582,8 +526,6 @@ handle_response(#state{body = Body, mod = ModData, headers = Headers, max_keep_alive_request = Max} = State) when Max > 0 -> - ?hdrt("handle response", - [{body, Body}, {mod, ModData}, {headers, Headers}, {max, Max}]), {NewBody, Data} = httpd_request:body_data(Headers, Body), ok = httpd_response:generate_and_send_response( ModData#mod{entity_body = NewBody}), @@ -592,8 +534,6 @@ handle_response(#state{body = Body, handle_response(#state{body = Body, headers = Headers, mod = ModData} = State) -> - ?hdrt("handle response", - [{body, Body}, {mod, ModData}, {headers, Headers}]), {NewBody, _} = httpd_request:body_data(Headers, Body), ok = httpd_response:generate_and_send_response( ModData#mod{entity_body = NewBody}), @@ -601,7 +541,6 @@ handle_response(#state{body = Body, handle_next_request(#state{mod = #mod{connection = true} = ModData, max_keep_alive_request = Max} = State, Data) -> - ?hdrt("handle next request", [{max, Max}]), NewModData = #mod{socket_type = ModData#mod.socket_type, socket = ModData#mod.socket, @@ -630,11 +569,9 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData, end; handle_next_request(State, _) -> - ?hdrt("handle next request - stop", []), {stop, normal, State}. activate_request_timeout(#state{timeout = Time} = State) -> - ?hdrt("activate request timeout", [{time, Time}]), Ref = erlang:send_after(Time, self(), timeout), State#state{timer = Ref}. data_receive_counter(State, Byte_limit) -> diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl index b0b18b9c3d..0d04a75205 100644 --- a/lib/inets/src/http_server/httpd_util.erl +++ b/lib/inets/src/http_server/httpd_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -206,9 +206,6 @@ message(413, Reason,_) -> "Entity: " ++ html_encode(Reason); message(414,ReasonPhrase,_) -> "Message " ++ html_encode(ReasonPhrase) ++ "."; -message(416,ReasonPhrase,_) -> - html_encode(ReasonPhrase); - message(500,_,ConfigDB) -> ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"), "The server encountered an internal error or " @@ -233,7 +230,9 @@ message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) -> end; message(503, String, _ConfigDB) -> - "This service in unavailable due to: " ++ html_encode(String). + "This service in unavailable due to: " ++ html_encode(String); +message(_, ReasonPhrase, _) -> + html_encode(ReasonPhrase). maybe_encode(URI) -> Decoded = try http_uri:decode(URI) of diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src index 4aea2ef3d7..9eae962d03 100644 --- a/lib/inets/src/inets_app/inets.app.src +++ b/lib/inets/src/inets_app/inets.app.src @@ -1,7 +1,7 @@ %% This is an -*- erlang -*- file. %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -59,6 +59,7 @@ httpd_acceptor, httpd_acceptor_sup, httpd_cgi, + httpd_connection_sup, httpd_conf, httpd_esi, httpd_example, @@ -109,4 +110,6 @@ {registered,[inets_sup, httpc_manager]}, %% If the "new" ssl is used then 'crypto' must be started before inets. {applications,[kernel,stdlib]}, - {mod,{inets_app,[]}}]}. + {mod,{inets_app,[]}}, + {runtime_dependencies, ["stdlib-2.0","ssl-5.3.4","runtime_tools-1.8.14", + "mnesia-4.12","kernel-3.0","erts-6.0"]}]}. diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index c63dcafa6c..dd081962cc 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -1,7 +1,7 @@ -%% This is an -*- erlang -*- file. +%% -*- erlang -*- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -15,11 +15,13 @@ %% under the License. %% %% %CopyrightEnd% - {"%VSN%", [ - {<<"5\\.*">>, [{restart_application, inets}]} - ], + {"5.9.8", [{load_module, ftp, soft_purge, soft_purge, []}]}, + {<<"5\\..*">>,[{restart_application, inets}]} + ], [ - {<<"5\\.*">>, [{restart_application, inets}]} -]}. + {"5.9.8", [{load_module, ftp, soft_purge, soft_purge, []}]}, + {<<"5\\..*">>,[{restart_application, inets}]} + ] +}. diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile index f18db273ec..609396273d 100644 --- a/lib/inets/test/Makefile +++ b/lib/inets/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2013. All Rights Reserved. +# Copyright Ericsson AB 1997-2014. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -158,12 +158,14 @@ MODULES = \ httpc_cookie_SUITE \ httpc_proxy_SUITE \ httpd_SUITE \ + old_httpd_SUITE \ httpd_basic_SUITE \ httpd_mod \ httpd_block \ httpd_load \ httpd_time_test \ httpd_1_1 \ + httpd_1_0 \ httpd_test_lib \ inets_sup_SUITE \ inets_SUITE \ @@ -201,7 +203,7 @@ INETS_FILES = inets.config $(INETS_SPECS) # inets_tftp_suite INETS_DATADIRS = inets_SUITE_data inets_sup_SUITE_data -HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data +HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data FTP_DATADIRS = ftp_SUITE_data diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl index 35f21cc74d..daee1bdcdc 100644 --- a/lib/inets/test/ftp_suite_lib.erl +++ b/lib/inets/test/ftp_suite_lib.erl @@ -1266,6 +1266,8 @@ read_log_6035([]) -> %%-------------------------------------------------------------------- do_user(Pid) -> {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS), + {error, euser} = ftp:user(Pid, ?FTP_USER++"\r\nPASS "++?FTP_PASS, ?FTP_PASS), + {error, euser} = ftp:user(Pid, ?FTP_USER, ?FTP_PASS++"\r\nCWD ."), ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS), ok. @@ -1278,6 +1280,7 @@ do_pwd(Pid) -> do_cd(Pid) -> ok = ftp:cd(Pid, "/pub"), {error, epath} = ftp:cd(Pid, ?BAD_DIR), + {error, efnamena} = ftp:cd(Pid, "/pub\r\nCWD ."), ok. do_lcd(Pid, Dir) -> @@ -1294,11 +1297,14 @@ do_ls(Pid) -> %% directory, but can also be a filename or a group %% of files (including wildcards). {ok, _} = ftp:ls(Pid, "incom*"), + %% but \r\n can't be in the wildcard + {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."), ok. do_nlist(Pid, WildcardSupport) -> {ok, _} = ftp:nlist(Pid), {ok, _} = ftp:nlist(Pid, "incoming"), + {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group @@ -1324,6 +1330,8 @@ do_rename(Pid, Config) -> ftp:delete(Pid, NewLFile), % reset ok = ftp:send(Pid, LFile), {error, epath} = ftp:rename(Pid, NewLFile, LFile), + {error, efnamena} = ftp:rename(Pid, NewLFile++"\r\nRNTO "++LFile++"\r\nRNFR "++NewLFile, LFile), + {error, efnamena} = ftp:rename(Pid, NewLFile, LFile++"\r\nCWD ."), ok = ftp:rename(Pid, LFile, NewLFile), ftp:delete(Pid, LFile), % cleanup ftp:delete(Pid, NewLFile), % cleanup @@ -1338,6 +1346,7 @@ do_delete(Pid, Config) -> ok = ftp:cd(Pid, "incoming"), ok = ftp:lcd(Pid, PrivDir), ftp:delete(Pid,LFile), % reset + {error, efnamena} = ftp:delete(Pid,LFile++"\r\nCWD ."), ok = ftp:send(Pid, LFile), ok = ftp:delete(Pid,LFile), ok. @@ -1348,6 +1357,8 @@ do_mkdir(Pid) -> integer_to_list(B) ++ "_" ++ integer_to_list(C), ok = ftp:cd(Pid, "incoming"), {ok, CurrDir} = ftp:pwd(Pid), + {error, efnamena} = ftp:mkdir(Pid, NewDir++"\r\nCWD ."), + {error, efnamena} = ftp:rmdir(Pid, NewDir++"\r\nCWD ."), ok = ftp:mkdir(Pid, NewDir), ok = ftp:cd(Pid, NewDir), ok = ftp:cd(Pid, CurrDir), @@ -1363,6 +1374,7 @@ do_send(Pid, Config) -> ok = file:write_file(AbsLFile, list_to_binary(Contents)), ok = ftp:cd(Pid, "incoming"), ok = ftp:lcd(Pid, PrivDir), + {error, efnamena} = ftp:send(Pid, LFile, RFile++"1\r\nCWD ."), ok = ftp:send(Pid, LFile, RFile), {ok, RFilesString} = ftp:nlist(Pid), RFiles = split(RFilesString), @@ -1392,6 +1404,7 @@ do_append(Pid, Config) -> ftp:delete(Pid, RFile), ftp:delete(Pid, LFile), + {error, efnamena} = ftp:append(Pid, LFile, RFile++"1\r\nCWD ."), ok = ftp:append(Pid, LFile, RFile), ok = ftp:append(Pid, LFile, RFile), ok = ftp:append(Pid, LFile), @@ -1413,6 +1426,7 @@ do_send_bin(Pid, Config) -> Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:send_bin(Pid, Contents, File), + {error, efnamena} = ftp:send_bin(Pid, Bin, File++"1\r\nCWD ."), ok = ftp:send_bin(Pid, Bin, File), {ok, RFilesString} = ftp:nlist(Pid), RFiles = split(RFilesString), @@ -1426,6 +1440,7 @@ do_append_bin(Pid, Config) -> Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:append_bin(Pid, Contents, File), + {error, efnamena} = ftp:append_bin(Pid, Bin, File++"1\r\nCWD ."), ok = ftp:append_bin(Pid, Bin, File), ok = ftp:append_bin(Pid, Bin, File), %% Control the contents of the file @@ -1438,6 +1453,7 @@ do_send_chunk(Pid, Config) -> Contents = "ftp_SUITE test ...", Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), + {error, efnamena} = ftp:send_chunk_start(Pid, File++"1\r\nCWD ."), ok = ftp:send_chunk_start(Pid, File), {error, echunk} = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:send_chunk(Pid, Contents), @@ -1454,6 +1470,7 @@ do_append_chunk(Pid, Config) -> File = ?config(file, Config), Contents = ["ER","LE","RL"], ok = ftp:cd(Pid, "incoming"), + {error, efnamena} = ftp:append_chunk_start(Pid, File++"1\r\nCWD ."), ok = ftp:append_chunk_start(Pid, File), {error, enotbinary} = ftp:append_chunk(Pid, lists:nth(1,Contents)), ok = ftp:append_chunk(Pid,list_to_binary(lists:nth(1,Contents))), @@ -1480,6 +1497,7 @@ do_recv(Pid, Config) -> ok = file:delete(AbsFile), % cleanup test_server:sleep(100), ok = ftp:lcd(Pid, PrivDir), + {error, efnamena} = ftp:recv(Pid, File++"\r\nCWD ."), ok = ftp:recv(Pid, File), {ok, Files} = file:list_dir(PrivDir), true = lists:member(File, Files), @@ -1495,6 +1513,7 @@ do_recv_bin(Pid, Config) -> ok = ftp:cd(Pid, "incoming"), ok = ftp:send_bin(Pid, Bin1, File), test_server:sleep(100), + {error, efnamena} = ftp:recv_bin(Pid, File++"\r\nCWD ."), {ok, Bin2} = ftp:recv_bin(Pid, File), ok = ftp:delete(Pid, File), % cleanup Contents2 = binary_to_list(Bin2), @@ -1520,6 +1539,7 @@ do_recv_chunk(Pid, Config) -> ok = ftp:send_bin(Pid, Bin1, File), test_server:sleep(100), {error, "ftp:recv_chunk_start/2 not called"} = recv_chunk(Pid, <<>>), + {error, efnamena} = ftp:recv_chunk_start(Pid, File++"\r\nCWD ."), ok = ftp:recv_chunk_start(Pid, File), {ok, Contents2} = recv_chunk(Pid, <<>>), ok = ftp:delete(Pid, File), % cleanup diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index fe6edd504e..1c3bbcaa9c 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -91,8 +91,10 @@ only_simulated() -> [ cookie, cookie_profile, + empty_set_cookie, trace, stream_once, + stream_single_chunk, no_content_204, tolerate_missing_CR, userinfo, @@ -104,6 +106,7 @@ only_simulated() -> remote_socket_close, remote_socket_close_async, transfer_encoding, + transfer_encoding_identity, redirect_loop, redirect_moved_permanently, redirect_multiple_choises, @@ -296,6 +299,9 @@ trace(Config) when is_list(Config) -> pipeline(Config) when is_list(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), []}, {ok, _} = httpc:request(get, Request, [], [], pipeline), + + %% Make sure pipeline session is registerd + test_server:sleep(4000), keep_alive_requests(Request, pipeline). %%-------------------------------------------------------------------- @@ -303,6 +309,9 @@ pipeline(Config) when is_list(Config) -> persistent_connection(Config) when is_list(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), []}, {ok, _} = httpc:request(get, Request, [], [], persistent), + + %% Make sure pipeline session is registerd + test_server:sleep(4000), keep_alive_requests(Request, persistent). %%------------------------------------------------------------------------- @@ -379,6 +388,13 @@ stream_once(Config) when is_list(Config) -> Request2 = {url(group_name(Config), "/once_chunked.html", Config), []}, stream_test(Request2, {stream, {self, once}}). +%%------------------------------------------------------------------------- +stream_single_chunk() -> + [{doc, "Test the option stream for asynchrony requests"}]. +stream_single_chunk(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/single_chunk.html", Config), []}, + stream_test(Request, {stream, self}). + %%------------------------------------------------------------------------- redirect_multiple_choises() -> @@ -530,6 +546,19 @@ cookie_profile(Config) when is_list(Config) -> inets:stop(httpc, cookie_test). %%------------------------------------------------------------------------- +empty_set_cookie() -> + [{doc, "Test empty Set-Cookie header."}]. +empty_set_cookie(Config) when is_list(Config) -> + ok = httpc:set_options([{cookies, enabled}]), + + Request0 = {url(group_name(Config), "/empty_set_cookie.html", Config), []}, + + {ok, {{_,200,_}, [_ | _], [_|_]}} + = httpc:request(get, Request0, [], []), + + ok = httpc:set_options([{cookies, disabled}]). + +%%------------------------------------------------------------------------- headers_as_is(doc) -> ["Test the option headers_as_is"]; headers_as_is(Config) when is_list(Config) -> @@ -624,6 +653,12 @@ transfer_encoding(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +transfer_encoding_identity(Config) when is_list(Config) -> + URL = url(group_name(Config), "/identity_transfer_encoding.html", Config), + {ok, {{_,200,_}, [_|_], "IDENTITY"}} = httpc:request(URL). + +%%------------------------------------------------------------------------- + empty_response_header() -> [{doc, "Test the case that the HTTP server does not send any headers. Solves OTP-6830"}]. empty_response_header(Config) when is_list(Config) -> @@ -1020,7 +1055,7 @@ stream_test(Request, To) -> ct:fail(Msg) end, - Body == binary_to_list(StreamedBody). + Body = binary_to_list(StreamedBody). url(http, End, Config) -> Port = ?config(port, Config), @@ -1609,6 +1644,13 @@ handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/identity_transfer_encoding.html",_,_,_,_) -> + "HTTP/1.0 200 OK\r\n" + "Transfer-Encoding:identity\r\n" + "Content-Length:8\r\n" + "\r\n" + "IDENTITY"; + handle_uri(_,"/cookie.html",_,_,_,_) -> "HTTP/1.1 200 ok\r\n" ++ "set-cookie:" ++ "test_cookie=true; path=/;" ++ @@ -1616,6 +1658,12 @@ handle_uri(_,"/cookie.html",_,_,_,_) -> "Content-Length:32\r\n\r\n"++ "<HTML><BODY>foobar</BODY></HTML>"; +handle_uri(_,"/empty_set_cookie.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" ++ + "set-cookie: \r\n" ++ + "Content-Length:32\r\n\r\n"++ + "<HTML><BODY>foobar</BODY></HTML>"; + handle_uri(_,"/missing_crlf.html",_,_,_,_) -> "HTTP/1.1 200 ok" ++ "Content-Length:32\r\n" ++ @@ -1635,6 +1683,14 @@ handle_uri(_,"/once_chunked.html",_,_,Socket,_) -> http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/single_chunk.html",_,_,Socket,_) -> + Chunk = "HTTP/1.1 200 ok\r\n" ++ + "Transfer-Encoding:Chunked\r\n\r\n" ++ + http_chunk:encode("<HTML><BODY>fo") ++ + http_chunk:encode("obar</BODY></HTML>") ++ + http_chunk:encode_last(), + send(Socket, Chunk); + handle_uri(_,"/once.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Content-Length:32\r\n\r\n", diff --git a/lib/inets/test/httpd_1_0.erl b/lib/inets/test/httpd_1_0.erl new file mode 100644 index 0000000000..0836c9e881 --- /dev/null +++ b/lib/inets/test/httpd_1_0.erl @@ -0,0 +1,38 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013-2014. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% + +-module(httpd_1_0). + +-export([host/4, trace/4]). + +%%------------------------------------------------------------------------- +%% Test cases +%%------------------------------------------------------------------------- +host(Type, Port, Host, Node) -> + %% No host needed for HTTP/1.0 + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET / HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]). +trace(Type, Port, Host, Node)-> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "TRACE / HTTP/1.0\r\n\r\n", + [{statuscode, 501}, + {version, "HTTP/1.0"}]). diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl index 07d94ea97a..6a5fc4a18f 100644 --- a/lib/inets/test/httpd_1_1.erl +++ b/lib/inets/test/httpd_1_1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,11 +20,9 @@ -module(httpd_1_1). --include("test_server.hrl"). --include("test_server_line.hrl"). -include_lib("kernel/include/file.hrl"). --export([host/4, chunked/4, expect/4, range/4, if_test/5, http_trace/4, +-export([host/4, chunked/4, expect/4, range/4, if_test/5, trace/4, head/4, mod_cgi_chunked_encoding_test/5]). %% -define(all_keys_lower_case,true). @@ -40,14 +38,10 @@ %%------------------------------------------------------------------------- -%% Test cases starts here. +%% Test cases %%------------------------------------------------------------------------- host(Type, Port, Host, Node) -> - %% No host needed for HTTP/1.0 - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "GET / HTTP/1.0\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/1.0"}]), + %% No host must generate an error ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET / HTTP/1.1\r\n\r\n", @@ -158,13 +152,13 @@ if_test(Type, Port, Host, Node, DocRoot)-> calendar:datetime_to_gregorian_seconds(FileInfo#file_info.mtime), Mod = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( - CreatedSec-1)), + CreatedSec-1)), %% Test that we get the data when the file is modified ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET / HTTP/1.1\r\nHost:" ++ Host ++ - "\r\nIf-Modified-Since:" ++ - Mod ++ "\r\n\r\n", + "\r\nIf-Modified-Since:" ++ + Mod ++ "\r\n\r\n", [{statuscode, 200}]), Mod1 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( CreatedSec+100)), @@ -174,74 +168,69 @@ if_test(Type, Port, Host, Node, DocRoot)-> ++ Mod1 ++"\r\n\r\n", [{statuscode, 304}]), - + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET / HTTP/1.1\r\nHost:" ++ Host ++ - "\r\nIf-Modified-Since:" ++ - "AAA[...]AAAA" ++ "\r\n\r\n", + "\r\nIf-Modified-Since:" ++ + "AAA[...]AAAA" ++ "\r\n\r\n", [{statuscode, 400}]), - - - Mod2 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( + + Mod2 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( CreatedSec+1)), - %% Control that the If-Unmodified-Header lmits the response - ok = httpd_test_lib:verify_request(Type,Host,Port,Node, - "GET / HTTP/1.1\r\nHost:" - ++ Host ++ - "\r\nIf-Unmodified-Since:" ++ Mod2 - ++ "\r\n\r\n", - [{statuscode, 200}]), - Mod3 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( + %% Control that the If-Unmodified-Header lmits the response + ok = httpd_test_lib:verify_request(Type,Host,Port,Node, + "GET / HTTP/1.1\r\nHost:" + ++ Host ++ + "\r\nIf-Unmodified-Since:" ++ Mod2 + ++ "\r\n\r\n", + [{statuscode, 200}]), + Mod3 = httpd_util:rfc1123_date(calendar:gregorian_seconds_to_datetime( CreatedSec-1)), ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "GET / HTTP/1.1\r\nHost:" - ++ Host ++ - "\r\nIf-Unmodified-Since:"++ Mod3 + "GET / HTTP/1.1\r\nHost:" + ++ Host ++ + "\r\nIf-Unmodified-Since:"++ Mod3 ++"\r\n\r\n", - [{statuscode, 412}]), + [{statuscode, 412}]), - %% Control that we get the body when the etag match - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "GET / HTTP/1.1\r\nHost:" ++ Host - ++"\r\n"++ - "If-Match:"++ - httpd_util:create_etag(FileInfo)++ - "\r\n\r\n", - [{statuscode, 200}]), + %% Control that we get the body when the etag match ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "GET / HTTP/1.1\r\nHost:" ++ - Host ++ "\r\n"++ - "If-Match:NotEtag\r\n\r\n", - [{statuscode, 412}]), + "GET / HTTP/1.1\r\nHost:" ++ Host + ++"\r\n"++ + "If-Match:"++ + httpd_util:create_etag(FileInfo)++ + "\r\n\r\n", + [{statuscode, 200}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET / HTTP/1.1\r\nHost:" ++ + Host ++ "\r\n"++ + "If-Match:NotEtag\r\n\r\n", + [{statuscode, 412}]), - %% Control the response when the if-none-match header is there - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "GET / HTTP/1.1\r\nHost:" - ++ Host ++"\r\n"++ - "If-None-Match:NoTaag," ++ - httpd_util:create_etag(FileInfo) ++ - "\r\n\r\n", - [{statuscode, 304}]), + %% Control the response when the if-none-match header is there + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET / HTTP/1.1\r\nHost:" + ++ Host ++"\r\n"++ + "If-None-Match:NoTaag," ++ + httpd_util:create_etag(FileInfo) ++ + "\r\n\r\n", + [{statuscode, 304}]), ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "GET / HTTP/1.1\r\nHost:" - ++ Host ++ "\r\n"++ - "If-None-Match:NotEtag," - "NeihterEtag\r\n\r\n", + ++ Host ++ "\r\n"++ + "If-None-Match:NotEtag," + "NeihterEtag\r\n\r\n", [{statuscode,200}]), ok. - -http_trace(Type, Port, Host, Node)-> + +trace(Type, Port, Host, Node)-> ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "TRACE / HTTP/1.1\r\n" ++ "Host:" ++ Host ++ "\r\n" ++ "Max-Forwards:2\r\n\r\n", - [{statuscode, 200}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "TRACE / HTTP/1.0\r\n\r\n", - [{statuscode, 501}, - {version, "HTTP/1.0"}]). + [{statuscode, 200}]). head(Type, Port, Host, Node)-> %% mod_include ok = httpd_test_lib:verify_request(Type, Host, Port, Node, @@ -289,7 +278,7 @@ mod_cgi_chunked_encoding_test(Type, Port, Host, Node, [Request| Rest])-> %%-------------------------------------------------------------------- validateRangeRequest(Socket,Response,ValidBody,C,O,DE)-> receive - {tcp,Socket,Data} -> + {_,Socket,Data} -> case string:str(Data,"\r\n") of 0-> validateRangeRequest(Socket, @@ -318,7 +307,7 @@ validateRangeRequest1(Socket, Response, ValidBody) -> case end_of_header(Response) of false -> receive - {tcp,Socket,Data} -> + {_,Socket,Data} -> validateRangeRequest1(Socket, Response ++ Data, ValidBody); _-> @@ -337,10 +326,10 @@ validateRangeRequest2(Socket, Head, Body, ValidBody, {multiPart,Boundary})-> validateMultiPartRangeRequest(Body, ValidBody, Boundary); false-> receive - {tcp, Socket, Data} -> + {_, Socket, Data} -> validateRangeRequest2(Socket, Head, Body ++ Data, ValidBody, {multiPart, Boundary}); - {tcp_closed, Socket} -> + {_, Socket} -> error; _ -> error @@ -359,7 +348,7 @@ validateRangeRequest2(Socket, Head, Body, ValidBody, BodySize) end; Size when Size < BodySize -> receive - {tcp, Socket, Data} -> + {_, Socket, Data} -> validateRangeRequest2(Socket, Head, Body ++ Data, ValidBody, BodySize); _ -> diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index ef801f91c7..4be20d3a69 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -1,2238 +1,1515 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2013-2014. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% +%% +%% ct:run("../inets_test", httpd_SUITE). +%% + -module(httpd_SUITE). --include_lib("test_server/include/test_server.hrl"). --include("test_server_line.hrl"). +-include_lib("kernel/include/file.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("public_key/include/public_key.hrl"). -include("inets_test_lib.hrl"). --include_lib("kernel/include/file.hrl"). +%% Note: This directive should only be used in test suites. +-compile(export_all). -%% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). --export([init_per_testcase/2, end_per_testcase/2, - init_per_suite/1, end_per_suite/1]). - -%% Core Server tests --export([ - ip_mod_alias/1, - ip_mod_actions/1, - ip_mod_security/1, - ip_mod_auth/1, - ip_mod_auth_api/1, - ip_mod_auth_mnesia_api/1, - ip_mod_htaccess/1, - ip_mod_cgi/1, - ip_mod_esi/1, - ip_mod_get/1, - ip_mod_head/1, - ip_mod_all/1, - ip_load_light/1, - ip_load_medium/1, - ip_load_heavy/1, - ip_dos_hostname/1, - ip_time_test/1, - ip_block_disturbing_idle/1, - ip_block_non_disturbing_idle/1, - ip_block_503/1, - ip_block_disturbing_active/1, - ip_block_non_disturbing_active/1, - ip_block_disturbing_active_timeout_not_released/1, - ip_block_disturbing_active_timeout_released/1, - ip_block_non_disturbing_active_timeout_not_released/1, - ip_block_non_disturbing_active_timeout_released/1, - ip_block_disturbing_blocker_dies/1, - ip_block_non_disturbing_blocker_dies/1, - ip_restart_no_block/1, - ip_restart_disturbing_block/1, - ip_restart_non_disturbing_block/1 - ]). - --export([ - essl_mod_alias/1, - essl_mod_actions/1, - essl_mod_security/1, - essl_mod_auth/1, - essl_mod_auth_api/1, - essl_mod_auth_mnesia_api/1, - essl_mod_htaccess/1, - essl_mod_cgi/1, - essl_mod_esi/1, - essl_mod_get/1, - essl_mod_head/1, - essl_mod_all/1, - essl_load_light/1, - essl_load_medium/1, - essl_load_heavy/1, - essl_dos_hostname/1, - essl_time_test/1, - essl_restart_no_block/1, - essl_restart_disturbing_block/1, - essl_restart_non_disturbing_block/1, - essl_block_disturbing_idle/1, - essl_block_non_disturbing_idle/1, - essl_block_503/1, - essl_block_disturbing_active/1, - essl_block_non_disturbing_active/1, - essl_block_disturbing_active_timeout_not_released/1, - essl_block_disturbing_active_timeout_released/1, - essl_block_non_disturbing_active_timeout_not_released/1, - essl_block_non_disturbing_active_timeout_released/1, - essl_block_disturbing_blocker_dies/1, - essl_block_non_disturbing_blocker_dies/1 - ]). - -%%% HTTP 1.1 tests --export([ip_host/1, ip_chunked/1, ip_expect/1, ip_range/1, - ip_if_test/1, ip_http_trace/1, ip_http1_1_head/1, - ip_mod_cgi_chunked_encoding_test/1]). - -%%% HTTP 1.0 tests --export([ip_head_1_0/1, ip_get_1_0/1, ip_post_1_0/1]). - -%%% HTTP 0.9 tests --export([ip_get_0_9/1]). - -%%% Ticket tests --export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1, - ticket_7304/1]). - -%%% IPv6 tests --export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1, - ipv6_address_ipcomm/0, ipv6_address_ipcomm/1, - ipv6_hostname_essl/0, ipv6_hostname_essl/1, - ipv6_address_essl/0, ipv6_address_essl/1]). - -%% Help functions --export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]). - --define(IP_PORT, 8898). --define(SSL_PORT, 8899). +-record(httpd_user, {user_name, password, user_data}). +-record(httpd_group, {group_name, userlist}). -define(MAX_HEADER_SIZE, 256). --define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1"). - %% Minutes before failed auths timeout. -define(FAIL_EXPIRE_TIME,1). - %% Seconds before successful auths timeout. -define(AUTH_TIMEOUT,5). --record(httpd_user, {user_name, password, user_data}). --record(httpd_group, {group_name, userlist}). - - %%-------------------------------------------------------------------- -%% all(Arg) -> [Doc] | [Case] | {skip, Comment} -%% Arg - doc | suite -%% Doc - string() -%% Case - atom() -%% Name of a test case function. -%% Comment - string() -%% Description: Returns documentation/test cases in this test suite -%% or a skip tuple if the platform is not supported. +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [ - {group, ip}, - {group, ssl}, - {group, http_1_1_ip}, - {group, http_1_0_ip}, - {group, http_0_9_ip}, - {group, ipv6}, - {group, tickets} + {group, http_basic}, + {group, https_basic}, + {group, http_limit}, + {group, https_limit}, + {group, http_basic_auth}, + {group, https_basic_auth}, + {group, http_auth_api}, + {group, https_auth_api}, + {group, http_auth_api_dets}, + {group, https_auth_api_dets}, + {group, http_auth_api_mnesia}, + {group, https_auth_api_mnesia}, + {group, http_htaccess}, + {group, https_htaccess}, + {group, http_security}, + {group, https_security} ]. -groups() -> +groups() -> [ - {ip, [], - [ip_mod_alias, ip_mod_actions, ip_mod_security, - ip_mod_auth, ip_mod_auth_api, ip_mod_auth_mnesia_api, - ip_mod_htaccess, ip_mod_cgi, ip_mod_esi, ip_mod_get, - ip_mod_head, ip_mod_all, ip_load_light, ip_load_medium, - ip_load_heavy, ip_dos_hostname, ip_time_test, - ip_restart_no_block, ip_restart_disturbing_block, - ip_restart_non_disturbing_block, - ip_block_disturbing_idle, ip_block_non_disturbing_idle, - ip_block_503, ip_block_disturbing_active, - ip_block_non_disturbing_active, - ip_block_disturbing_active_timeout_not_released, - ip_block_disturbing_active_timeout_released, - ip_block_non_disturbing_active_timeout_not_released, - ip_block_non_disturbing_active_timeout_released, - ip_block_disturbing_blocker_dies, - ip_block_non_disturbing_blocker_dies]}, - {ssl, [], [{group, essl}]}, - {essl, [], - [essl_mod_alias, essl_mod_actions, essl_mod_security, - essl_mod_auth, essl_mod_auth_api, - essl_mod_auth_mnesia_api, essl_mod_htaccess, - essl_mod_cgi, essl_mod_esi, essl_mod_get, essl_mod_head, - essl_mod_all, essl_load_light, essl_load_medium, - essl_load_heavy, essl_dos_hostname, essl_time_test, - essl_restart_no_block, essl_restart_disturbing_block, - essl_restart_non_disturbing_block, - essl_block_disturbing_idle, - essl_block_non_disturbing_idle, essl_block_503, - essl_block_disturbing_active, - essl_block_non_disturbing_active, - essl_block_disturbing_active_timeout_not_released, - essl_block_disturbing_active_timeout_released, - essl_block_non_disturbing_active_timeout_not_released, - essl_block_non_disturbing_active_timeout_released, - essl_block_disturbing_blocker_dies, - essl_block_non_disturbing_blocker_dies]}, - {http_1_1_ip, [], - [ip_host, ip_chunked, ip_expect, ip_range, ip_if_test, - ip_http_trace, ip_http1_1_head, - ip_mod_cgi_chunked_encoding_test]}, - {http_1_0_ip, [], - [ip_head_1_0, ip_get_1_0, ip_post_1_0]}, - {http_0_9_ip, [], [ip_get_0_9]}, - {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm, - ipv6_hostname_essl, ipv6_address_essl]}, - {tickets, [], - [ticket_5775, ticket_5865, ticket_5913, ticket_6003, - ticket_7304]}]. - - -init_per_group(ipv6 = _GroupName, Config) -> - case inets_test_lib:has_ipv6_support() of - {ok, _} -> - Config; - _ -> - {skip, "Host does not support IPv6"} - end; -init_per_group(essl, Config) -> - catch crypto:stop(), - case (catch crypto:start()) of - ok -> - Config; - _ -> - {skip, "Crypto not startable"} - end; - -init_per_group(_GroupName, Config) -> - Config. + {http_basic, [], basic_groups()}, + {https_basic, [], basic_groups()}, + {http_limit, [], [{group, limit}]}, + {https_limit, [], [{group, limit}]}, + {http_basic_auth, [], [{group, basic_auth}]}, + {https_basic_auth, [], [{group, basic_auth}]}, + {http_auth_api, [], [{group, auth_api}]}, + {https_auth_api, [], [{group, auth_api}]}, + {http_auth_api_dets, [], [{group, auth_api_dets}]}, + {https_auth_api_dets, [], [{group, auth_api_dets}]}, + {http_auth_api_mnesia, [], [{group, auth_api_mnesia}]}, + {https_auth_api_mnesia, [], [{group, auth_api_mnesia}]}, + {http_htaccess, [], [{group, htaccess}]}, + {https_htaccess, [], [{group, htaccess}]}, + {http_security, [], [{group, security}]}, + {https_security, [], [{group, security}]}, + {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, + {basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]}, + {auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 + ]}, + {auth_api_dets, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 + ]}, + {auth_api_mnesia, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 + ]}, + {htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]}, + {security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code + {http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test, + trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()}, + {http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()}, + {http_0_9, [], http_head() ++ http_get() ++ load()} + ]. -end_per_group(_GroupName, Config) -> - Config. +basic_groups ()-> + [{group, http_1_1}, + {group, http_1_0}, + {group, http_0_9} + ]. +http_head() -> + [head]. +http_get() -> + [alias, + get, + %%actions, Add configuration so that this test mod_action + esi, + ssi, + content_length, + bad_hex, + missing_CR, + max_header, + ipv6 + ]. -%%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%%-------------------------------------------------------------------- +load() -> + [light, medium + %%,heavy + ]. + init_per_suite(Config) -> - io:format(user, "init_per_suite -> entry with" - "~n Config: ~p" - "~n", [Config]), - - ?PRINT_SYSTEM_INFO([]), - PrivDir = ?config(priv_dir, Config), - SuiteTopDir = filename:join(PrivDir, ?MODULE), - case file:make_dir(SuiteTopDir) of - ok -> - ok; - {error, eexist} -> - ok; - Error -> - throw({error, {failed_creating_suite_top_dir, Error}}) - end, - - [{has_ipv6_support, inets_test_lib:has_ipv6_support()}, - {suite_top_dir, SuiteTopDir}, + DataDir = ?config(data_dir, Config), + inets_test_lib:stop_apps([inets]), + ServerRoot = filename:join(PrivDir, "server_root"), + inets_test_lib:del_dirs(ServerRoot), + DocRoot = filename:join(ServerRoot, "htdocs"), + setup_server_dirs(ServerRoot, DocRoot, DataDir), + [{server_root, ServerRoot}, + {doc_root, DocRoot}, {node, node()}, - {host, inets_test_lib:hostname()}, + {host, inets_test_lib:hostname()}, {address, getaddr()} | Config]. +end_per_suite(_Config) -> + ok. %%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- +init_per_group(Group, Config0) when Group == https_basic; + Group == https_limit; + Group == https_basic_auth; + Group == https_auth_api; + Group == https_auth_api_dets; + Group == https_auth_api_mnesia; + Group == https_security + -> + init_ssl(Group, Config0); +init_per_group(Group, Config0) when Group == http_basic; + Group == http_limit; + Group == http_basic_auth; + Group == http_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == http_security + -> + ok = start_apps(Group), + init_httpd(Group, [{type, ip_comm} | Config0]); +init_per_group(http_1_1, Config) -> + [{http_version, "HTTP/1.1"} | Config]; +init_per_group(http_1_0, Config) -> + [{http_version, "HTTP/1.0"} | Config]; +init_per_group(http_0_9, Config) -> + case {os:type(), os:version()} of + {{win32, _}, {5,1,2600}} -> + {skip, "eaddrinuse XP problem"}; + _ -> + [{http_version, "HTTP/0.9"} | Config] + end; +init_per_group(http_htaccess = Group, Config) -> + Path = ?config(doc_root, Config), + catch remove_htaccess(Path), + create_htaccess_data(Path, ?config(address, Config)), + ok = start_apps(Group), + init_httpd(Group, [{type, ip_comm} | Config]); +init_per_group(https_htaccess = Group, Config) -> + Path = ?config(doc_root, Config), + catch remove_htaccess(Path), + create_htaccess_data(Path, ?config(address, Config)), + init_ssl(Group, Config); +init_per_group(auth_api, Config) -> + [{auth_prefix, ""} | Config]; +init_per_group(auth_api_dets, Config) -> + [{auth_prefix, "dets_"} | Config]; +init_per_group(auth_api_mnesia, Config) -> + start_mnesia(?config(node, Config)), + [{auth_prefix, "mnesia_"} | Config]; +init_per_group(_, Config) -> + Config. -end_per_suite(_Config) -> - %% SuiteTopDir = ?config(suite_top_dir, Config), - %% inets_test_lib:del_dirs(SuiteTopDir), +end_per_group(Group, _Config) when Group == http_basic; + Group == http_limit; + Group == http_basic_auth; + Group == http_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == http_htaccess; + Group == http_security + -> + inets:stop(); +end_per_group(Group, _Config) when Group == https_basic; + Group == https_limit; + Group == https_basic_auth; + Group == https_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == https_htaccess; + Group == http_security + -> + ssl:stop(), + inets:stop(); + +end_per_group(auth_api_mnesia, _) -> + cleanup_mnesia(); + +end_per_group(_, _) -> ok. - -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(Case, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- -init_per_testcase(Case, Config) -> - NewConfig = init_per_testcase2(Case, Config), - init_per_testcase3(Case, NewConfig). - +init_per_testcase(Case, Config) when Case == host; Case == trace -> + Prop = ?config(tc_group_properties, Config), + Name = proplists:get_value(name, Prop), + Cb = case Name of + http_1_0 -> + httpd_1_0; + http_1_1 -> + httpd_1_1 + end, + [{version_cb, Cb} | proplists:delete(version_cb, Config)]; + +init_per_testcase(range, Config) -> + DocRoot = ?config(doc_root, Config), + create_range_data(DocRoot), + Config; + +init_per_testcase(_, Config) -> + Config. -init_per_testcase2(Case, Config) -> +end_per_testcase(_Case, _Config) -> + ok. - %% tsp("init_per_testcase2 -> entry with" - %% "~n Config: ~p", [Config]), - - IpNormal = integer_to_list(?IP_PORT) ++ ".conf", - IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf", - SslNormal = integer_to_list(?SSL_PORT) ++ ".conf", - SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf", +%%------------------------------------------------------------------------- +%% Test cases starts here. +%%------------------------------------------------------------------------- - DataDir = ?config(data_dir, Config), - SuiteTopDir = ?config(suite_top_dir, Config), +head() -> + [{doc, "HTTP HEAD request for static page"}]. - %% tsp("init_per_testcase2 -> " - %% "~n SuiteDir: ~p" - %% "~n DataDir: ~p", [SuiteTopDir, DataDir]), - - TcTopDir = filename:join(SuiteTopDir, Case), - ?line ok = file:make_dir(TcTopDir), +head(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), ?config(node, Config), + http_request("HEAD /index.html ", Version, Host), + [{statuscode, head_status(Version)}, + {version, Version}]). - %% tsp("init_per_testcase2 -> " - %% "~n TcTopDir: ~p", [TcTopDir]), +get() -> + [{doc, "HTTP GET request for static page"}]. - DataSrc = filename:join([DataDir, "server_root"]), - ServerRoot = filename:join([TcTopDir, "server_root"]), - - %% tsp("init_per_testcase2 -> " - %% "~n DataSrc: ~p" - %% "~n ServerRoot: ~p", [DataSrc, ServerRoot]), +get(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request("GET /index.html ", Version, Host), + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]). - ok = file:make_dir(ServerRoot), - ok = file:make_dir(filename:join([TcTopDir, "logs"])), +basic_auth_1_1(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/1.1"} | Config]). - NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config], +basic_auth_1_0(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/1.0"} | Config]). - %% tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"), +basic_auth_0_9(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/0.9"} | Config]). - inets_test_lib:copy_dirs(DataSrc, ServerRoot), +basic_auth() -> + [{doc, "Test Basic authentication with WWW-Authenticate header"}]. - %% tsp("init_per_testcase2 -> fix cgi"), - EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]), - {ok, FileInfo} = file:read_file_info(EnvCGI), - ok = file:write_file_info(EnvCGI, - FileInfo#file_info{mode = 8#00755}), - - EchoCGI = case test_server:os_type() of - {win32, _} -> - "cgi_echo.exe"; - _ -> - "cgi_echo" - end, - CGIDir = filename:join([ServerRoot, "cgi-bin"]), - inets_test_lib:copy_file(EchoCGI, DataDir, CGIDir), - NewEchoCGI = filename:join([CGIDir, EchoCGI]), - {ok, FileInfo1} = file:read_file_info(NewEchoCGI), - ok = file:write_file_info(NewEchoCGI, - FileInfo1#file_info{mode = 8#00755}), +basic_auth(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + basic_auth_requiered(Config), + %% Authentication OK! ["one:OnePassword" user first in user list] + ok = auth_status(auth_request("/open/dummy.html", "one", "onePassword", Version, Host), Config, + [{statuscode, 200}]), + %% Authentication OK and a directory listing is supplied! + %% ["Aladdin:open sesame" user second in user list] + ok = auth_status(auth_request("/open/", "Aladdin", "AladdinPassword", Version, Host), Config, + [{statuscode, 200}]), + %% User correct but wrong password! ["one:one" user first in user list] + ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config, + [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + %% Make sure Authenticate header is received even the second time + %% we try a incorrect password! Otherwise a browser client will hang! + ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config, + [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + %% Neither user or password correct! ["dummy:dummy"] + ok = auth_status(auth_request("/open/dummy.html", "dummy", "dummy", Version, Host), Config, + [{statuscode, 401}]), + %% Nested secret/top_secret OK! ["Aladdin:open sesame"] + ok = http_status(auth_request("/secret/top_secret/", "Aladdin", "AladdinPassword", Version, Host), + Config, [{statuscode, 200}]), + %% Authentication still required! + basic_auth_requiered(Config). + +auth_api_1_1(Config) when is_list(Config) -> + auth_api([{http_version, "HTTP/1.1"} | Config]). + +auth_api_1_0(Config) when is_list(Config) -> + auth_api([{http_version, "HTTP/1.0"} | Config]). + +auth_api_0_9(Config) when is_list(Config) -> + auth_api([{http_version, "HTTP/0.9"} | Config]). + +auth_api() -> + [{doc, "Test mod_auth API"}]. + +auth_api(Config) when is_list(Config) -> + Prefix = ?config(auth_prefix, Config), + do_auth_api(Prefix, Config). + +do_auth_api(AuthPrefix, Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Node = ?config(node, Config), + ServerRoot = ?config(server_root, Config), + ok = http_status("GET / ", Config, + [{statuscode, 200}]), + ok = auth_status(auth_request("/", "one", "WrongPassword", Version, Host), Config, + [{statuscode, 200}]), + + %% Make sure Authenticate header is received even the second time + %% we try a incorrect password! Otherwise a browser client will hang! + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "dummy", "WrongPassword", Version, Host), Config, + [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", "dummy", "WrongPassword", + Version, Host), Config, [{statuscode, 401}, + {header, "WWW-Authenticate"}]), - %% To be used by IP test cases - %% tsp("init_per_testcase2 -> ip testcase setups"), - create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig], - normal_access, IpNormal), - create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig], - mod_htaccess, IpHtaccess), - - %% To be used by SSL test cases - %% tsp("init_per_testcase2 -> ssl testcase setups"), - SocketType = - case atom_to_list(Case) of - [X, $s, $s, $l | _] -> - case X of - $p -> ssl; - $e -> essl - end; - _ -> - ssl - end, - - create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig], - normal_access, SslNormal), - create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig], - mod_htaccess, SslHtaccess), + %% Change the password to DummyPassword then try to add a user + %% Get an error and set it to NoPassword + ok = update_password(Node, ServerRoot, Host, Port, AuthPrefix, + "open", "NoPassword", "DummyPassword"), + {error,bad_password} = + add_user(Node, ServerRoot, Port, AuthPrefix, "open", "one", + "onePassword", []), + ok = update_password(Node, ServerRoot, Host, Port, AuthPrefix, "open", + "DummyPassword", "NoPassword"), - %% To be used by IPv6 test cases. Case-clause is so that - %% you can do ts:run(inets, httpd_SUITE, <test case>) - %% for all cases except the ipv6 cases as they depend - %% on 'test_host_ipv6_only' that will only be present - %% when you run the whole test suite due to shortcomings - %% of the test server. - - tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"), - NewConfig2 = - case atom_to_list(Case) of - "ipv6_" ++ _ -> - case (catch inets_test_lib:has_ipv6_support(NewConfig)) of - {ok, IPv6Address0} -> - {ok, Hostname} = inet:gethostname(), - IPv6Address = http_transport:ipv6_name(IPv6Address0), - create_ipv6_config([{port, ?IP_PORT}, - {sock_type, ip_comm}, - {ipv6_host, IPv6Address} | - NewConfig], - "ipv6_hostname_ipcomm.conf", - Hostname), - create_ipv6_config([{port, ?IP_PORT}, - {sock_type, ip_comm}, - {ipv6_host, IPv6Address} | - NewConfig], - "ipv6_address_ipcomm.conf", - IPv6Address), - create_ipv6_config([{port, ?SSL_PORT}, - {sock_type, essl}, - {ipv6_host, IPv6Address} | - NewConfig], - "ipv6_hostname_essl.conf", - Hostname), - create_ipv6_config([{port, ?SSL_PORT}, - {sock_type, essl}, - {ipv6_host, IPv6Address} | - NewConfig], - "ipv6_address_essl.conf", - IPv6Address), - [{ipv6_host, IPv6Address} | NewConfig]; - _ -> - NewConfig - end; - - _ -> - NewConfig - end, - - %% tsp("init_per_testcase2 -> done when" - %% "~n NewConfig2: ~p", [NewConfig2]), - - NewConfig2. - - -init_per_testcase3(Case, Config) -> - tsp("init_per_testcase3(~w) -> entry with" - "~n Config: ~p", [Case, Config]), - - -%% %% Create a new fresh node to be used by the server in this test-case + %% Test /*open, require user one Aladdin + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "open"), -%% NodeName = list_to_atom(atom_to_list(Case) ++ "_httpd"), -%% Node = inets_test_lib:start_node(NodeName), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "one", "onePassword", Version, Host), Config, + [{statuscode, 401}]), - %% Clean up (we do not want this clean up in end_per_testcase - %% if init_per_testcase crashes for some testcase it will - %% have contaminated the environment and there will be no clean up.) - %% This init can take a few different paths so that one crashes - %% does not mean that all invocations will. - - application:unset_env(inets, services), - application:stop(inets), - application:stop(ssl), - cleanup_mnesia(), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "two", "twoPassword", Version, Host), Config, + [{statuscode, 401}]), - %% Start initialization - tsp("init_per_testcase3(~w) -> start init", [Case]), - - Dog = test_server:timetrap(inets_test_lib:minutes(10)), - NewConfig = lists:keydelete(watchdog, 1, Config), - TcTopDir = ?config(tc_top_dir, Config), - - CaseRest = - case atom_to_list(Case) of - "ip_mod_htaccess" -> - inets_test_lib:start_http_server( - filename:join(TcTopDir, - integer_to_list(?IP_PORT) ++ - "htaccess.conf")), - "mod_htaccess"; - "ip_" ++ Rest -> - inets_test_lib:start_http_server( - filename:join(TcTopDir, - integer_to_list(?IP_PORT) ++ ".conf")), - Rest; - "ticket_5913" -> - HttpdOptions = - [{file, - filename:join(TcTopDir, - integer_to_list(?IP_PORT) ++ ".conf")}, - {accept_timeout,30000}, - {debug,[{exported_functions, - [httpd_manager,httpd_request_handler]}]}], - inets_test_lib:start_http_server(HttpdOptions); - "ticket_"++Rest -> - %% OTP-5913 use the new syntax of inets.config - inets_test_lib:start_http_server([{file, - filename:join(TcTopDir, - integer_to_list(?IP_PORT) ++ ".conf")}]), - Rest; - - [X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] -> - ?ENSURE_STARTED([crypto, public_key, ssl]), - SslTag = - case X of - $p -> ssl; % Plain - $e -> essl % Erlang based ssl - end, - case inets_test_lib:start_http_server_ssl( - filename:join(TcTopDir, - integer_to_list(?SSL_PORT) ++ - "htaccess.conf"), SslTag) of - ok -> - "mod_htaccess"; - Other -> - error_logger:info_msg("Other: ~p~n", [Other]), - {skip, "SSL does not seem to be supported"} - end; - [X, $s, $s, $l, $_ | Rest] -> - ?ENSURE_STARTED([crypto, public_key, ssl]), - SslTag = - case X of - $p -> ssl; - $e -> essl - end, - case inets_test_lib:start_http_server_ssl( - filename:join(TcTopDir, - integer_to_list(?SSL_PORT) ++ - ".conf"), SslTag) of - ok -> - Rest; - Other -> - error_logger:info_msg("Other: ~p~n", [Other]), - {skip, "SSL does not seem to be supported"} - end; - "ipv6_" ++ _ = TestCaseStr -> - case inets_test_lib:has_ipv6_support() of - {ok, _} -> - inets_test_lib:start_http_server( - filename:join(TcTopDir, - TestCaseStr ++ ".conf")); - - _ -> - {skip, "Host does not support IPv6"} - end - end, - - InitRes = - case CaseRest of - {skip, _} = Skip -> - Skip; - "mod_auth_" ++ _ -> - start_mnesia(?config(node, Config)), - [{watchdog, Dog} | NewConfig]; - "mod_htaccess" -> - ServerRoot = ?config(server_root, Config), - Path = filename:join([ServerRoot, "htdocs"]), - catch remove_htaccess(Path), - create_htaccess_data(Path, ?config(address, Config)), - [{watchdog, Dog} | NewConfig]; - "range" -> - ServerRoot = ?config(server_root, Config), - Path = filename:join([ServerRoot, "htdocs"]), - create_range_data(Path), - [{watchdog, Dog} | NewConfig]; - _ -> - [{watchdog, Dog} | NewConfig] - end, + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "Aladdin", "onePassword", Version, Host), + Config, [{statuscode, 401}]), - tsp("init_per_testcase3(~w) -> done when" - "~n InitRes: ~p", [Case, InitRes]), - - InitRes. - - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(Case, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- -end_per_testcase(Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), - end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)), - ok. - -end_per_testcase2(Case, Config) -> - tsp("end_per_testcase2(~w) -> entry with" - "~n Config: ~p", [Case, Config]), - application:unset_env(inets, services), - application:stop(inets), - application:stop(ssl), - application:stop(crypto), % used by the new ssl (essl test cases) - cleanup_mnesia(), - tsp("end_per_testcase2(~w) -> done", [Case]), - ok. - - -%%------------------------------------------------------------------------- -%% Test cases starts here. -%%------------------------------------------------------------------------- - + true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "one", + "onePassword", []), + true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "two", + "twoPassword", []), + true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "Aladdin", + "AladdinPassword", []), + {ok, [_|_]} = list_users(Node, ServerRoot, Host, Port, + AuthPrefix, "open"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "one", "WrongPassword", Version, Host), + Config, [{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "one", "onePassword", Version, Host), + Config, [{statuscode, 200}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "two", "twoPassword", Version, Host), + Config,[{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "Aladdin", "WrongPassword", Version, Host), + Config,[{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "Aladdin", "AladdinPassword", Version, Host), + Config, [{statuscode, 200}]), + + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "open"), + {ok, []} = list_users(Node, ServerRoot, Host, Port, + AuthPrefix, "open"), + + %% Phase 2 + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), + {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthPrefix, + "secret"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "one", "onePassword", Version, Host), + Config, [{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "two", "twoPassword", Version, Host), + Config, [{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "three", "threePassword", Version, Host), + Config, [{statuscode, 401}]), + add_user(Node, ServerRoot, Port, AuthPrefix, "secret", "one", + "onePassword", + []), + add_user(Node, ServerRoot, Port, AuthPrefix, "secret", + "two", "twoPassword", []), + add_user(Node, ServerRoot, Port, AuthPrefix, "secret", "Aladdin", + "AladdinPassword",[]), + add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret", + "one", "group1"), + add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret", + "two", "group1"), + add_group_member(Node, ServerRoot, Port, AuthPrefix, + "secret", "Aladdin", "group2"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "one", "onePassword", Version, Host), + Config, [{statuscode, 200}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "two", "twoPassword", Version, Host), + Config,[{statuscode, 200}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "Aladdin", "AladdinPassword", Version, Host), + Config, [{statuscode, 200}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", + "three", "threePassword", Version, Host), + Config, [{statuscode, 401}]), + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), + {ok, []} = list_users(Node, ServerRoot, Host, Port, + AuthPrefix, "secret"), + remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), + + {ok, []} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), + + %% Phase 3 + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), + remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), + + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", + "three", "threePassword", Version, Host), + Config, [{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", "two", "twoPassword", Version, Host), + Config, [{statuscode, 401}]), + add_user(Node, ServerRoot, Port, AuthPrefix, + "secret/top_secret","three", + "threePassword",[]), + add_user(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", + "two","twoPassword", []), + add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", "three", "group3"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", "three", "threePassword", + Version, Host), + Config, [{statuscode, 200}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", "two", "twoPassword", Version, Host), + Config, [{statuscode, 401}]), + add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", "two", "group3"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", + "two", "twoPassword", Version, Host), + Config, [{statuscode, 200}]), + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), + {ok, []} = list_users(Node, ServerRoot, Host, Port, + AuthPrefix, "secret/top_secret"), + remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), + {ok, []} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/", "two", "twoPassword", Version, Host), + Config, [{statuscode, 401}]), + ok = auth_status(auth_request("/" ++ AuthPrefix ++ + "secret/top_secret/","three", "threePassword", Version, Host), + Config, [{statuscde, 401}]). +%%------------------------------------------------------------------------- +ipv6() -> + [{require, ipv6_hosts}, + {doc,"Test ipv6."}]. +ipv6(Config) when is_list(Config) -> + {ok, Hostname0} = inet:gethostname(), + case lists:member(list_to_atom(Hostname0), ct:get_config(ipv6_hosts)) of + true -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + URI = http_request("GET /", Version, Host), + httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), [inet6], + ?config(code, Config), + URI, + [{statuscode, 200}, {version, Version}]); + false -> + {skip, "Host does not support IPv6"} + end. + +%%------------------------------------------------------------------------- +ssi() -> + [{doc, "HTTP GET server side include test"}]. +ssi(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request("GET /fsize.shtml ", Version, Host), + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]). %%------------------------------------------------------------------------- -ip_mod_alias(doc) -> - ["Module test: mod_alias"]; -ip_mod_alias(suite) -> - []; -ip_mod_alias(Config) when is_list(Config) -> - httpd_mod:alias(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. +htaccess_1_1(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/1.1"} | Config]). -%%------------------------------------------------------------------------- -ip_mod_actions(doc) -> - ["Module test: mod_actions"]; -ip_mod_actions(suite) -> - []; -ip_mod_actions(Config) when is_list(Config) -> - httpd_mod:actions(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. +htaccess_1_0(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/1.0"} | Config]). -%%------------------------------------------------------------------------- -ip_mod_security(doc) -> - ["Module test: mod_security"]; -ip_mod_security(suite) -> - []; -ip_mod_security(Config) when is_list(Config) -> - ServerRoot = ?config(server_root, Config), - httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. +htaccess_0_9(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/0.9"} | Config]). -%%------------------------------------------------------------------------- -ip_mod_auth(doc) -> - ["Module test: mod_auth"]; -ip_mod_auth(suite) -> - []; -ip_mod_auth(Config) when is_list(Config) -> - httpd_mod:auth(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. +htaccess() -> + [{doc, "Test mod_auth API"}]. -%%------------------------------------------------------------------------- -ip_mod_auth_api(doc) -> - ["Module test: mod_auth_api"]; -ip_mod_auth_api(suite) -> - []; -ip_mod_auth_api(Config) when is_list(Config) -> - ServerRoot = ?config(server_root, Config), - Host = ?config(host, Config), +htaccess(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + Port = ?config(port, Config), Node = ?config(node, Config), - httpd_mod:auth_api(ServerRoot, "", ip_comm, ?IP_PORT, Host, Node), - httpd_mod:auth_api(ServerRoot, "dets_", ip_comm, ?IP_PORT, Host, Node), - httpd_mod:auth_api(ServerRoot, "mnesia_", ip_comm, ?IP_PORT, Host, Node), - ok. -%%------------------------------------------------------------------------- -ip_mod_auth_mnesia_api(doc) -> - ["Module test: mod_auth_mnesia_api"]; -ip_mod_auth_mnesia_api(suite) -> - []; -ip_mod_auth_mnesia_api(Config) when is_list(Config) -> - httpd_mod:auth_mnesia_api(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_mod_htaccess(doc) -> - ["Module test: mod_htaccess"]; -ip_mod_htaccess(suite) -> - []; -ip_mod_htaccess(Config) when is_list(Config) -> - httpd_mod:htaccess(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_mod_cgi(doc) -> - ["Module test: mod_cgi"]; -ip_mod_cgi(suite) -> - []; -ip_mod_cgi(Config) when is_list(Config) -> - httpd_mod:cgi(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_mod_esi(doc) -> - ["Module test: mod_esi"]; -ip_mod_esi(suite) -> - []; -ip_mod_esi(Config) when is_list(Config) -> - httpd_mod:esi(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. - -%%------------------------------------------------------------------------- -ip_mod_get(doc) -> - ["Module test: mod_get"]; -ip_mod_get(suite) -> - []; -ip_mod_get(Config) when is_list(Config) -> - httpd_mod:get(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. - -%%------------------------------------------------------------------------- -ip_mod_head(doc) -> - ["Module test: mod_head"]; -ip_mod_head(suite) -> - []; -ip_mod_head(Config) when is_list(Config) -> - httpd_mod:head(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_mod_all(doc) -> - ["All modules test"]; -ip_mod_all(suite) -> - []; -ip_mod_all(Config) when is_list(Config) -> - httpd_mod:all(ip_comm, ?IP_PORT, - ?config(host, Config), ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_load_light(doc) -> - ["Test light load"]; -ip_load_light(suite) -> - []; -ip_load_light(Config) when is_list(Config) -> - httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config), - get_nof_clients(ip_comm, light)), - ok. -%%------------------------------------------------------------------------- -ip_load_medium(doc) -> - ["Test medium load"]; -ip_load_medium(suite) -> - []; -ip_load_medium(Config) when is_list(Config) -> - httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config), - get_nof_clients(ip_comm, medium)), - ok. -%%------------------------------------------------------------------------- -ip_load_heavy(doc) -> - ["Test heavy load"]; -ip_load_heavy(suite) -> - []; -ip_load_heavy(Config) when is_list(Config) -> - httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config), - get_nof_clients(ip_comm, heavy)), - ok. - - -%%------------------------------------------------------------------------- -ip_dos_hostname(doc) -> - ["Denial Of Service (DOS) attack test case"]; -ip_dos_hostname(suite) -> - []; -ip_dos_hostname(Config) when is_list(Config) -> - dos_hostname(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config), ?MAX_HEADER_SIZE), - ok. - - -%%------------------------------------------------------------------------- -ip_time_test(doc) -> - [""]; -ip_time_test(suite) -> - []; -ip_time_test(Config) when is_list(Config) -> - %% <CONDITIONAL-SKIP> - Skippable = [win32], - Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> + %% Control that authentication required! + %% Control that the pages that shall be + %% authenticated really need authenticatin + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/open/ ", Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/secret/ ", Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/secret/top_secret/ ", + Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]), + + %% Make sure Authenticate header is received even the second time + %% we try a incorrect password! Otherwise a browser client will hang! + ok = auth_status(auth_request("/ht/open/", + "dummy", "WrongPassword", Version, Host), Config, + [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + ok = auth_status(auth_request("/ht/open/", + "dummy", "WrongPassword", Version, Host), Config, + [{statuscode, 401}, + {header, "WWW-Authenticate"}]), - httpd_time_test:t(ip_comm, ?config(host, Config), ?IP_PORT), - ok. - -%%------------------------------------------------------------------------- -ip_block_503(doc) -> - ["Check that you will receive status code 503 when the server" - " is blocked and 200 when its not blocked."]; -ip_block_503(suite) -> - []; -ip_block_503(Config) when is_list(Config) -> - httpd_block:block_503(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_disturbing_idle(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "distribing does not really make a difference in this case."]; -ip_block_disturbing_idle(suite) -> - []; -ip_block_disturbing_idle(Config) when is_list(Config) -> - httpd_block:block_disturbing_idle(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_non_disturbing_idle(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "non distribing does not really make a difference in this case."]; -ip_block_non_disturbing_idle(suite) -> - []; -ip_block_non_disturbing_idle(Config) when is_list(Config) -> - httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_disturbing_active(doc) -> - ["Check that you can block/unblock an active server. The strategy " - "distribing means ongoing requests should be terminated."]; -ip_block_disturbing_active(suite) -> - []; -ip_block_disturbing_active(Config) when is_list(Config) -> - httpd_block:block_disturbing_active(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_non_disturbing_active(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "non distribing means the ongoing requests should be compleated."]; -ip_block_non_disturbing_active(suite) -> - []; -ip_block_non_disturbing_active(Config) when is_list(Config) -> - httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - -%%------------------------------------------------------------------------- -ip_block_disturbing_active_timeout_not_released(doc) -> - ["Check that you can block an active server. The strategy " - "distribing means ongoing requests should be compleated" - "if the timeout does not occur."]; -ip_block_disturbing_active_timeout_not_released(suite) -> - []; -ip_block_disturbing_active_timeout_not_released(Config) - when is_list(Config) -> - httpd_block:block_disturbing_active_timeout_not_released(ip_comm, - ?IP_PORT, - ?config(host, - Config), - ?config(node, - Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_disturbing_active_timeout_released(doc) -> - ["Check that you can block an active server. The strategy " - "distribing means ongoing requests should be terminated when" - "the timeout occurs."]; -ip_block_disturbing_active_timeout_released(suite) -> - []; -ip_block_disturbing_active_timeout_released(Config) - when is_list(Config) -> - httpd_block:block_disturbing_active_timeout_released(ip_comm, - ?IP_PORT, - ?config(host, - Config), - ?config(node, - Config)), - ok. - -%%------------------------------------------------------------------------- -ip_block_non_disturbing_active_timeout_not_released(doc) -> - ["Check that you can block an active server. The strategy " - "non non distribing means ongoing requests should be completed."]; -ip_block_non_disturbing_active_timeout_not_released(suite) -> - []; -ip_block_non_disturbing_active_timeout_not_released(Config) - when is_list(Config) -> - httpd_block: - block_non_disturbing_active_timeout_not_released(ip_comm, - ?IP_PORT, - ?config(host, - Config), - ?config(node, - Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_non_disturbing_active_timeout_released(doc) -> - ["Check that you can block an active server. The strategy " - "non non distribing means ongoing requests should be completed. " - "When the timeout occurs the block operation sohould be canceled." ]; -ip_block_non_disturbing_active_timeout_released(suite) -> - []; -ip_block_non_disturbing_active_timeout_released(Config) - when is_list(Config) -> - httpd_block: - block_non_disturbing_active_timeout_released(ip_comm, - ?IP_PORT, - ?config(host, - Config), - ?config(node, - Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_disturbing_blocker_dies(doc) -> - []; -ip_block_disturbing_blocker_dies(suite) -> - []; -ip_block_disturbing_blocker_dies(Config) when is_list(Config) -> - httpd_block:disturbing_blocker_dies(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_block_non_disturbing_blocker_dies(doc) -> - []; -ip_block_non_disturbing_blocker_dies(suite) -> - []; -ip_block_non_disturbing_blocker_dies(Config) when is_list(Config) -> - httpd_block:non_disturbing_blocker_dies(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_restart_no_block(doc) -> - [""]; -ip_restart_no_block(suite) -> - []; -ip_restart_no_block(Config) when is_list(Config) -> - httpd_block:restart_no_block(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_restart_disturbing_block(doc) -> - [""]; -ip_restart_disturbing_block(suite) -> - []; -ip_restart_disturbing_block(Config) when is_list(Config) -> - %% <CONDITIONAL-SKIP> - Condition = - fun() -> - case os:type() of - {unix, linux} -> - HW = string:strip(os:cmd("uname -m"), right, $\n), - case HW of - "ppc" -> - case inet:gethostname() of - {ok, "peach"} -> - true; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end + %% Control that not just the first user in the list is valid + %% Control the first user + %% Authennticating ["one:OnePassword" user first in user list] + ok = auth_status(auth_request("/ht/open/dummy.html", "one", "OnePassword", + Version, Host), Config, + [{statuscode, 200}]), + + %% Control the second user + %% Authentication OK and a directory listing is supplied! + %% ["Aladdin:open sesame" user second in user list] + ok = auth_status(auth_request("/ht/open/","Aladdin", + "AladdinPassword", Version, Host), Config, + [{statuscode, 200}]), + + %% Contro that bad passwords and userids get a good denial + %% User correct but wrong password! ["one:one" user first in user list] + ok = auth_status(auth_request("/ht/open/", "one", "one", Version, Host), Config, + [{statuscode, 401}]), + %% Neither user or password correct! ["dummy:dummy"] + ok = auth_status(auth_request("/ht/open/", "dummy", "dummy", Version, Host), Config, + [{statuscode, 401}]), + + %% Control that authetication still works, even if its a member in a group + %% Authentication OK! ["two:TwoPassword" user in first group] + ok = auth_status(auth_request("/ht/secret/dummy.html", "two", + "TwoPassword", Version, Host), Config, + [{statuscode, 200}]), + + %% Authentication OK and a directory listing is supplied! + %% ["three:ThreePassword" user in second group] + ok = auth_status(auth_request("/ht/secret/", "three", + "ThreePassword", Version, Host), Config, + [{statuscode, 200}]), + + %% Deny users with bad passwords even if the user is a group member + %% User correct but wrong password! ["two:two" user in first group] + ok = auth_status(auth_request("/ht/secret/", "two", "two", Version, Host), Config, + [{statuscode, 401}]), + %% Neither user or password correct! ["dummy:dummy"] + ok = auth_status(auth_request("/ht/secret/", "dummy", "dummy", Version, Host), Config, + [{statuscode, 401}]), + + %% control that we deny the users that are in subnet above the allowed + ok = auth_status(auth_request("/ht/blocknet/dummy.html", "four", + "FourPassword", Version, Host), Config, + [{statuscode, 403}]), + %% Control that we only applies the rules to the right methods + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("HEAD /ht/blocknet/dummy.html ", Version, Host), + [{statuscode, head_status(Version)}, + {version, Version}]), + + %% Control that the rerquire directive can be overrideen + ok = auth_status(auth_request("/ht/secret/top_secret/ ", "Aladdin", "AladdinPassword", + Version, Host), Config, + [{statuscode, 401}]), + + %% Authentication still required! + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/open/ ", Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/secret/ ", Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + http_request("GET /ht/secret/top_secret/ ", Version, Host), + [{statuscode, 401}, + {version, Version}, + {header, "WWW-Authenticate"}]). + +%%------------------------------------------------------------------------- +host() -> + [{doc, "Test host header"}]. + +host(Config) when is_list(Config) -> + Cb = ?config(version_cb, Config), + Cb:host(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config)). +%%------------------------------------------------------------------------- +chunked() -> + [{doc, "Check that the server accepts chunked requests."}]. + +chunked(Config) when is_list(Config) -> + httpd_1_1:chunked(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config)). +%%------------------------------------------------------------------------- +expect() -> + ["Check that the server handles request with the expect header " + "field appropiate"]. +expect(Config) when is_list(Config) -> + httpd_1_1:expect(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config)). +%%------------------------------------------------------------------------- +max_clients_1_1() -> + [{doc, "Test max clients limit"}]. + +max_clients_1_1(Config) when is_list(Config) -> + do_max_clients([{http_version, "HTTP/1.1"} | Config]). + +max_clients_1_0() -> + [{doc, "Test max clients limit"}]. + +max_clients_1_0(Config) when is_list(Config) -> + do_max_clients([{http_version, "HTTP/1.0"} | Config]). + +max_clients_0_9() -> + [{doc, "Test max clients limit"}]. + +max_clients_0_9(Config) when is_list(Config) -> + do_max_clients([{http_version, "HTTP/0.9"} | Config]). +%%------------------------------------------------------------------------- +esi() -> + [{doc, "Test mod_esi"}]. + +esi(Config) when is_list(Config) -> + ok = http_status("GET /eval?httpd_example:print(\"Hi!\") ", + Config, [{statuscode, 200}]), + ok = http_status("GET /eval?not_allowed:print(\"Hi!\") ", + Config, [{statuscode, 403}]), + ok = http_status("GET /eval?httpd_example:undef(\"Hi!\") ", + Config, [{statuscode, 500}]), + ok = http_status("GET /cgi-bin/erl/httpd_example ", + Config, [{statuscode, 400}]), + ok = http_status("GET /cgi-bin/erl/httpd_example:get ", + Config, [{statuscode, 200}]), + ok = http_status("GET /cgi-bin/erl/httpd_example:" + "get?input=4711 ", Config, + [{statuscode, 200}]), + ok = http_status("GET /cgi-bin/erl/httpd_example:post ", + Config, [{statuscode, 200}]), + ok = http_status("GET /cgi-bin/erl/not_allowed:post ", + Config, [{statuscode, 403}]), + ok = http_status("GET /cgi-bin/erl/httpd_example:undef ", + Config, [{statuscode, 404}]), + ok = http_status("GET /cgi-bin/erl/httpd_example/yahoo ", + Config, [{statuscode, 302}]), + %% Check "ErlScriptNoCache" directive (default: false) + ok = http_status("GET /cgi-bin/erl/httpd_example:get ", + Config, [{statuscode, 200}, + {no_header, "cache-control"}]). +%%------------------------------------------------------------------------- +cgi() -> + [{doc, "Test mod_cgi"}]. + +cgi(Config) when is_list(Config) -> + {Script, Script2, Script3} = + case test_server:os_type() of + {win32, _} -> + {"printenv.bat", "printenv.sh", "cgi_echo.exe"}; + _ -> + {"printenv.sh", "printenv.bat", "cgi_echo"} end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. + %%The length (> 100) is intentional + ok = http_status("POST /cgi-bin/" ++ Script3 ++ " ", + {"Content-Length:100 \r\n", + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"}, + Config, + [{statuscode, 200}, + {header, "content-type", "text/plain"}]), + + ok = http_status("GET /cgi-bin/"++ Script ++ " ", Config, [{statuscode, 200}]), -%%------------------------------------------------------------------------- -ip_restart_non_disturbing_block(doc) -> - [""]; -ip_restart_non_disturbing_block(suite) -> - []; -ip_restart_non_disturbing_block(Config) when is_list(Config) -> - %% <CONDITIONAL-SKIP> - Condition = - fun() -> - case os:type() of - {unix, linux} -> - HW = string:strip(os:cmd("uname -m"), right, $\n), - case HW of - "ppc" -> - case inet:gethostname() of - {ok, "peach"} -> - true; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end + ok = http_status("GET /cgi-bin/not_there ", Config, + [{statuscode, 404}, {statuscode, 500}]), + + ok = http_status("GET /cgi-bin/"++ Script ++ "?Nisse:kkk?sss/lll ", + Config, + [{statuscode, 200}]), + + ok = http_status("POST /cgi-bin/"++ Script ++ " ", Config, + [{statuscode, 200}]), + + ok = http_status("GET /htbin/"++ Script ++ " ", Config, + [{statuscode, 200}]), + + ok = http_status("GET /htbin/not_there ", Config, + [{statuscode, 404},{statuscode, 500}]), + + ok = http_status("GET /htbin/"++ Script ++ "?Nisse:kkk?sss/lll ", Config, + [{statuscode, 200}]), + + ok = http_status("POST /htbin/"++ Script ++ " ", Config, + [{statuscode, 200}]), + + ok = http_status("POST /htbin/"++ Script ++ " ", Config, + [{statuscode, 200}]), + + %% Execute an existing, but bad CGI script.. + ok = http_status("POST /htbin/"++ Script2 ++ " ", Config, + [{statuscode, 404}]), + + ok = http_status("POST /cgi-bin/"++ Script2 ++ " ", Config, + [{statuscode, 404}]), + + %% Check "ScriptNoCache" directive (default: false) + ok = http_status("GET /cgi-bin/" ++ Script ++ " ", Config, + [{statuscode, 200}, + {no_header, "cache-control"}]). +%%------------------------------------------------------------------------- +cgi_chunked_encoding_test() -> + [{doc, "Test chunked encoding together with mod_cgi "}]. +cgi_chunked_encoding_test(Config) when is_list(Config) -> + Host = ?config(host, Config), + Script = + case test_server:os_type() of + {win32, _} -> + "/cgi-bin/printenv.bat"; + _ -> + "/cgi-bin/printenv.sh" end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - - httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - -%%------------------------------------------------------------------------- - -essl_mod_alias(doc) -> - ["Module test: mod_alias - using new of configure new SSL"]; -essl_mod_alias(suite) -> - []; -essl_mod_alias(Config) when is_list(Config) -> - ssl_mod_alias(essl, Config). - - -ssl_mod_alias(Tag, Config) -> - httpd_mod:alias(Tag, ?SSL_PORT, - ?config(host, Config), ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- - -essl_mod_actions(doc) -> - ["Module test: mod_actions - using new of configure new SSL"]; -essl_mod_actions(suite) -> - []; -essl_mod_actions(Config) when is_list(Config) -> - ssl_mod_actions(essl, Config). - - -ssl_mod_actions(Tag, Config) -> - httpd_mod:actions(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- - -essl_mod_security(doc) -> - ["Module test: mod_security - using new of configure new SSL"]; -essl_mod_security(suite) -> - []; -essl_mod_security(Config) when is_list(Config) -> - ssl_mod_security(essl, Config). - -ssl_mod_security(Tag, Config) -> - ServerRoot = ?config(server_root, Config), - httpd_mod:security(ServerRoot, - Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- - -essl_mod_auth(doc) -> - ["Module test: mod_auth - using new of configure new SSL"]; -essl_mod_auth(suite) -> - []; -essl_mod_auth(Config) when is_list(Config) -> - ssl_mod_auth(essl, Config). - -ssl_mod_auth(Tag, Config) -> - httpd_mod:auth(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- - - -essl_mod_auth_api(doc) -> - ["Module test: mod_auth - using new of configure new SSL"]; -essl_mod_auth_api(suite) -> - []; -essl_mod_auth_api(Config) when is_list(Config) -> - ssl_mod_auth_api(essl, Config). - -ssl_mod_auth_api(Tag, Config) -> - ServerRoot = ?config(server_root, Config), - Host = ?config(host, Config), - Node = ?config(node, Config), - httpd_mod:auth_api(ServerRoot, "", Tag, ?SSL_PORT, Host, Node), - httpd_mod:auth_api(ServerRoot, "dets_", Tag, ?SSL_PORT, Host, Node), - httpd_mod:auth_api(ServerRoot, "mnesia_", Tag, ?SSL_PORT, Host, Node), - ok. - - -%%------------------------------------------------------------------------- - - -essl_mod_auth_mnesia_api(doc) -> - ["Module test: mod_auth_mnesia_api - using new of configure new SSL"]; -essl_mod_auth_mnesia_api(suite) -> - []; -essl_mod_auth_mnesia_api(Config) when is_list(Config) -> - ssl_mod_auth_mnesia_api(essl, Config). - -ssl_mod_auth_mnesia_api(Tag, Config) -> - httpd_mod:auth_mnesia_api(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- - -essl_mod_htaccess(doc) -> - ["Module test: mod_htaccess - using new of configure new SSL"]; -essl_mod_htaccess(suite) -> - []; -essl_mod_htaccess(Config) when is_list(Config) -> - ssl_mod_htaccess(essl, Config). - -ssl_mod_htaccess(Tag, Config) -> - httpd_mod:htaccess(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - + Requests = + ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n", + "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:" + ++ Host ++"\r\n\r\n"], + httpd_1_1:mod_cgi_chunked_encoding_test(?config(type, Config), ?config(port, Config), + Host, + ?config(node, Config), + Requests). %%------------------------------------------------------------------------- +alias() -> + [{doc, "Test mod_alias"}]. -essl_mod_cgi(doc) -> - ["Module test: mod_cgi - using new of configure new SSL"]; -essl_mod_cgi(suite) -> - []; -essl_mod_cgi(Config) when is_list(Config) -> - ssl_mod_cgi(essl, Config). - -ssl_mod_cgi(Tag, Config) -> - httpd_mod:cgi(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +alias(Config) when is_list(Config) -> + ok = http_status("GET /pics/icon.sheet.gif ", Config, + [{statuscode, 200}, + {header, "Content-Type","image/gif"}, + {header, "Server"}, + {header, "Date"}]), + + ok = http_status("GET / ", Config, + [{statuscode, 200}, + {header, "Content-Type","text/html"}, + {header, "Server"}, + {header, "Date"}]), + + ok = http_status("GET /misc/ ", Config, + [{statuscode, 200}, + {header, "Content-Type","text/html"}, + {header, "Server"}, + {header, "Date"}]), + %% Check redirection if trailing slash is missing. + ok = http_status("GET /misc ", Config, + [{statuscode, 301}, + {header, "Location"}, + {header, "Content-Type","text/html"}]). %%------------------------------------------------------------------------- +actions() -> + [{doc, "Test mod_actions"}]. -essl_mod_esi(doc) -> - ["Module test: mod_esi - using new of configure new SSL"]; -essl_mod_esi(suite) -> - []; -essl_mod_esi(Config) when is_list(Config) -> - ssl_mod_esi(essl, Config). - -ssl_mod_esi(Tag, Config) -> - httpd_mod:esi(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +actions(Config) when is_list(Config) -> + ok = http_status("GET /", Config, [{statuscode, 200}]). %%------------------------------------------------------------------------- +range() -> + [{doc, "Test Range header"}]. -essl_mod_get(doc) -> - ["Module test: mod_get - using new of configure new SSL"]; -essl_mod_get(suite) -> - []; -essl_mod_get(Config) when is_list(Config) -> - ssl_mod_get(essl, Config). - -ssl_mod_get(Tag, Config) -> - httpd_mod:get(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +range(Config) when is_list(Config) -> + httpd_1_1:range(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config)). %%------------------------------------------------------------------------- +if_modified_since() -> + [{doc, "Test If-Modified-Since header"}]. -essl_mod_head(doc) -> - ["Module test: mod_head - using new of configure new SSL"]; -essl_mod_head(suite) -> - []; -essl_mod_head(Config) when is_list(Config) -> - ssl_mod_head(essl, Config). - -ssl_mod_head(Tag, Config) -> - httpd_mod:head(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - +if_modified_since(Config) when is_list(Config) -> + httpd_1_1:if_test(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config), + ?config(doc_root, Config)). %%------------------------------------------------------------------------- +trace() -> + [{doc, "Test TRACE method"}]. -essl_mod_all(doc) -> - ["All modules test - using new of configure new SSL"]; -essl_mod_all(suite) -> - []; -essl_mod_all(Config) when is_list(Config) -> - ssl_mod_all(essl, Config). - -ssl_mod_all(Tag, Config) -> - httpd_mod:all(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +trace(Config) when is_list(Config) -> + Cb = ?config(version_cb, Config), + Cb:trace(?config(type, Config), ?config(port, Config), + ?config(host, Config), ?config(node, Config)). %%------------------------------------------------------------------------- - -essl_load_light(doc) -> - ["Test light load - using new of configure new SSL"]; -essl_load_light(suite) -> - []; -essl_load_light(Config) when is_list(Config) -> - ssl_load_light(essl, Config). - -ssl_load_light(Tag, Config) -> - httpd_load:load_test(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config), - get_nof_clients(ssl, light)), - ok. - - +light() -> + ["Test light load"]. +light(Config) when is_list(Config) -> + httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), + ?config(node, Config), 10). %%------------------------------------------------------------------------- - -essl_load_medium(doc) -> - ["Test medium load - using new of configure new SSL"]; -essl_load_medium(suite) -> - []; -essl_load_medium(Config) when is_list(Config) -> - ssl_load_medium(essl, Config). - -ssl_load_medium(Tag, Config) -> - %% <CONDITIONAL-SKIP> - Skippable = [win32], - Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - - httpd_load:load_test(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config), - get_nof_clients(ssl, medium)), - ok. - - +medium() -> + ["Test medium load"]. +medium(Config) when is_list(Config) -> + httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), + ?config(node, Config), 100). %%------------------------------------------------------------------------- - -essl_load_heavy(doc) -> - ["Test heavy load - using new of configure new SSL"]; -essl_load_heavy(suite) -> - []; -essl_load_heavy(Config) when is_list(Config) -> - ssl_load_heavy(essl, Config). - -ssl_load_heavy(Tag, Config) -> - %% <CONDITIONAL-SKIP> - Skippable = [win32], - Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - - httpd_load:load_test(Tag, - ?SSL_PORT, - ?config(host, Config), +heavy() -> + ["Test heavy load"]. +heavy(Config) when is_list(Config) -> + httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), ?config(node, Config), - get_nof_clients(ssl, heavy)), - ok. - - -%%------------------------------------------------------------------------- - - -essl_dos_hostname(doc) -> - ["Denial Of Service (DOS) attack test case - using new of configure new SSL"]; -essl_dos_hostname(suite) -> - []; -essl_dos_hostname(Config) when is_list(Config) -> - ssl_dos_hostname(essl, Config). - -ssl_dos_hostname(Tag, Config) -> - dos_hostname(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config), - ?MAX_HEADER_SIZE), - ok. - - -%%------------------------------------------------------------------------- - - -essl_time_test(doc) -> - ["using new of configure new SSL"]; -essl_time_test(suite) -> - []; -essl_time_test(Config) when is_list(Config) -> - ssl_time_test(essl, Config). - -ssl_time_test(Tag, Config) when is_list(Config) -> - %% <CONDITIONAL-SKIP> - FreeBSDVersionVerify = - fun() -> - case os:version() of - {7, 1, _} -> % We only have one such machine, so... - true; - _ -> - false - end - end, - Skippable = [win32, {unix, [{freebsd, FreeBSDVersionVerify}]}], - Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - - httpd_time_test:t(Tag, - ?config(host, Config), - ?SSL_PORT), - ok. - - + 1000). %%------------------------------------------------------------------------- - - -essl_block_503(doc) -> - ["Check that you will receive status code 503 when the server" - " is blocked and 200 when its not blocked - using new of configure new SSL."]; -essl_block_503(suite) -> - []; -essl_block_503(Config) when is_list(Config) -> - ssl_block_503(essl, Config). - -ssl_block_503(Tag, Config) -> - httpd_block:block_503(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - +content_length() -> + ["Tests that content-length is correct OTP-5775"]. +content_length(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), ?config(node, Config), + http_request("GET /cgi-bin/erl/httpd_example:get_bin ", + Version, Host), + [{statuscode, 200}, + {content_length, 274}, + {version, Version}]). %%------------------------------------------------------------------------- - -essl_block_disturbing_idle(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "distribing does not really make a difference in this case." - "Using new of configure new SSL"]; -essl_block_disturbing_idle(suite) -> - []; -essl_block_disturbing_idle(Config) when is_list(Config) -> - ssl_block_disturbing_idle(essl, Config). - -ssl_block_disturbing_idle(Tag, Config) -> - httpd_block:block_disturbing_idle(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - +bad_hex() -> + ["Tests that a URI with a bad hexadecimal code is handled OTP-6003"]. +bad_hex(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), ?config(node, Config), + http_request("GET http://www.erlang.org/%skalle ", + Version, Host), + [{statuscode, 400}, + {version, Version}]). %%------------------------------------------------------------------------- - -essl_block_non_disturbing_idle(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "non distribing does not really make a difference in this case." - "Using new of configure new SSL"]; -essl_block_non_disturbing_idle(suite) -> - []; -essl_block_non_disturbing_idle(Config) when is_list(Config) -> - ssl_block_non_disturbing_idle(essl, Config). - -ssl_block_non_disturbing_idle(Tag, Config) -> - httpd_block:block_non_disturbing_idle(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +missing_CR() -> + ["Tests missing CR in delimiter OTP-7304"]. +missing_CR(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), ?config(node, Config), + http_request_missing_CR("GET /index.html ", Version, Host), + [{statuscode, 200}, + {version, Version}]). %%------------------------------------------------------------------------- - -essl_block_disturbing_active(doc) -> - ["Check that you can block/unblock an active server. The strategy " - "distribing means ongoing requests should be terminated." - "Using new of configure new SSL"]; -essl_block_disturbing_active(suite) -> - []; -essl_block_disturbing_active(Config) when is_list(Config) -> - ssl_block_disturbing_active(essl, Config). - -ssl_block_disturbing_active(Tag, Config) -> - httpd_block:block_disturbing_active(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - +max_header() -> + ["Denial Of Service (DOS) attack, prevented by max_header"]. +max_header(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + case Version of + "HTTP/0.9" -> + {skip, no_implemented}; + _ -> + dos_hostname(?config(type, Config), ?config(port, Config), Host, + ?config(node, Config), Version, ?MAX_HEADER_SIZE) + end. %%------------------------------------------------------------------------- +security_1_1(Config) when is_list(Config) -> + security([{http_version, "HTTP/1.1"} | Config]). -essl_block_non_disturbing_active(doc) -> - ["Check that you can block/unblock an idle server. The strategy " - "non distribing means the ongoing requests should be compleated." - "Using new of configure new SSL"]; -essl_block_non_disturbing_active(suite) -> - []; -essl_block_non_disturbing_active(Config) when is_list(Config) -> - ssl_block_non_disturbing_active(essl, Config). - -ssl_block_non_disturbing_active(Tag, Config) -> - httpd_block:block_non_disturbing_idle(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. - - -%%------------------------------------------------------------------------- +security_1_0(Config) when is_list(Config) -> + security([{http_version, "HTTP/1.0"} | Config]). -essl_block_disturbing_active_timeout_not_released(doc) -> - ["Check that you can block an active server. The strategy " - "distribing means ongoing requests should be compleated" - "if the timeout does not occur." - "Using new of configure new SSL"]; -essl_block_disturbing_active_timeout_not_released(suite) -> - []; -essl_block_disturbing_active_timeout_not_released(Config) - when is_list(Config) -> - ssl_block_disturbing_active_timeout_not_released(essl, Config). - -ssl_block_disturbing_active_timeout_not_released(Tag, Config) -> - Port = ?SSL_PORT, - Host = ?config(host, Config), - Node = ?config(node, Config), - httpd_block:block_disturbing_active_timeout_not_released(Tag, - Port, Host, Node), - ok. +security() -> + ["Test mod_security"]. +security(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Node = ?config(node, Config), + ServerRoot = ?config(server_root, Config), + global:register_name(mod_security_test, self()), % Receive events -%%------------------------------------------------------------------------- + test_server:sleep(5000), -essl_block_disturbing_active_timeout_released(doc) -> - ["Check that you can block an active server. The strategy " - "distribing means ongoing requests should be terminated when" - "the timeout occurs." - "Using new of configure new SSL"]; -essl_block_disturbing_active_timeout_released(suite) -> - []; -essl_block_disturbing_active_timeout_released(Config) - when is_list(Config) -> - ssl_block_disturbing_active_timeout_released(essl, Config). - -ssl_block_disturbing_active_timeout_released(Tag, Config) -> - Port = ?SSL_PORT, - Host = ?config(host, Config), - Node = ?config(node, Config), - httpd_block:block_disturbing_active_timeout_released(Tag, - Port, - Host, - Node), - ok. + OpenDir = filename:join([ServerRoot, "htdocs", "open"]), + %% Test blocking / unblocking of users. -%%------------------------------------------------------------------------- + %% /open, require user one Aladdin + remove_users(Node, ServerRoot, Host, Port, "", "open"), -essl_block_non_disturbing_active_timeout_not_released(doc) -> - ["Check that you can block an active server. The strategy " - "non non distribing means ongoing requests should be completed." - "Using new of configure new SSL"]; -essl_block_non_disturbing_active_timeout_not_released(suite) -> - []; -essl_block_non_disturbing_active_timeout_not_released(Config) - when is_list(Config) -> - ssl_block_non_disturbing_active_timeout_not_released(essl, Config). - -ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) -> - Port = ?SSL_PORT, - Host = ?config(host, Config), - Node = ?config(node, Config), - httpd_block:block_non_disturbing_active_timeout_not_released(Tag, - Port, - Host, - Node), - ok. + ok = auth_status(auth_request("/open/", + "one", "onePassword", Version, Host), Config, + [{statuscode, 401}]), + + receive_security_event({event, auth_fail, Port, OpenDir, + [{user, "one"}, {password, "onePassword"}]}, + Node, Port), + + ok = auth_status(auth_request("/open/", + "two", "twoPassword", Version, Host), Config, + [{statuscode, 401}]), + + receive_security_event({event, auth_fail, Port, OpenDir, + [{user, "two"}, {password, "twoPassword"}]}, + Node, Port), + ok = auth_status(auth_request("/open/", + "Aladdin", "AladdinPassword", Version, Host), + Config, [{statuscode, 401}]), + + receive_security_event({event, auth_fail, Port, OpenDir, + [{user, "Aladdin"}, + {password, "AladdinPassword"}]}, + Node, Port), -%%------------------------------------------------------------------------- + add_user(Node, ServerRoot, Port, "", "open", "one", "onePassword", []), + add_user(Node, ServerRoot, Port, "", "open", "two", "twoPassword", []), + ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, + [{statuscode, 401}]), + + receive_security_event({event, auth_fail, Port, OpenDir, + [{user, "one"}, {password, "WrongPassword"}]}, + Node, Port), -essl_block_non_disturbing_active_timeout_released(doc) -> - ["Check that you can block an active server. The strategy " - "non distribing means ongoing requests should be completed. " - "When the timeout occurs the block operation sohould be canceled." - "Using new of configure new SSL"]; -essl_block_non_disturbing_active_timeout_released(suite) -> - []; -essl_block_non_disturbing_active_timeout_released(Config) - when is_list(Config) -> - ssl_block_non_disturbing_active_timeout_released(essl, Config). - -ssl_block_non_disturbing_active_timeout_released(Tag, Config) - when is_list(Config) -> - Port = ?SSL_PORT, - Host = ?config(host, Config), - Node = ?config(node, Config), - httpd_block:block_non_disturbing_active_timeout_released(Tag, - Port, - Host, - Node), + ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, + [{statuscode, 401}]), + + receive_security_event({event, auth_fail, Port, OpenDir, + [{user, "one"}, {password, "WrongPassword"}]}, + Node, Port), + receive_security_event({event, user_block, Port, OpenDir, + [{user, "one"}]}, Node, Port), + + global:unregister_name(mod_security_test), % No more events. + + ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, + [{statuscode, 401}]), + + %% User "one" should be blocked now.. + case list_blocked_users(Node, Port) of + [{"one",_, Port, OpenDir,_}] -> + ok; + Blocked -> + ct:fail({unexpected_blocked, Blocked}) + end, - ok. + [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir), + true = unblock_user(Node, "one", Port, OpenDir), + %% User "one" should not be blocked any more. -%%------------------------------------------------------------------------- + [] = list_blocked_users(Node, Port), + ok = auth_status(auth_request("/open/", "one", "onePassword", Version, Host), Config, + [{statuscode, 200}]), -essl_block_disturbing_blocker_dies(doc) -> - ["using new of configure new SSL"]; -essl_block_disturbing_blocker_dies(suite) -> - []; -essl_block_disturbing_blocker_dies(Config) when is_list(Config) -> - ssl_block_disturbing_blocker_dies(essl, Config). + %% Test list_auth_users & auth_timeout -ssl_block_disturbing_blocker_dies(Tag, Config) -> - httpd_block:disturbing_blocker_dies(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. + ["one"] = list_auth_users(Node, Port), + ok = auth_status(auth_request("/open/", "two", "onePassword", Version, Host), Config, + [{statuscode, 401}]), -%%------------------------------------------------------------------------- + ["one"] = list_auth_users(Node, Port), -essl_block_non_disturbing_blocker_dies(doc) -> - ["using new of configure new SSL"]; -essl_block_non_disturbing_blocker_dies(suite) -> - []; -essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) -> - ssl_block_non_disturbing_blocker_dies(essl, Config). - -ssl_block_non_disturbing_blocker_dies(Tag, Config) -> - httpd_block:non_disturbing_blocker_dies(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. + + ["one"] = list_auth_users(Node, Port, OpenDir), + + ok = auth_status(auth_request("/open/", "two", "twoPassword", Version, Host), Config, + [{statuscode, 401}]), -%%------------------------------------------------------------------------- + ["one"] = list_auth_users(Node, Port), + + ["one"] = list_auth_users(Node, Port, OpenDir), -essl_restart_no_block(doc) -> - ["using new of configure new SSL"]; -essl_restart_no_block(suite) -> - []; -essl_restart_no_block(Config) when is_list(Config) -> - ssl_restart_no_block(essl, Config). + %% Wait for successful auth to timeout. + test_server:sleep(?AUTH_TIMEOUT*1001), -ssl_restart_no_block(Tag, Config) -> - httpd_block:restart_no_block(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. + [] = list_auth_users(Node, Port), + [] = list_auth_users(Node, Port, OpenDir), -%%------------------------------------------------------------------------- + %% "two" is blocked. + true = unblock_user(Node, "two", Port, OpenDir), -essl_restart_disturbing_block(doc) -> - ["using new of configure new SSL"]; -essl_restart_disturbing_block(suite) -> - []; -essl_restart_disturbing_block(Config) when is_list(Config) -> - ssl_restart_disturbing_block(essl, Config). - -ssl_restart_disturbing_block(Tag, Config) -> - %% <CONDITIONAL-SKIP> - Condition = - fun() -> - case os:type() of - {unix, linux} -> - case ?OSCMD("uname -m") of - "ppc" -> - case file:read_file_info("/etc/fedora-release") of - {ok, _} -> - case ?OSCMD("awk '{print $2}' /etc/fedora-release") of - "release" -> - %% Fedora 7 and later - case ?OSCMD("awk '{print $3}' /etc/fedora-release") of - "7" -> - true; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end - end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - httpd_block:restart_disturbing_block(Tag, ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. + %% Test explicit blocking. Block user 'two'. + [] = list_blocked_users(Node,Port,OpenDir), -%%------------------------------------------------------------------------- + true = block_user(Node, "two", Port, OpenDir, 10), + ok = auth_status(auth_request("/open/", "two", "twoPassword", Version, Host), Config, + [{statuscode, 401}]), + + true = unblock_user(Node, "two", Port, OpenDir). + -essl_restart_non_disturbing_block(doc) -> - ["using new of configure new SSL"]; -essl_restart_non_disturbing_block(suite) -> - []; -essl_restart_non_disturbing_block(Config) when is_list(Config) -> - ssl_restart_non_disturbing_block(essl, Config). - -ssl_restart_non_disturbing_block(Tag, Config) -> - %% <CONDITIONAL-SKIP> - Condition = - fun() -> - case os:type() of - {unix, linux} -> - HW = string:strip(os:cmd("uname -m"), right, $\n), - case HW of - "ppc" -> - case inet:gethostname() of - {ok, "peach"} -> - true; - _ -> - false - end; - _ -> - false - end; - _ -> - false - end - end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - httpd_block:restart_non_disturbing_block(Tag, - ?SSL_PORT, - ?config(host, Config), - ?config(node, Config)), - ok. +%%-------------------------------------------------------------------- +%% Internal functions ----------------------------------- +%%-------------------------------------------------------------------- +do_max_clients(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + + Request = http_request("GET /index.html ", Version, Host), + BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), + {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), + inets_test_lib:send(Type, Socket, BlockRequest), + ct:sleep(100), %% Avoid possible timing issues + ok = httpd_test_lib:verify_request(Type, Host, + Port, + transport_opts(Type, Config), + ?config(node, Config), + Request, + [{statuscode, 503}, + {version, Version}]), + receive + {_, Socket, _Msg} -> + ok + end, + inets_test_lib:close(Type, Socket), + ct:sleep(100), %% Avoid possible timing issues + ok = httpd_test_lib:verify_request(Type, Host, + Port, + transport_opts(Type, Config), + ?config(node, Config), + Request, + [{statuscode, 200}, + {version, Version}]). +setup_server_dirs(ServerRoot, DocRoot, DataDir) -> + CgiDir = filename:join(ServerRoot, "cgi-bin"), + AuthDir = filename:join(ServerRoot, "auth"), + PicsDir = filename:join(ServerRoot, "icons"), -%%------------------------------------------------------------------------- -ip_host(doc) -> - ["Control that the server accepts/rejects requests with/ without host"]; -ip_host(suite)-> - []; -ip_host(Config) when is_list(Config) -> - httpd_1_1:host(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_chunked(doc) -> - ["Control that the server accepts chunked requests"]; -ip_chunked(suite) -> - []; -ip_chunked(Config) when is_list(Config) -> - httpd_1_1:chunked(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_expect(doc) -> - ["Control that the server handles request with the expect header " - "field appropiate"]; -ip_expect(suite)-> - []; -ip_expect(Config) when is_list(Config) -> - httpd_1_1:expect(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_range(doc) -> - ["Control that the server can handle range requests to plain files"]; -ip_range(suite)-> - []; -ip_range(Config) when is_list(Config) -> - httpd_1_1:range(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_if_test(doc) -> - ["Test that the if - request header fields is handled correclty"]; -ip_if_test(suite) -> - []; -ip_if_test(Config) when is_list(Config) -> - ServerRoot = ?config(server_root, Config), - DocRoot = filename:join([ServerRoot, "htdocs"]), - httpd_1_1:if_test(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config), DocRoot), - ok. -%%------------------------------------------------------------------------- -ip_http_trace(doc) -> - ["Test the trace module "]; -ip_http_trace(suite) -> - []; -ip_http_trace(Config) when is_list(Config) -> - httpd_1_1:http_trace(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. -%%------------------------------------------------------------------------- -ip_http1_1_head(doc) -> - ["Test the trace module "]; -ip_http1_1_head(suite)-> - []; -ip_http1_1_head(Config) when is_list(Config) -> - httpd_1_1:head(ip_comm, ?IP_PORT, ?config(host, Config), - ?config(node, Config)), - ok. - -%%------------------------------------------------------------------------- -ip_get_0_9(doc) -> - ["Test simple HTTP/0.9 GET"]; -ip_get_0_9(suite)-> - []; -ip_get_0_9(Config) when is_list(Config) -> - Host = ?config(host, Config), - Node = ?config(node, Config), - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "GET / \r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/0.9"} ]), - %% Without space after uri - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "GET /\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/0.9"} ]), - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "GET / HTTP/0.9\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/0.9"}]), - - ok. -%%------------------------------------------------------------------------- -ip_head_1_0(doc) -> - ["Test HTTP/1.0 HEAD"]; -ip_head_1_0(suite)-> - []; -ip_head_1_0(Config) when is_list(Config) -> - Host = ?config(host, Config), - Node = ?config(node, Config), - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "HEAD / HTTP/1.0\r\n\r\n", [{statuscode, 200}, - {version, "HTTP/1.0"}]), + ok = file:make_dir(ServerRoot), + ok = file:make_dir(DocRoot), + ok = file:make_dir(CgiDir), + ok = file:make_dir(AuthDir), + ok = file:make_dir(PicsDir), + + DocSrc = filename:join(DataDir, "server_root/htdocs"), + AuthSrc = filename:join(DataDir, "server_root/auth"), + CgiSrc = filename:join(DataDir, "server_root/cgi-bin"), + PicsSrc = filename:join(DataDir, "server_root/icons"), - ok. -%%------------------------------------------------------------------------- -ip_get_1_0(doc) -> - ["Test HTTP/1.0 GET"]; -ip_get_1_0(suite)-> - []; -ip_get_1_0(Config) when is_list(Config) -> - Host = ?config(host, Config), - Node = ?config(node, Config), - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "GET / HTTP/1.0\r\n\r\n", [{statuscode, 200}, - {version, "HTTP/1.0"}]), + inets_test_lib:copy_dirs(DocSrc, DocRoot), + inets_test_lib:copy_dirs(AuthSrc, AuthDir), + inets_test_lib:copy_dirs(CgiSrc, CgiDir), + inets_test_lib:copy_dirs(PicsSrc, PicsDir), + + Cgi = case test_server:os_type() of + {win32, _} -> + "cgi_echo.exe"; + _ -> + "cgi_echo" + end, - ok. -%%------------------------------------------------------------------------- -ip_post_1_0(doc) -> - ["Test HTTP/1.0 POST"]; -ip_post_1_0(suite)-> - []; -ip_post_1_0(Config) when is_list(Config) -> - Host = ?config(host, Config), - Node = ?config(node, Config), - %% Test the post message formatin 1.0! Real post are testes elsewhere - ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, - "POST / HTTP/1.0\r\n\r\n " - "Content-Length:6 \r\n\r\nfoobar", - [{statuscode, 500}, {version, "HTTP/1.0"}]), + inets_test_lib:copy_file(Cgi, DataDir, CgiDir), + AbsCgi = filename:join([CgiDir, Cgi]), + {ok, FileInfo} = file:read_file_info(AbsCgi), + ok = file:write_file_info(AbsCgi, FileInfo#file_info{mode = 8#00755}), - ok. -%%------------------------------------------------------------------------- -ip_mod_cgi_chunked_encoding_test(doc) -> - ["Test the trace module "]; -ip_mod_cgi_chunked_encoding_test(suite)-> - []; -ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) -> - Host = ?config(host, Config), - Script = - case test_server:os_type() of - {win32, _} -> - "/cgi-bin/printenv.bat"; - _ -> - "/cgi-bin/printenv.sh" - end, - Requests = - ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n", - "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:" - ++ Host ++"\r\n\r\n"], - httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT, - Host, - ?config(node, Config), - Requests), - ok. - -%------------------------------------------------------------------------- - -ipv6_hostname_ipcomm() -> - [{require, ipv6_hosts}]. -ipv6_hostname_ipcomm(X) -> - SocketType = ip_comm, - Port = ?IP_PORT, - ipv6_hostname(SocketType, Port, X). - -ipv6_hostname_essl() -> - [{require, ipv6_hosts}]. -ipv6_hostname_essl(X) -> - SocketType = essl, - Port = ?SSL_PORT, - ipv6_hostname(SocketType, Port, X). - -ipv6_hostname(_SocketType, _Port, doc) -> - ["Test standard ipv6 address"]; -ipv6_hostname(_SocketType, _Port, suite)-> - []; -ipv6_hostname(SocketType, Port, Config) when is_list(Config) -> - tsp("ipv6_hostname -> entry with" - "~n SocketType: ~p" - "~n Port: ~p" - "~n Config: ~p", [SocketType, Port, Config]), - Host = ?config(host, Config), - URI = "GET HTTP://" ++ - Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n", - tsp("ipv6_hostname -> Host: ~p", [Host]), - httpd_test_lib:verify_request(SocketType, Host, Port, [inet6], - node(), - URI, - [{statuscode, 200}, {version, "HTTP/1.1"}]), - ok. - -%%------------------------------------------------------------------------- - -ipv6_address_ipcomm() -> - [{require, ipv6_hosts}]. -ipv6_address_ipcomm(X) -> - SocketType = ip_comm, - Port = ?IP_PORT, - ipv6_address(SocketType, Port, X). - -ipv6_address_essl() -> - [{require, ipv6_hosts}]. -ipv6_address_essl(X) -> - SocketType = essl, - Port = ?SSL_PORT, - ipv6_address(SocketType, Port, X). - -ipv6_address(_SocketType, _Port, doc) -> - ["Test standard ipv6 address"]; -ipv6_address(_SocketType, _Port, suite)-> - []; -ipv6_address(SocketType, Port, Config) when is_list(Config) -> - tsp("ipv6_address -> entry with" - "~n SocketType: ~p" - "~n Port: ~p" - "~n Config: ~p", [SocketType, Port, Config]), - Host = ?config(host, Config), - tsp("ipv6_address -> Host: ~p", [Host]), - URI = "GET HTTP://" ++ - Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n", - httpd_test_lib:verify_request(SocketType, Host, Port, [inet6], - node(), - URI, - [{statuscode, 200}, {version, "HTTP/1.1"}]), - ok. - - -%%-------------------------------------------------------------------- -ticket_5775(doc) -> - ["Tests that content-length is correct"]; -ticket_5775(suite) -> - []; -ticket_5775(Config) -> - ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config), - ?IP_PORT, ?config(node, Config), - "GET /cgi-bin/erl/httpd_example:get_bin " - "HTTP/1.0\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/1.0"}]), - ok. -ticket_5865(doc) -> - ["Tests that a header without last-modified is handled"]; -ticket_5865(suite) -> - []; -ticket_5865(Config) -> - ?SKIP(as_of_r15_behaviour_of_calendar_has_changed), - Host = ?config(host,Config), - ServerRoot = ?config(server_root, Config), - DocRoot = filename:join([ServerRoot, "htdocs"]), - File = filename:join([DocRoot,"last_modified.html"]), - - Bad_mtime = case test_server:os_type() of - {win32, _} -> - {{1600,12,31},{23,59,59}}; - {unix, _} -> - {{1969,12,31},{23,59,59}} - end, + EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]), + {ok, FileInfo1} = file:read_file_info(EnvCGI), + ok = file:write_file_info(EnvCGI, + FileInfo1#file_info{mode = 8#00755}). - {ok,FI}=file:read_file_info(File), +start_apps(Group) when Group == https_basic; + Group == https_limit; + Group == https_basic_auth; + Group == https_auth_api; + Group == https_auth_api_dets; + Group == https_auth_api_mnesia; + Group == http_htaccess; + Group == http_security -> + inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]); +start_apps(Group) when Group == http_basic; + Group == http_limit; + Group == http_basic_auth; + Group == http_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == https_htaccess; + Group == https_security -> + inets_test_lib:start_apps([inets]). + +server_start(_, HttpdConfig) -> + {ok, Pid} = inets:start(httpd, HttpdConfig), + Serv = inets:services_info(), + {value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv), + {Pid, proplists:get_value(port, Info)}. + +init_ssl(Group, Config) -> + PrivDir = ?config(priv_dir, Config), + CaKey = {_Trusted,_} = + erl_make_certs:make_cert([{key, dsa}, + {subject, + [{name, "Public Key"}, + {?'id-at-name', + {printableString, "public_key"}}, + {?'id-at-pseudonym', + {printableString, "pubkey"}}, + {city, "Stockholm"}, + {country, "SE"}, + {org, "erlang"}, + {org_unit, "testing dep"} + ]} + ]), + ok = erl_make_certs:write_pem(PrivDir, "public_key_cacert", CaKey), - case file:write_file_info(File,FI#file_info{mtime=Bad_mtime}) of + CertK1 = {_Cert1, _} = erl_make_certs:make_cert([{issuer, CaKey}]), + CertK2 = {_Cert2,_} = erl_make_certs:make_cert([{issuer, CertK1}, + {digest, md5}, + {extensions, false}]), + ok = erl_make_certs:write_pem(PrivDir, "public_key_cert", CertK2), + + case start_apps(Group) of ok -> - ok = httpd_test_lib:verify_request(ip_comm, Host, - ?IP_PORT, ?config(node, Config), - "GET /last_modified.html" - " HTTP/1.1\r\nHost:" - ++Host++"\r\n\r\n", - [{statuscode, 200}, - {no_header, - "last-modified"}]), - ok; - {error, Reason} -> - Fault = - io_lib:format("Attempt to change the file info to set the" - " preconditions of the test case failed ~p~n", - [Reason]), - {skip, Fault} + init_httpd(Group, [{type, ssl} | Config]); + _ -> + {skip, "Could not start https apps"} end. -ticket_5913(doc) -> - ["Tests that a header without last-modified is handled"]; -ticket_5913(suite) -> []; -ticket_5913(Config) -> - ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), - ?IP_PORT, ?config(node, Config), - "GET /cgi-bin/erl/httpd_example:get_bin " - "HTTP/1.0\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/1.0"}]), - ok. - -ticket_6003(doc) -> - ["Tests that a URI with a bad hexadecimal code is handled"]; -ticket_6003(suite) -> []; -ticket_6003(Config) -> - ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), - ?IP_PORT, ?config(node, Config), - "GET http://www.erlang.org/%skalle " - "HTTP/1.0\r\n\r\n", - [{statuscode, 400}, - {version, "HTTP/1.0"}]), - ok. - -ticket_7304(doc) -> - ["Tests missing CR in delimiter"]; -ticket_7304(suite) -> - []; -ticket_7304(Config) -> - ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), - ?IP_PORT, ?config(node, Config), - "GET / HTTP/1.0\r\n\n", - [{statuscode, 200}, - {version, "HTTP/1.0"}]), - ok. - -%%-------------------------------------------------------------------- -%% Internal functions -%%-------------------------------------------------------------------- -dos_hostname(Type, Port, Host, Node, Max) -> - H1 = {"", 200}, - H2 = {"dummy-host.ericsson.se", 200}, - TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")), - H3 = {TooLongHeader, 403}, - Hosts = [H1,H2,H3], - dos_hostname_poll(Type, Host, Port, Node, Hosts). - -%% make_ipv6(T) when is_tuple(T) andalso (size(T) =:= 8) -> -%% make_ipv6(tuple_to_list(T)); - -%% make_ipv6([_, _, _, _, _, _, _, _] = IPV6) -> -%% lists:flatten(io_lib:format("~s:~s:~s:~s:~s:~s:~s:~s", IPV6)). - - -%%-------------------------------------------------------------------- -%% Other help functions -create_config(Config, Access, FileName) -> +server_config(http_basic, Config) -> + basic_conf() ++ server_config(http, Config); +server_config(https_basic, Config) -> + basic_conf() ++ server_config(https, Config); +server_config(http_limit, Config) -> + [{max_clients, 1}] ++ server_config(http, Config); +server_config(https_limit, Config) -> + [{max_clients, 1}] ++ server_config(https, Config); +server_config(http_basic_auth, Config) -> ServerRoot = ?config(server_root, Config), - TcTopDir = ?config(tc_top_dir, Config), - Port = ?config(port, Config), - Type = ?config(sock_type, Config), - Host = ?config(host, Config), - Mods = io_lib:format("~p", [httpd_mod]), - Funcs = io_lib:format("~p", [ssl_password_cb]), - MaxHdrSz = io_lib:format("~p", [256]), - MaxHdrAct = io_lib:format("~p", [close]), - - io:format(user, - "create_config -> " - "~n ServerRoot: ~p" - "~n TcTopDir: ~p" - "~n Type: ~p" - "~n Port: ~p" - "~n Host: ~p" - "~n", [ServerRoot, TcTopDir, Type, Port, Host]), - - SSL = - if - (Type =:= ssl) orelse - (Type =:= essl) -> - [cline(["SSLCertificateFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLCertificateKeyFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLCACertificateFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLPasswordCallbackModule ", Mods]), - cline(["SSLPasswordCallbackFunction ", Funcs]), - cline(["SSLVerifyClient 0"]), - cline(["SSLVerifyDepth 1"])]; - true -> - [] - end, - ModOrder = - case Access of - mod_htaccess -> - "Modules mod_alias mod_htaccess mod_auth " - "mod_security " - "mod_responsecontrol mod_trace mod_esi " - "mod_actions mod_cgi mod_include mod_dir " - "mod_range mod_get " - "mod_head mod_log mod_disk_log"; - _ -> - "Modules mod_alias mod_auth mod_security " - "mod_responsecontrol mod_trace mod_esi " - "mod_actions mod_cgi mod_include mod_dir " - "mod_range mod_get " - "mod_head mod_log mod_disk_log" - end, - - %% The test suite currently does not handle an explicit BindAddress. - %% They assume any has been used, that is Addr is always set to undefined! - - %% {ok, Hostname} = inet:gethostname(), - %% {ok, Addr} = inet:getaddr(Hostname, inet6), - %% AddrStr = make_ipv6(Addr), - %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])), - - BindAddress = "*|inet", - %% BindAddress = "*", - - HttpConfig = [ - cline(["Port ", integer_to_list(Port)]), - cline(["ServerName ", Host]), - cline(["SocketType ", atom_to_list(Type)]), - cline([ModOrder]), - %% cline(["LogFormat ", "erlang"]), - cline(["ServerAdmin [email protected]"]), - cline(["BindAddress ", BindAddress]), - cline(["ServerRoot ", ServerRoot]), - cline(["ErrorLog ", TcTopDir, - "/logs/error_log_", integer_to_list(Port)]), - cline(["TransferLog ", TcTopDir, - "/logs/access_log_", integer_to_list(Port)]), - cline(["SecurityLog ", TcTopDir, - "/logs/security_log_", integer_to_list(Port)]), - cline(["ErrorDiskLog ", TcTopDir, - "/logs/error_disk_log_", integer_to_list(Port)]), - cline(["ErrorDiskLogSize ", "190000 ", "11"]), - cline(["TransferDiskLog ", TcTopDir, - "/logs/access_disk_log_", integer_to_list(Port)]), - cline(["TransferDiskLogSize ", "200000 ", "10"]), - cline(["SecurityDiskLog ", TcTopDir, - "/logs/security_disk_log_", integer_to_list(Port)]), - cline(["SecurityDiskLogSize ", "210000 ", "9"]), - cline(["MaxClients 10"]), - cline(["MaxHeaderSize ", MaxHdrSz]), - cline(["MaxHeaderAction ", MaxHdrAct]), - cline(["DocumentRoot ", - filename:join(ServerRoot, "htdocs")]), - cline(["DirectoryIndex ", "index.html ", "welcome.html"]), - cline(["DefaultType ", "text/plain"]), - SSL, - mod_alias_config(ServerRoot), - - config_directory(filename:join([ServerRoot,"htdocs", - "open"]), - "Open Area", - filename:join(ServerRoot, "auth/passwd"), - filename:join(ServerRoot, "auth/group"), - plain, - "user one Aladdin", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join([ServerRoot,"htdocs", - "secret"]), - "Secret Area", - filename:join(ServerRoot, "auth/passwd"), - filename:join(ServerRoot, "auth/group"), - plain, - "group group1 group2", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join([ServerRoot,"htdocs", - "secret", - "top_secret"]), - "Top Secret Area", - filename:join(ServerRoot, "auth/passwd"), - filename:join(ServerRoot, "auth/group"), - plain, - "group group3", - filename:join(ServerRoot, "security_data")), - - config_directory(filename:join([ServerRoot,"htdocs", - "dets_open"]), - "Dets Open Area", - filename:join(ServerRoot, "passwd"), - filename:join(ServerRoot, "group"), - dets, - "user one Aladdin", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join([ServerRoot,"htdocs", - "dets_secret"]), - "Dets Secret Area", - filename:join(ServerRoot, "passwd"), - filename:join(ServerRoot, "group"), - dets, - "group group1 group2", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join([ServerRoot,"htdocs", - "dets_secret", - "top_secret"]), - "Dets Top Secret Area", - filename:join(ServerRoot, "passwd"), - filename:join(ServerRoot, "group"), - dets, - "group group3", - filename:join(ServerRoot, "security_data")), - - config_directory(filename:join([ServerRoot,"htdocs", - "mnesia_open"]), - "Mnesia Open Area", - false, - false, - mnesia, - "user one Aladdin", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join([ServerRoot,"htdocs", - "mnesia_secret"]), - "Mnesia Secret Area", - false, - false, - mnesia, - "group group1 group2", - filename:join(ServerRoot, "security_data")), - config_directory(filename:join( - [ServerRoot, "htdocs", "mnesia_secret", - "top_secret"]), - "Mnesia Top Secret Area", - false, - false, - mnesia, - "group group3", - filename:join(ServerRoot, "security_data")) - ], - ConfigFile = filename:join([TcTopDir, FileName]), - {ok, Fd} = file:open(ConfigFile, [write]), - ok = file:write(Fd, lists:flatten(HttpConfig)), - ok = file:close(Fd). - -config_directory(Dir, AuthName, AuthUserFile, AuthGroupFile, AuthDBType, - Require, SF) -> - file:delete(SF), - [ - cline(["<Directory ", Dir, ">"]), - cline(["SecurityDataFile ", SF]), - cline(["SecurityMaxRetries 3"]), - cline(["SecurityFailExpireTime ", integer_to_list(?FAIL_EXPIRE_TIME)]), - cline(["SecurityBlockTime 1"]), - cline(["SecurityAuthTimeout ", integer_to_list(?AUTH_TIMEOUT)]), - cline(["SecurityCallbackModule ", "httpd_mod"]), - cline_if_set("AuthUserFile", AuthUserFile), - cline_if_set("AuthGroupFile", AuthGroupFile), - cline_if_set("AuthName", AuthName), - cline_if_set("AuthDBType", AuthDBType), - cline(["require ", Require]), - cline(["</Directory>\r\n"]) - ]. + auth_conf(ServerRoot) ++ server_config(http, Config); +server_config(https_basic_auth, Config) -> + ServerRoot = ?config(server_root, Config), + auth_conf(ServerRoot) ++ server_config(https, Config); +server_config(http_auth_api, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, plain) ++ server_config(http, Config); +server_config(https_auth_api, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, plain) ++ server_config(https, Config); +server_config(http_auth_api_dets, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, dets) ++ server_config(http, Config); +server_config(https_auth_api_dets, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, dets) ++ server_config(https, Config); +server_config(http_auth_api_mnesia, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, mnesia) ++ server_config(http, Config); +server_config(https_auth_api_mnesia, Config) -> + ServerRoot = ?config(server_root, Config), + auth_api_conf(ServerRoot, mnesia) ++ server_config(https, Config); +server_config(http_htaccess, Config) -> + auth_access_conf() ++ server_config(http, Config); +server_config(https_htaccess, Config) -> + auth_access_conf() ++ server_config(https, Config); +server_config(http_security, Config) -> + ServerRoot = ?config(server_root, Config), + tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(http, Config); +server_config(https_security, Config) -> + ServerRoot = ?config(server_root, Config), + tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(https, Config); -mod_alias_config(Root) -> +server_config(http, Config) -> + ServerRoot = ?config(server_root, Config), + [{port, 0}, + {server_name,"httpd_test"}, + {server_root, ServerRoot}, + {document_root, ?config(doc_root, Config)}, + {bind_address, any}, + {ipfamily, inet}, + {max_header_size, 256}, + {max_header_action, close}, + {directory_index, ["index.html", "welcome.html"]}, + {mime_types, [{"html","text/html"},{"htm","text/html"}, {"shtml","text/html"}, + {"gif", "image/gif"}]}, + {alias, {"/icons/", filename:join(ServerRoot,"icons") ++ "/"}}, + {alias, {"/pics/", filename:join(ServerRoot,"icons") ++ "/"}}, + {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}, + {script_alias, {"/htbin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}, + {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}}, + {eval_script_alias, {"/eval", [httpd_example, io]}} + ]; + +server_config(https, Config) -> + PrivDir = ?config(priv_dir, Config), + [{socket_type, {essl, + [{cacertfile, + filename:join(PrivDir, "public_key_cacert.pem")}, + {certfile, + filename:join(PrivDir, "public_key_cert.pem")}, + {keyfile, + filename:join(PrivDir, "public_key_cert_key.pem")} + ]}}] ++ server_config(http, Config). + +init_httpd(Group, Config0) -> + Config1 = proplists:delete(port, Config0), + Config = proplists:delete(server_pid, Config1), + {Pid, Port} = server_start(Group, server_config(Group, Config)), + [{server_pid, Pid}, {port, Port} | Config]. + +http_request(Request, "HTTP/1.1" = Version, Host, {Headers, Body}) -> + Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n" ++ Headers ++ "\r\n" ++ Body; +http_request(Request, Version, _, {Headers, Body}) -> + Request ++ Version ++ "\r\n" ++ Headers ++ "\r\n" ++ Body. + +http_request(Request, "HTTP/1.1" = Version, Host) -> + Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n\r\n"; +http_request(Request, Version, _) -> + Request ++ Version ++ "\r\n\r\n". + +auth_request(Path, User, Passwd, "HTTP/1.1" = Version, Host) -> + "GET " ++ Path ++ " " ++ Version ++ "\r\nhost:" ++ Host ++ + "\r\nAuthorization: Basic " ++ + base64:encode_to_string(User++":"++Passwd) ++ + "\r\n\r\n"; +auth_request(Path, User, Passwd, Version, _Host) -> + "GET " ++ Path ++ " " ++ Version ++ + "\r\nAuthorization: Basic " ++ + base64:encode_to_string(User++":"++Passwd) ++ + "\r\n\r\n". + +http_request_missing_CR(Request, "HTTP/1.1" = Version, Host) -> + Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n\r\n\n"; +http_request_missing_CR(Request, Version, _) -> + Request ++ Version ++ "\r\n\n". + +head_status("HTTP/0.9") -> + 501; %% Not implemented in HTTP/0.9 +head_status(_) -> + 200. + +basic_conf() -> + [{modules, [mod_alias, mod_range, mod_responsecontrol, + mod_trace, mod_esi, mod_cgi, mod_dir, mod_get, mod_head]}]. + +auth_access_conf() -> + [{modules, [mod_alias, mod_htaccess, mod_dir, mod_get, mod_head]}, + {access_files, [".htaccess"]}]. + +auth_conf(Root) -> + [{modules, [mod_alias, mod_auth, mod_dir, mod_get, mod_head]}, + {directory, {filename:join(Root, "htdocs/open"), + [{auth_type, plain}, + {auth_name, "Open Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_user, ["one", "Aladdin"]}]}}, + {directory, {filename:join(Root, "htdocs/secret"), + [{auth_type, plain}, + {auth_name, "Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group1", "group2"]}]}}, + {directory, {filename:join(Root, "htdocs/secret/top_secret"), + [{auth_type, plain}, + {auth_name, "Top Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group3"]}]}}]. + +auth_api_conf(Root, plain) -> + [{modules, [mod_alias, mod_auth, mod_dir, mod_get, mod_head]}, + {directory, {filename:join(Root, "htdocs/open"), + [{auth_type, plain}, + {auth_name, "Open Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_user, ["one", "Aladdin"]}]}}, + {directory, {filename:join(Root, "htdocs/secret"), + [{auth_type, plain}, + {auth_name, "Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group1", "group2"]}]}}, + {directory, {filename:join(Root, "htdocs/secret/top_secret"), + [{auth_type, plain}, + {auth_name, "Top Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group3"]}]}}]; + +auth_api_conf(Root, dets) -> [ - cline(["Alias /icons/ ", filename:join(Root,"icons"), "/"]), - cline(["Alias /pics/ ", filename:join(Root, "icons"), "/"]), - cline(["ScriptAlias /cgi-bin/ ", filename:join(Root, "cgi-bin"), "/"]), - cline(["ScriptAlias /htbin/ ", filename:join(Root, "cgi-bin"), "/"]), - cline(["ErlScriptAlias /cgi-bin/erl httpd_example io"]), - cline(["EvalScriptAlias /eval httpd_example io"]) + {modules, [mod_alias, mod_auth, mod_dir, mod_get, mod_head]}, + {directory, {filename:join(Root, "htdocs/dets_open"), + [{auth_type, dets}, + {auth_name, "Dets Open Area"}, + {auth_user_file, filename:join(Root, "passwd")}, + {auth_group_file, filename:join(Root, "group")}, + {require_user, ["one", "Aladdin"]}]}}, + {directory, {filename:join(Root, "htdocs/dets_secret"), + [{auth_type, dets}, + {auth_name, "Dests Secret Area"}, + {auth_user_file, filename:join(Root, "passwd")}, + {auth_group_file, filename:join(Root, "group")}, + {require_group, ["group1", "group2"]}]}}, + {directory, {filename:join(Root, "htdocs/dets_secret/top_secret"), + [{auth_type, dets}, + {auth_name, "Dets Top Secret Area"}, + {auth_user_file, filename:join(Root, "passwd")}, + {auth_group_file, filename:join(Root, "group")}, + {require_group, ["group3"]}]}} + ]; + +auth_api_conf(Root, mnesia) -> + [{modules, [mod_alias, mod_auth, mod_dir, mod_get, mod_head]}, + {directory, {filename:join(Root, "htdocs/mnesia_open"), + [{auth_type, mnesia}, + {auth_name, "Mnesia Open Area"}, + {require_user, ["one", "Aladdin"]}]}}, + {directory, {filename:join(Root, "htdocs/mnesia_secret"), + [{auth_type, mnesia}, + {auth_name, "Mnesia Secret Area"}, + {require_group, ["group1", "group2"]}]}}, + {directory, {filename:join(Root, "htdocs/mnesia_secret/top_secret"), + [{auth_type, mnesia}, + {auth_name, "Mnesia Top Secret Area"}, + {require_group, ["group3"]}]}}]. + +security_conf(Root) -> + SecFile = filename:join(Root, "security_data"), + Open = filename:join(Root, "htdocs/open"), + Secret = filename:join(Root, "htdocs/secret"), + TopSecret = filename:join(Root, "htdocs/secret/top_secret"), + + [{modules, [mod_alias, mod_auth, mod_security, mod_dir, mod_get, mod_head]}, + {security_directory, {Open, + [{auth_name, "Open Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_user, ["one", "Aladdin"]} | + mod_security_conf(SecFile, Open)]}}, + {security_directory, {Secret, + [{auth_name, "Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group1", "group2"]} | + mod_security_conf(SecFile, Secret)]}}, + {security_directory, {TopSecret, + [{auth_name, "Top Secret Area"}, + {auth_user_file, filename:join(Root, "auth/passwd")}, + {auth_group_file, filename:join(Root, "auth/group")}, + {require_group, ["group3"]} | + mod_security_conf(SecFile, TopSecret)]}}]. + +mod_security_conf(SecFile, Dir) -> + [{data_file, SecFile}, + {max_retries, 3}, + {fail_expire_time, ?FAIL_EXPIRE_TIME}, + {block_time, 1}, + {auth_timeout, ?AUTH_TIMEOUT}, + {callback_module, ?MODULE}, + {path, Dir} %% This is should not be needed, but is atm, awful design! ]. + -cline(List) -> - lists:flatten([List, "\r\n"]). - -cline_if_set(_, false) -> - []; -cline_if_set(Name, Var) when is_list(Var) -> - cline([Name, " ", Var]); -cline_if_set(Name, Var) when is_atom(Var) -> - cline([Name, " ", atom_to_list(Var)]). - -getaddr() -> - {ok,HostName} = inet:gethostname(), - {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet), - lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])). +http_status(Request, Config, Expected) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request(Request, Version, Host), + Expected ++ [{version, Version}]). + +http_status(Request, HeadersAndBody, Config, Expected) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request(Request, Version, Host, HeadersAndBody), + Expected ++ [{version, Version}]). + +auth_status(AuthRequest, Config, Expected) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Type = ?config(type, Config), + httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + AuthRequest, + Expected ++ [{version, Version}]). + +basic_auth_requiered(Config) -> + ok = http_status("GET /open/ ", Config, [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + ok = http_status("GET /secret/ ", Config, [{statuscode, 401}, + {header, "WWW-Authenticate"}]), + ok = http_status("GET /secret/top_secret/ ", Config, [{statuscode, 401}, + {header, "WWW-Authenticate"}]). start_mnesia(Node) -> case rpc:call(Node, ?MODULE, cleanup_mnesia, []) of ok -> ok; Other -> - tsf({failed_to_cleanup_mnesia, Other}) + ct:fail({failed_to_cleanup_mnesia, Other}) end, case rpc:call(Node, ?MODULE, setup_mnesia, []) of {atomic, ok} -> ok; Other2 -> - tsf({failed_to_setup_mnesia, Other2}) + ct:fail({failed_to_setup_mnesia, Other2}) end, ok. @@ -2260,6 +1537,28 @@ cleanup_mnesia() -> mnesia:delete_schema([node()]), ok. +transport_opts(ssl, Config) -> + PrivDir = ?config(priv_dir, Config), + [{cacertfile, filename:join(PrivDir, "public_key_cacert.pem")}]; +transport_opts(_, _) -> + []. + + +%%% mod_range +create_range_data(Path) -> + PathAndFileName=filename:join([Path,"range.txt"]), + case file:read_file(PathAndFileName) of + {error, enoent} -> + file:write_file(PathAndFileName,list_to_binary(["12345678901234567890", + "12345678901234567890", + "12345678901234567890", + "12345678901234567890", + "12345678901234567890"])); + _ -> + ok + end. + +%%% mod_htaccess create_htaccess_data(Path, IpAddress)-> create_htaccess_dirs(Path), @@ -2356,99 +1655,140 @@ remove_htaccess(Path)-> file:delete(filename:join([Path,"ht","groups.file"])), remove_htaccess_dirs(Path). +dos_hostname(Type, Port, Host, Node, Version, Max) -> + TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + dos_hostname_request("", Version), + [{statuscode, 200}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + dos_hostname_request("dummy-host.ericsson.se", Version), + [{statuscode, 200}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + dos_hostname_request(TooLongHeader, Version), + [{statuscode, dos_code(Version)}, + {version, Version}]). +dos_hostname_request(Host, Version) -> + dos_http_request("GET / ", Version, Host). + +dos_http_request(Request, "HTTP/1.1" = Version, Host) -> + http_request(Request, Version, Host); +dos_http_request(Request, Version, Host) -> + Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n\r\n". + +dos_code("HTTP/1.0") -> + 403; %% 413 not defined in HTTP/1.0 +dos_code(_) -> + 413. + +update_password(Node, ServerRoot, _Address, Port, AuthPrefix, Dir, Old, New)-> + Directory = filename:join([ServerRoot, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, update_password, + [undefined, Port, Directory, Old, New, New]). + +add_user(Node, Root, Port, AuthPrefix, Dir, User, Password, UserData) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, add_user, + [User, Password, UserData, Addr, Port, Directory]). + + +delete_user(Node, Root, _Host, Port, AuthPrefix, Dir, User) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, delete_user, [User, Addr, Port, Directory]). +remove_users(Node, ServerRoot, Host, Port, AuthPrefix, Dir) -> + %% List users, delete them, and make sure they are gone. + case list_users(Node, ServerRoot, Host, Port, AuthPrefix, Dir) of + {ok, Users} -> + lists:foreach(fun(User) -> + delete_user(Node, ServerRoot, Host, + Port, AuthPrefix, Dir, User) + end, + Users), + {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthPrefix, Dir); + _ -> + ok + end. -dos_hostname_poll(Type, Host, Port, Node, Hosts) -> - [dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) - || {Host1,Code} <- Hosts]. +list_users(Node, Root, _Host, Port, AuthPrefix, Dir) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, list_users, [Addr, Port, Directory]). + +remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, Dir) -> + {ok, Groups} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, Dir), + lists:foreach(fun(Group) -> + delete_group(Node, Group, Port, ServerRoot, AuthPrefix, Dir) + end, + Groups), + {ok, []} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, Dir). + +delete_group(Node, Group, Port, Root, AuthPrefix, Dir) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, delete_group, [Group, Addr, Port, Directory]). + +list_groups(Node, Root, _, Port, AuthPrefix, Dir) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, list_groups, [Addr, Port, Directory]). + +add_group_member(Node, Root, Port, AuthPrefix, Dir, User, Group) -> + Addr = undefined, + Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]), + rpc:call(Node, mod_auth, add_group_member, [Group, User, Addr, Port, + Directory]). +getaddr() -> + {ok,HostName} = inet:gethostname(), + {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet), + lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])). -dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) -> - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - dos_hostname_request(Host1), - [{statuscode, Code}, - {version, "HTTP/1.0"}]). - -dos_hostname_request(Host) -> - "GET / HTTP/1.0\r\n" ++ Host ++ "\r\n\r\n". +receive_security_event(Event, Node, Port) -> + receive + Event -> + ok; + {'EXIT', _, _} -> + receive_security_event(Event, Node, Port) + after 5000 -> + %% Flush the message queue, to see if we got something... + inets_test_lib:flush() + end. -get_nof_clients(Mode, Load) -> - get_nof_clients(test_server:os_type(), Mode, Load). +list_blocked_users(Node,Port) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, list_blocked_users, [Addr,Port]). -get_nof_clients(_, ip_comm, light) -> 5; -get_nof_clients(_, ssl, light) -> 2; -get_nof_clients(_, ip_comm, medium) -> 10; -get_nof_clients(_, ssl, medium) -> 4; -get_nof_clients(_, ip_comm, heavy) -> 20; -get_nof_clients(_, ssl, heavy) -> 6. +list_blocked_users(Node,Port,Dir) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, list_blocked_users, [Addr,Port,Dir]). -%% Make a file 100 bytes long containing 012...9*10 -create_range_data(Path) -> - PathAndFileName=filename:join([Path,"range.txt"]), - file:write_file(PathAndFileName,list_to_binary(["12345678901234567890", - "12345678901234567890", - "12345678901234567890", - "12345678901234567890", - "12345678901234567890"])). +block_user(Node,User,Port,Dir,Sec) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, block_user, [User, Addr, Port, Dir, Sec]). -create_ipv6_config(Config, FileName, Ipv6Address) -> - ServerRoot = ?config(server_root, Config), - TcTopDir = ?config(tc_top_dir, Config), - Port = ?config(port, Config), - SockType = ?config(sock_type, Config), - Mods = io_lib:format("~p", [httpd_mod]), - Funcs = io_lib:format("~p", [ssl_password_cb]), - Host = ?config(ipv6_host, Config), - - MaxHdrSz = io_lib:format("~p", [256]), - MaxHdrAct = io_lib:format("~p", [close]), - - Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi" - " mod_include mod_dir mod_get mod_head" - " mod_log mod_disk_log mod_trace", - - SSL = - if - (SockType =:= ssl) orelse - (SockType =:= essl) -> - [cline(["SSLCertificateFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLCertificateKeyFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLCACertificateFile ", - filename:join(ServerRoot, "ssl/ssl_server.pem")]), - cline(["SSLPasswordCallbackModule ", Mods]), - cline(["SSLPasswordCallbackFunction ", Funcs]), - cline(["SSLVerifyClient 0"]), - cline(["SSLVerifyDepth 1"])]; - true -> - [] - end, +unblock_user(Node,User,Port,Dir) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, unblock_user, [User, Addr, Port, Dir]). + +list_auth_users(Node,Port) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, list_auth_users, [Addr,Port]). - BindAddress = "[" ++ Ipv6Address ++"]|inet6", - - HttpConfig = - [cline(["BindAddress ", BindAddress]), - cline(["Port ", integer_to_list(Port)]), - cline(["ServerName ", Host]), - cline(["SocketType ", atom_to_list(SockType)]), - cline([Mod_order]), - cline(["ServerRoot ", ServerRoot]), - cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]), - cline(["MaxHeaderSize ",MaxHdrSz]), - cline(["MaxHeaderAction ",MaxHdrAct]), - cline(["DirectoryIndex ", "index.html "]), - cline(["DefaultType ", "text/plain"]), - SSL], - ConfigFile = filename:join([TcTopDir,FileName]), - {ok, Fd} = file:open(ConfigFile, [write]), - ok = file:write(Fd, lists:flatten(HttpConfig)), - ok = file:close(Fd). - - -tsp(F) -> - inets_test_lib:tsp("[~w]" ++ F, [?MODULE]). -tsp(F, A) -> - inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]). - -tsf(Reason) -> - inets_test_lib:tsf(Reason). +list_auth_users(Node,Port,Dir) -> + Addr = undefined, % Assumed to be on the same host + rpc:call(Node, mod_security, list_auth_users, [Addr,Port,Dir]). + +event(What, Port, Dir, Data) -> + Msg = {event, What, Port, Dir, Data}, + case global:whereis_name(mod_security_test) of + undefined -> + ok; + _Pid -> + global:send(mod_security_test, Msg) + end. diff --git a/lib/inets/test/httpd_all.erl b/lib/inets/test/httpd_all.erl new file mode 100644 index 0000000000..9be02e3fd8 --- /dev/null +++ b/lib/inets/test/httpd_all.erl @@ -0,0 +1,240 @@ +alias(Version, Type, Port, Host, Node) -> + Opts = [], + ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, + "GET /pics/icon.sheet.gif " + ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {header, "Content-Type","image/gif"}, + {header, "Server"}, + {header, "Date"}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, + "GET / " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {header, "Content-Type","text/html"}, + {header, "Server"}, + {header, "Date"}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, + "GET /misc/ " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {header, "Content-Type","text/html"}, + {header, "Server"}, + {header, "Date"}, + {version, Version}]), + + %% Check redirection if trailing slash is missing. + ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node, + "GET /misc "++ Version ++ "\r\n\r\n", + [{statuscode, 301}, + {header, "Location"}, + {header, "Content-Type","text/html"}, + {version, Version}]). + + +head(Version, Type, Port, Host, Node) -> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "HEAD /index.html " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]). + + +get(Version, Type, Port, Host, Node) -> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /index.html " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /fsize.shtml " ++ Version ++ "\r\nHost:" + ++ Host ++ "\r\n\r\n", + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date"}, + {header, "Server"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /secret/dummy.html " + ++ Version ++ "\r\n\r\n", + [{statuscode, 401}, + {header, "WWW-Authenticate"}, + {version, Version}]). + +esi(Version, Type, Port, Host, Node) -> + %% Check "ErlScriptAlias" and "EvalScriptAlias" directives + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /eval?httpd_example:print(\"Hi!\") " + ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /eval?not_allowed:print(\"Hi!\") " + ++ Version ++ "\r\n\r\n", + [{statuscode, 403}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /eval?httpd_example:undef(\"Hi!\") " + ++ Version ++ "\r\n\r\n", + [{statuscode, 500}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example " + ++ Version ++ "\r\n\r\n", + [{statuscode, 400}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example:get " + ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example:" + "get?input=4711" + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example:" + "post " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/not_allowed:post " + ++ Version ++ "\r\n\r\n", + [{statuscode, 403}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example:undef " + ++ Version ++ "\r\n\r\n", + [{statuscode, 404}, + {version, Version}]), + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example/yahoo " + ++ Version ++ "\r\n\r\n", + [{statuscode, 302}, + {version, Version}]), + %% Check "ErlScriptNoCache" directive (default: false) + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example:get " + ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {no_header, "cache-control"}, + {version, "HTTP/1.0"}]). + +cgi(Version, Type, Port, Host, Node) -> + {Script, Script2, Script3} = + case test_server:os_type() of + {win32, _} -> + {"printenv.bat", "printenv.sh", "cgi_echo.exe"}; + _ -> + {"printenv.sh", "printenv.bat", "cgi_echo"} + end, + + %% The length (> 100) is intentional + ok = httpd_test_lib: + verify_request(Type, Host, Port, Node, + "POST /cgi-bin/" ++ Script3 ++ + Version ++ " \r\n" + "Content-Length:100 \r\n\r\n " + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + " \r\n\r\n", + [{statuscode, 200}, + {version, Version}, + {header, "content-type", "text/plain"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/"++ Script ++ + " " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/not_there " ++ + Version ++ "\r\n\r\n", + [{statuscode, 404},{statuscode, 500}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/"++ Script ++ + "?Nisse:kkk?sss/lll " ++ Version ++ "\r\n\r\n", + [{statuscode, 200}, + {version, Version}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "POST /cgi-bin/"++ Script ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /htbin/"++ Script ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /htbin/not_there " + "HTTP/1.0\r\n\r\n", + [{statuscode, 404},{statuscode, 500}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /htbin/"++ Script ++ + "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "POST /htbin/"++ Script ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "POST /htbin/"++ Script ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + %% Execute an existing, but bad CGI script.. + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "POST /htbin/"++ Script2 ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 404}, + {version, "HTTP/1.0"}]), + + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "POST /cgi-bin/"++ Script2 ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 404}, + {version, "HTTP/1.0"}]), + + %% Check "ScriptNoCache" directive (default: false) + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/" ++ Script ++ + " HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {no_header, "cache-control"}, + {version, "HTTP/1.0"}]). + diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl index 2d06f3e70c..fbe65145dc 100644 --- a/lib/inets/test/httpd_basic_SUITE.erl +++ b/lib/inets/test/httpd_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -65,7 +65,8 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) -> tsp("init_per_suite -> entry with" "~n Config: ~p", [Config]), - ok = inets:start(), + inets_test_lib:stop_apps([inets]), + inets_test_lib:start_apps([inets]), PrivDir = ?config(priv_dir, Config), DataDir = ?config(data_dir, Config), diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl index ac1bf43ff5..9790623b6f 100644 --- a/lib/inets/test/httpd_block.erl +++ b/lib/inets/test/httpd_block.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,8 +19,7 @@ %% -module(httpd_block). --include("test_server.hrl"). --include("test_server_line.hrl"). +-include_lib("common_test/include/ct.hrl"). %% General testcases bodies called from httpd_SUITE -export([block_disturbing_idle/4, block_non_disturbing_idle/4, @@ -88,7 +87,7 @@ block_503(Type, Port, Host, Node) -> block_disturbing_active(Type, Port, Host, Node) -> process_flag(trap_exit, true), Pid = long_poll(Type, Host, Port, Node, 200, 60000), - test_server:sleep(15000), + ct:sleep(15000), block_server(Node, Host, Port), await_suite_failed_process_exit(Pid, "poller", 60000, connection_closed), @@ -100,7 +99,7 @@ block_disturbing_active(Type, Port, Host, Node) -> block_non_disturbing_active(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 60000), - test_server:sleep(15000), + ct:sleep(15000), ok = block_nd_server(Node, Host, Port), await_normal_process_exit(Poller, "poller", 60000), blocked = get_admin_state(Node, Host, Port), @@ -111,9 +110,8 @@ block_non_disturbing_active(Type, Port, Host, Node) -> block_disturbing_active_timeout_not_released(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 60000), - test_server:sleep(15000), - Blocker = blocker(Node, Host, Port, 50000), - await_normal_process_exit(Blocker, "blocker", 50000), + ct:sleep(15000), + ok = httpd_block(undefined, Port, disturbing, 50000), await_normal_process_exit(Poller, "poller", 30000), blocked = get_admin_state(Node, Host, Port), process_flag(trap_exit, false), @@ -123,9 +121,8 @@ block_disturbing_active_timeout_not_released(Type, Port, Host, Node) -> block_disturbing_active_timeout_released(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 40000), - test_server:sleep(5000), - Blocker = blocker(Node, Host, Port, 10000), - await_normal_process_exit(Blocker, "blocker", 15000), + ct:sleep(5000), + ok = httpd_block(undefined, Port, disturbing, 10000), await_suite_failed_process_exit(Poller, "poller", 40000, connection_closed), blocked = get_admin_state(Node, Host, Port), @@ -146,7 +143,7 @@ block_non_disturbing_active_timeout_not_released(Type, Port, Host, Node) -> block_non_disturbing_active_timeout_released(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 45000), - test_server:sleep(5000), + ct:sleep(5000), Blocker = blocker_nd(Node, Host, Port ,10000, {error,timeout}), await_normal_process_exit(Blocker, "blocker", 15000), await_normal_process_exit(Poller, "poller", 50000), @@ -157,9 +154,9 @@ block_non_disturbing_active_timeout_released(Type, Port, Host, Node) -> disturbing_blocker_dies(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 60000), - test_server:sleep(5000), + ct:sleep(5000), Blocker = blocker(Node, Host, Port, 10000), - test_server:sleep(5000), + ct:sleep(5000), exit(Blocker,simulate_blocker_crash), await_normal_process_exit(Poller, "poller", 60000), unblocked = get_admin_state(Node, Host, Port), @@ -170,9 +167,9 @@ disturbing_blocker_dies(Type, Port, Host, Node) -> non_disturbing_blocker_dies(Type, Port, Host, Node) -> process_flag(trap_exit, true), Poller = long_poll(Type, Host, Port, Node, 200, 60000), - test_server:sleep(5000), + ct:sleep(5000), Blocker = blocker_nd(Node, Host, Port, 10000, ok), - test_server:sleep(5000), + ct:sleep(5000), exit(Blocker, simulate_blocker_crash), await_normal_process_exit(Poller, "poller", 60000), unblocked = get_admin_state(Node, Host, Port), @@ -297,9 +294,12 @@ httpd_restart(Addr, Port) -> make_name(Addr, Port) -> httpd_util:make_name("httpd", Addr, Port). -get_admin_state(Node, _Host, Port) -> - Addr = undefined, - rpc:call(Node, httpd, get_admin_state, [Addr, Port]). +get_admin_state(_, _Host, Port) -> + Name = make_name(undefined, Port), + {status, _, _, StatusInfo} = sys:get_status(whereis(Name)), + [_, _,_, _, Prop] = StatusInfo, + State = state(Prop), + element(6, State). validate_admin_state(Node, Host, Port, Expect) -> io:format("try validating server admin state: ~p~n", [Expect]), @@ -323,15 +323,15 @@ await_normal_process_exit(Pid, Name, Timeout) -> io_lib:format("expected normal exit, " "unexpected exit of ~s process: ~p", [Name, Reason])), - test_server:fail(Err) + ct:fail(Err) after Timeout -> - test_server:fail("timeout while waiting for " ++ Name) + ct:fail("timeout while waiting for " ++ Name) end. await_suite_failed_process_exit(Pid, Name, Timeout, Why) -> receive - {'EXIT', Pid, {suite_failed, Why}} -> + {'EXIT', Pid, {test_failed, Why}} -> ok; {'EXIT', Pid, Reason} -> Err = @@ -339,9 +339,9 @@ await_suite_failed_process_exit(Pid, Name, Timeout, Why) -> io_lib:format("expected connection_closed, " "unexpected exit of ~s process: ~p", [Name, Reason])), - test_server:fail(Err) + ct:fail(Err) after Timeout -> - test_server:fail("timeout while waiting for " ++ Name) + ct:fail("timeout while waiting for " ++ Name) end. long_poll(Type, Host, Port, Node, StatusCode, Timeout) -> @@ -359,10 +359,13 @@ do_long_poll(Type, Host, Port, Node, StatusCode, Timeout) -> ok -> exit(normal); Reason -> - test_server:fail(Reason) + exit({test_failed, Reason}) end. - - - +state([{data,[{"State", State}]} | _]) -> + State; +state([{data,[{"StateData", State}]} | _]) -> + State; +state([_ | Rest]) -> + state(Rest). diff --git a/lib/inets/test/httpd_mod_SUITE.erl b/lib/inets/test/httpd_mod_SUITE.erl new file mode 100644 index 0000000000..d23cd22670 --- /dev/null +++ b/lib/inets/test/httpd_mod_SUITE.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013-2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% + +%% +%% ct:run("../inets_test", httpd_mod_SUITE). +-module(httpd_mod_SUITE). + +-include_lib("kernel/include/file.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include("inets_test_lib.hrl"). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + {group, http}, + {group, https} + ]. + +groups() -> + [ + {http, [], all_version_groups()}, + {https, [], all_version_groups()} + {http_1_1, [], []}, + {http_1_0, [], []}, + {http_0_9, [], []}, + {mod_alias, [], []}, + {mod_actions, [], []}, + {mod_security, [], []}, + {mod_auth, [], []}, + {mod_htaccess, [], []}, + {mod_cgi, [], []}, + {mod_esi, [], []}, + {mod_head, [], []}, + {configure, [], []} + ]. + +all_version_groups ()-> + [ + {group, mod_alias}, + {group, mod_actions}, + {group, mod_security}, + {group, mod_auth}, + {group, mod_htaccess}, + {group, mod_cgi}, + {group, mod_esi}, + {group, mod_head} + ]. + +%%------------------------------------------------------------------------- +%% Test cases starts here. +%%------------------------------------------------------------------------- diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl index 3e82324a30..ed466fd727 100644 --- a/lib/inets/test/httpd_test_lib.erl +++ b/lib/inets/test/httpd_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -92,16 +92,6 @@ verify_request(SocketType, Host, Port, Node, RequestStr, Options, TimeOut) verify_request(SocketType, Host, Port, [], Node, RequestStr, Options, TimeOut). verify_request(SocketType, Host, Port, TranspOpts0, Node, RequestStr, Options, TimeOut) -> - tsp("verify_request -> entry with" - "~n SocketType: ~p" - "~n Host: ~p" - "~n Port: ~p" - "~n TranspOpts: ~p" - "~n Node: ~p" - "~n Options: ~p" - "~n TimeOut: ~p", - [SocketType, Host, Port, TranspOpts0, Node, Options, TimeOut]), - %% For now, until we modernize the httpd tests TranspOpts = case lists:member(inet6, TranspOpts0) of @@ -113,10 +103,7 @@ verify_request(SocketType, Host, Port, TranspOpts0, Node, RequestStr, Options, T try inets_test_lib:connect_bin(SocketType, Host, Port, TranspOpts) of {ok, Socket} -> - tsp("verify_request -> connected - now send message"), SendRes = inets_test_lib:send(SocketType, Socket, RequestStr), - tsp("verify_request -> send result: " - "~n ~p", [SendRes]), State = case inets_regexp:match(RequestStr, "printenv") of nomatch -> #state{}; @@ -127,37 +114,24 @@ verify_request(SocketType, Host, Port, TranspOpts0, Node, RequestStr, Options, T case request(State#state{request = RequestStr, socket = Socket}, TimeOut) of {error, Reason} -> - tsp("verify_request -> request failed: " - "~n Reason: ~p", [Reason]), {error, Reason}; NewState -> - tsp("verify_request -> validate reply: " - "~n NewState: ~p", [NewState]), ValidateResult = validate(RequestStr, NewState, Options, Node, Port), - tsp("verify_request -> validation result: " - "~n ~p", [ValidateResult]), inets_test_lib:close(SocketType, Socket), ValidateResult end; ConnectError -> - tsp("verify_request -> connect error: " - "~n ~p" - "~n", [ConnectError]), - tsf({connect_error, ConnectError, - [SocketType, Host, Port, TranspOpts]}) + ct:fail({connect_error, ConnectError, + [SocketType, Host, Port, TranspOpts]}) catch T:E -> - tsp("verify_request -> connect failed: " - "~n E: ~p" - "~n T: ~p" - "~n", [E, T]), - tsf({connect_failure, - [{type, T}, - {error, E}, - {stacktrace, erlang:get_stacktrace()}, - {args, [SocketType, Host, Port, TranspOpts]}]}) + ct:fail({connect_failure, + [{type, T}, + {error, E}, + {stacktrace, erlang:get_stacktrace()}, + {args, [SocketType, Host, Port, TranspOpts]}]}) end. request(#state{mfa = {Module, Function, Args}, @@ -166,10 +140,6 @@ request(#state{mfa = {Module, Function, Args}, HeadRequest = lists:sublist(RequestStr, 1, 4), receive {tcp, Socket, Data} -> - io:format("~p ~w[~w]request -> received (tcp) data" - "~n Data: ~p" - "~n", [self(), ?MODULE, ?LINE, Data]), - print(tcp, Data, State), case Module:Function([Data | Args]) of {ok, Parsed} -> handle_http_msg(Parsed, State); @@ -179,22 +149,12 @@ request(#state{mfa = {Module, Function, Args}, request(State#state{mfa = NewMFA}, TimeOut) end; {tcp_closed, Socket} when Function =:= whole_body -> - io:format("~p ~w[~w]request -> " - "received (tcp) closed when whole_body" - "~n", [self(), ?MODULE, ?LINE]), - print(tcp, "closed", State), State#state{body = hd(Args)}; {tcp_closed, Socket} -> - io:format("~p ~w[~w]request -> received (tcp) closed" - "~n", [self(), ?MODULE, ?LINE]), - test_server:fail(connection_closed); + exit({test_failed, connection_closed}); {tcp_error, Socket, Reason} -> - io:format("~p ~w[~w]request -> received (tcp) error" - "~n Reason: ~p" - "~n", [self(), ?MODULE, ?LINE, Reason]), - test_server:fail({tcp_error, Reason}); + ct:fail({tcp_error, Reason}); {ssl, Socket, Data} -> - print(ssl, Data, State), case Module:Function([Data | Args]) of {ok, Parsed} -> handle_http_msg(Parsed, State); @@ -204,28 +164,19 @@ request(#state{mfa = {Module, Function, Args}, request(State#state{mfa = NewMFA}, TimeOut) end; {ssl_closed, Socket} when Function =:= whole_body -> - print(ssl, "closed", State), State#state{body = hd(Args)}; {ssl_closed, Socket} -> - test_server:fail(connection_closed); + exit({test_failed, connection_closed}); {ssl_error, Socket, Reason} -> - test_server:fail({ssl_error, Reason}) + ct:fail({ssl_error, Reason}) after TimeOut -> - io:format("~p ~w[~w]request -> timeout" - "~n", [self(), ?MODULE, ?LINE]), - test_server:fail(connection_timed_out) + ct:pal("~p ~w[~w]request -> timeout" + "~n", [self(), ?MODULE, ?LINE]), + ct:fail(connection_timed_out) end. handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body}, State = #state{request = RequestStr}) -> - io:format("~p ~w[~w]handle_http_msg -> entry with" - "~n Version: ~p" - "~n StatusCode: ~p" - "~n ReasonPharse: ~p" - "~n Headers: ~p" - "~n Body: ~p" - "~n", [self(), ?MODULE, ?LINE, - Version, StatusCode, ReasonPharse, Headers, Body]), case is_expect(RequestStr) of true -> State#state{status_line = {Version, @@ -277,7 +228,7 @@ handle_http_body(Body, State = #state{headers = Headers, request(State#state{mfa = MFA}, 5000) end; false -> - test_server:fail(body_too_big) + ct:fail(body_too_big) end end. @@ -285,11 +236,6 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _}, headers = Headers, body = Body}, Options, N, P) -> - tsp("validate -> entry with" - "~n StatusCode: ~p" - "~n Headers: ~p" - "~n Body: ~p", [StatusCode, Headers, Body]), - check_version(Version, Options), case lists:keysearch(statuscode, 1, Options) of {value, _} -> @@ -311,20 +257,20 @@ check_version(Version, Options) -> {value, {version, Version}} -> ok; {value, {version, Ver}} -> - tsf({wrong_version, [{got, Version}, - {expected, Ver}]}); + ct:fail({wrong_version, [{got, Version}, + {expected, Ver}]}); _ -> - case Version of - "HTTP/1.1" -> - ok; + case Version of + "HTTP/1.1" -> + ok; _ -> - tsf({wrong_version, [{got, Version}, - {expected, "HTTP/1.1"}]}) - end + ct:fail({wrong_version, [{got, Version}, + {expected, "HTTP/1.1"}]}) + end end. check_status_code(StatusCode, [], Options) -> - tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]}); + ct:fail({wrong_status_code, [{got, StatusCode}, {expected, Options}]}); check_status_code(StatusCode, Current = [_ | Rest], Options) -> case lists:keysearch(statuscode, 1, Current) of {value, {statuscode, StatusCode}} -> @@ -332,7 +278,7 @@ check_status_code(StatusCode, Current = [_ | Rest], Options) -> {value, {statuscode, _OtherStatus}} -> check_status_code(StatusCode, Rest, Options); false -> - tsf({wrong_status_code, [{got, StatusCode}, {expected, Options}]}) + ct:fail({wrong_status_code, [{got, StatusCode}, {expected, Options}]}) end. do_validate(_, [], _, _) -> @@ -345,9 +291,9 @@ do_validate(Header, [{header, HeaderField}|Rest], N, P) -> {value, {LowerHeaderField, _Value}} -> ok; false -> - tsf({missing_header_field, LowerHeaderField, Header}); + ct:fail({missing_header_field, LowerHeaderField, Header}); _ -> - tsf({missing_header_field, LowerHeaderField, Header}) + ct:fail({missing_header_field, LowerHeaderField, Header}) end, do_validate(Header, Rest, N, P); do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) -> @@ -356,15 +302,15 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) -> {value, {LowerHeaderField, Value}} -> ok; false -> - tsf({wrong_header_field_value, LowerHeaderField, Header}); + ct:fail({wrong_header_field_value, LowerHeaderField, Header}); _ -> - tsf({wrong_header_field_value, LowerHeaderField, Header}) + ct:fail({wrong_header_field_value, LowerHeaderField, Header}) end, do_validate(Header, Rest, N, P); do_validate(Header,[{no_header, HeaderField}|Rest],N,P) -> case lists:keysearch(HeaderField,1,Header) of {value,_} -> - tsf({wrong_header_field_value, HeaderField, Header}); + ct:fail({wrong_header_field_value, HeaderField, Header}); _ -> ok end, @@ -382,14 +328,14 @@ is_expect(RequestStr) -> %% OTP-5775, content-length check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when (Length =/= 274) -> - tsf(content_length_error); + ct:fail(content_length_error); check_body("GET /cgi-bin/cgi_echo HTTP/1.0\r\n\r\n", 200, "text/plain", _, Body) -> case size(Body) of 100 -> ok; _ -> - tsf(content_length_error) + ct:fail(content_length_error) end; check_body(RequestStr, 200, "text/html", _, Body) -> @@ -404,16 +350,3 @@ check_body(RequestStr, 200, "text/html", _, Body) -> check_body(_, _, _, _,_) -> ok. -print(Proto, Data, #state{print = true}) -> - test_server:format("Received ~p: ~p~n", [Proto, Data]); -print(_, _, #state{print = false}) -> - ok. - - -tsp(F) -> - inets_test_lib:tsp(F). -tsp(F, A) -> - inets_test_lib:tsp(F, A). - -tsf(Reason) -> - inets_test_lib:tsf(Reason). diff --git a/lib/inets/test/inets_appup_test.erl b/lib/inets/test/inets_appup_test.erl index d563b52ae7..a8051c6c85 100644 --- a/lib/inets/test/inets_appup_test.erl +++ b/lib/inets/test/inets_appup_test.erl @@ -23,13 +23,7 @@ -module(inets_appup_test). -compile(export_all). --compile({no_auto_import,[error/1]}). - --include("inets_test_lib.hrl"). - - - % t() -> megaco_test_lib:t(?MODULE). - % t(Case) -> megaco_test_lib:t({?MODULE, Case}). +-include_lib("common_test/include/ct.hrl"). %% Test server callbacks @@ -59,16 +53,9 @@ end_per_group(_GroupName, Config) -> init_per_suite(suite) -> []; init_per_suite(doc) -> []; init_per_suite(Config) when is_list(Config) -> - AppFile = file_name(inets, ".app"), - AppupFile = file_name(inets, ".appup"), - [{app_file, AppFile}, {appup_file, AppupFile}|Config]. + Config. -file_name(App, Ext) -> - LibDir = code:lib_dir(App), - filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]). - - end_per_suite(suite) -> []; end_per_suite(doc) -> []; end_per_suite(Config) when is_list(Config) -> @@ -77,282 +64,7 @@ end_per_suite(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -appup(suite) -> - []; -appup(doc) -> - "perform a simple check of the appup file"; +appup() -> + [{doc, "Perform a simple check of the inets appup file"}]. appup(Config) when is_list(Config) -> - AppupFile = key1search(appup_file, Config), - AppFile = key1search(app_file, Config), - Modules = modules(AppFile), - check_appup(AppupFile, Modules). - -modules(File) -> - case file:consult(File) of - {ok, [{application,inets,Info}]} -> - case lists:keysearch(modules,1,Info) of - {value, {modules, Modules}} -> - Modules; - false -> - fail({bad_appinfo, Info}) - end; - Error -> - fail({bad_appfile, Error}) - end. - - -check_appup(AppupFile, Modules) -> - case file:consult(AppupFile) of - {ok, [{V, UpFrom, DownTo}]} -> -% io:format("~p => " -% "~n ~p" -% "~n ~p" -% "~n", [V, UpFrom, DownTo]), - check_appup(V, UpFrom, DownTo, Modules); - Else -> - fail({bad_appupfile, Else}) - end. - - -check_appup(V, UpFrom, DownTo, Modules) -> - check_version(V), - check_depends(up, UpFrom, Modules), - check_depends(down, DownTo, Modules), - ok. - - -check_depends(_, [], _) -> - ok; -check_depends(UpDown, [Dep|Deps], Modules) -> - check_depend(UpDown, Dep, Modules), - check_depends(UpDown, Deps, Modules). - - -check_depend(UpDown, {V, Instructions}, Modules) -> - check_version(V), - case check_instructions(UpDown, - Instructions, Instructions, [], [], Modules) of - {_Good, []} -> - ok; - {_, Bad} -> - fail({bad_instructions, Bad, UpDown}) - end. - - -check_instructions(_, [], _, Good, Bad, _) -> - {lists:reverse(Good), lists:reverse(Bad)}; -check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) -> - case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of - ok -> - check_instructions(UpDown, Instrs, AllInstr, - [Instr|Good], Bad, Modules); - {error, Reason} -> - check_instructions(UpDown, Instrs, AllInstr, Good, - [{Instr, Reason}|Bad], Modules) - end; -check_instructions(UpDown, Instructions, _, _, _, _) -> - fail({bad_instructions, {UpDown, Instructions}}). - -%% A new module is added -check_instruction(up, {add_module, Module}, _, Modules) - when is_atom(Module) -> - check_module(Module, Modules); - -%% An old module is re-added -check_instruction(down, {add_module, Module}, _, Modules) - when is_atom(Module) -> - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - ok; - ok -> - error({existing_readded_module, Module}) - end; - -%% Removing a module on upgrade: -%% - the module has been removed from the app-file. -%% - check that no module depends on this (removed) module -check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - check_purge(Pre), - check_purge(Post); - ok -> - error({existing_removed_module, Module}) - end; - -%% Removing a module on downgrade: the module exist -%% in the app-file. -check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - case (catch check_module(Module, Modules)) of - ok -> - check_purge(Pre), - check_purge(Post), - check_no_remove_depends(Module, AllInstr); - {error, {unknown_module, Module, Modules}} -> - error({nonexisting_removed_module, Module}) - end; - -check_instruction(up, {load_module, Module, Pre, Post, Depend}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_purge(Pre), - check_purge(Post); - -check_instruction(down, {load_module, Module, Pre, Post, Depend}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - check_module(Module, Modules), - % Can not be sure that the the dependent module exists in the new appfile - %%check_module_depend(Module, Depend, Modules), - check_purge(Pre), - check_purge(Post); - - - -check_instruction(up, {delete_module, Module}, _, Modules) - when is_atom(Module) -> - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - ok; - ok -> - error({existing_module_deleted, Module}) - end; - -check_instruction(down, {delete_module, Module}, _, Modules) - when is_atom(Module) -> - check_module(Module, Modules); - - -check_instruction(_, {apply, {Module, Function, Args}}, _, _) when is_atom(Module), is_atom(Function), is_list(Args) -> - ok; - -check_instruction(_, {update, Module, supervisor}, _, Modules) when is_atom(Module) -> - check_module(Module, Modules); - -check_instruction(_, {update, Module, {advanced, _}, DepMods}, _, Modules) when is_atom(Module), is_list(DepMods) -> - check_module(Module, Modules), - check_module_depend(Module, DepMods, Modules); - -check_instruction(_, {update, Module, Change, Pre, Post, Depend}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_change(Change), - check_purge(Pre), - check_purge(Post); - -check_instruction(_, {restart_application, inets}, _AllInstr, _Modules) -> - ok; - -check_instruction(_, {update, Module, {advanced, _}}, _, Modules) -> - check_module(Module, Modules); - -check_instruction(_, Instr, _AllInstr, _Modules) -> - error({error, {unknown_instruction, Instr}}). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -check_version(V) when is_list(V) -> - ok; -check_version(REBin) when is_binary(REBin) -> - try - begin - RE = binary_to_list(REBin), - case re:compile(RE) of - {ok, _} -> - ok; - {error, _} -> - error({bad_version, REBin}) - end - end - catch - _T:_E -> - error({bad_version, REBin}) - end; -check_version(V) -> - error({bad_version, V}). - - -check_module(M, Modules) when is_atom(M) -> - case lists:member(M,Modules) of - true -> - ok; - false -> - error({unknown_module, M, Modules}) - end; -check_module(M, _) -> - error({bad_module, M}). - - -check_module_depend(M, [], _) when is_atom(M) -> - ok; -check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) -> - case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of - [] -> - ok; - Unknown -> - error({unknown_depend_modules, Unknown}) - end; -check_module_depend(_M, D, _Modules) -> - error({bad_depend, D}). - - -check_no_remove_depends(_Module, []) -> - ok; -check_no_remove_depends(Module, [Instr|Instrs]) -> - check_no_remove_depend(Module, Instr), - check_no_remove_depends(Module, Instrs). - -check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, load_module, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, update, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(_, _) -> - ok. - - -check_change(soft) -> - ok; -check_change({advanced, _Something}) -> - ok; -check_change(Change) -> - error({bad_change, Change}). - - -check_purge(soft_purge) -> - ok; -check_purge(brutal_purge) -> - ok; -check_purge(Purge) -> - error({bad_purge, Purge}). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -error(Reason) -> - throw({error, Reason}). - -fail(Reason) -> - exit({suite_failed, Reason}). - -key1search(Key, L) -> - case lists:keysearch(Key, 1, L) of - undefined -> - fail({not_found, Key, L}); - {value, {Key, Value}} -> - Value - end. + ok = ?t:appup_test(inets). diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl index 0ac940fd3e..60979278fc 100644 --- a/lib/inets/test/inets_sup_SUITE.erl +++ b/lib/inets/test/inets_sup_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ -module(inets_sup_SUITE). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). + %% Note: This directive should only be used in test suites. -compile(export_all). @@ -77,75 +77,32 @@ end_per_suite(_) -> %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_testcase(httpd_subtree, Config) -> - io:format("init_per_testcase(httpd_subtree) -> entry with" - "~n Config: ~p" - "~n", [Config]), Dog = test_server:timetrap(?t:minutes(1)), NewConfig = lists:keydelete(watchdog, 1, Config), - - DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), - ServerROOT = filename:join(PrivDir, "server_root"), - DocROOT = filename:join(PrivDir, "htdocs"), - ConfDir = filename:join(ServerROOT, "conf"), - - io:format("init_per_testcase(httpd_subtree) -> create dir(s)" - "~n", []), - file:make_dir(ServerROOT), %% until http_test is cleaned up! - ok = file:make_dir(DocROOT), - ok = file:make_dir(ConfDir), - - io:format("init_per_testcase(httpd_subtree) -> copy file(s)" - "~n", []), - {ok, _} = inets_test_lib:copy_file("simple.conf", DataDir, PrivDir), - {ok, _} = inets_test_lib:copy_file("mime.types", DataDir, ConfDir), - - io:format("init_per_testcase(httpd_subtree) -> write file(s)" - "~n", []), - ConfFile = filename:join(PrivDir, "simple.conf"), - {ok, Fd} = file:open(ConfFile, [append]), - ok = file:write(Fd, "ServerRoot " ++ ServerROOT ++ "\n"), - ok = file:write(Fd, "DocumentRoot " ++ DocROOT ++ "\n"), - ok = file:close(Fd), - - %% To make sure application:set_env is not overwritten by any - %% app-file settings. - io:format("init_per_testcase(httpd_subtree) -> load inets app" - "~n", []), - application:load(inets), - io:format("init_per_testcase(httpd_subtree) -> update inets env" - "~n", []), - ok = application:set_env(inets, services, [{httpd, ConfFile}]), - + + SimpleConfig = [{port, 0}, + {server_name,"www.test"}, + {modules, [mod_get]}, + {server_root, PrivDir}, + {document_root, PrivDir}, + {bind_address, any}, + {ipfamily, inet}], try - io:format("init_per_testcase(httpd_subtree) -> start inets app" - "~n", []), - ok = inets:start(), - io:format("init_per_testcase(httpd_subtree) -> done" - "~n", []), - [{watchdog, Dog}, {server_root, ServerROOT}, {doc_root, DocROOT}, - {conf_dir, ConfDir}| NewConfig] + inets:start(), + inets:start(httpd, SimpleConfig), + [{watchdog, Dog} | NewConfig] catch _:Reason -> - io:format("init_per_testcase(httpd_subtree) -> " - "failed starting inets - cleanup" - "~n Reason: ~p" - "~n", [Reason]), - application:unset_env(inets, services), - application:unload(inets), + inets:stop(), exit({failed_starting_inets, Reason}) end; -init_per_testcase(Case, Config) -> - io:format("init_per_testcase(~p) -> entry with" - "~n Config: ~p" - "~n", [Case, Config]), +init_per_testcase(_Case, Config) -> Dog = test_server:timetrap(?t:minutes(5)), NewConfig = lists:keydelete(watchdog, 1, Config), - Stop = inets:stop(), - io:format("init_per_testcase(~p) -> Stop: ~p" - "~n", [Case, Stop]), + inets:stop(), ok = inets:start(), [{watchdog, Dog} | NewConfig]. @@ -260,10 +217,10 @@ tftpd_worker(suite) -> []; tftpd_worker(Config) when is_list(Config) -> [] = supervisor:which_children(tftp_sup), - {ok, Pid0} = inets:start(tftpd, [{host, "localhost"}, - {port, inet_port()}]), - {ok, _Pid1} = inets:start(tftpd, [{host, "localhost"}, - {port, inet_port()}], stand_alone), + {ok, Pid0} = inets:start(tftpd, [{host, inets_test_lib:hostname()}, + {port, 0}]), + {ok, _Pid1} = inets:start(tftpd, [{host, inets_test_lib:hostname()}, + {port, 0}], stand_alone), [{_,Pid0, worker, _}] = supervisor:which_children(tftp_sup), inets:stop(tftpd, Pid0), @@ -280,30 +237,22 @@ httpd_subtree(doc) -> httpd_subtree(suite) -> []; httpd_subtree(Config) when is_list(Config) -> - io:format("httpd_subtree -> entry with" - "~n Config: ~p" - "~n", [Config]), - %% Check that we have the httpd top supervisor - io:format("httpd_subtree -> verify inets~n", []), {ok, _} = verify_child(inets_sup, httpd_sup, supervisor), %% Check that we have the httpd instance supervisor - io:format("httpd_subtree -> verify httpd~n", []), {ok, Id} = verify_child(httpd_sup, httpd_instance_sup, supervisor), {httpd_instance_sup, Addr, Port} = Id, Instance = httpd_util:make_name("httpd_instance_sup", Addr, Port), %% Check that we have the expected httpd instance children - io:format("httpd_subtree -> verify httpd instance children " - "(acceptor, misc and manager)~n", []), + {ok, _} = verify_child(Instance, httpd_connection_sup, supervisor), {ok, _} = verify_child(Instance, httpd_acceptor_sup, supervisor), {ok, _} = verify_child(Instance, httpd_misc_sup, supervisor), {ok, _} = verify_child(Instance, httpd_manager, worker), %% Check that the httpd instance acc supervisor has children - io:format("httpd_subtree -> verify acc~n", []), - InstanceAcc = httpd_util:make_name("httpd_acc_sup", Addr, Port), + InstanceAcc = httpd_util:make_name("httpd_acceptor_sup", Addr, Port), case supervisor:which_children(InstanceAcc) of [_ | _] -> ok; @@ -327,15 +276,7 @@ httpd_subtree(Config) when is_list(Config) -> verify_child(Parent, Child, Type) -> -%% io:format("verify_child -> entry with" -%% "~n Parent: ~p" -%% "~n Child: ~p" -%% "~n Type: ~p" -%% "~n", [Parent, Child, Type]), Children = supervisor:which_children(Parent), -%% io:format("verify_child -> which children" -%% "~n Children: ~p" -%% "~n", [Children]), verify_child(Children, Parent, Child, Type). verify_child([], Parent, Child, _Type) -> @@ -343,21 +284,12 @@ verify_child([], Parent, Child, _Type) -> verify_child([{Id, _Pid, Type2, Mods}|Children], Parent, Child, Type) -> case lists:member(Child, Mods) of true when (Type2 =:= Type) -> -%% io:format("verify_child -> found with expected type" -%% "~n Id: ~p" -%% "~n", [Id]), {ok, Id}; true when (Type2 =/= Type) -> -%% io:format("verify_child -> found with unexpected type" -%% "~n Type2: ~p" -%% "~n Id: ~p" -%% "~n", [Type2, Id]), {error, {wrong_type, Type2, Child, Parent}}; false -> verify_child(Children, Parent, Child, Type) end. - - %%------------------------------------------------------------------------- %% httpc_subtree @@ -367,47 +299,19 @@ httpc_subtree(doc) -> httpc_subtree(suite) -> []; httpc_subtree(Config) when is_list(Config) -> - tsp("httpc_subtree -> entry with" - "~n Config: ~p", [Config]), - - tsp("httpc_subtree -> start inets service httpc with profile foo"), - {ok, _Foo} = inets:start(httpc, [{profile, foo}]), + {ok, Foo} = inets:start(httpc, [{profile, foo}]), - tsp("httpc_subtree -> " - "start stand-alone inets service httpc with profile bar"), - {ok, _Bar} = inets:start(httpc, [{profile, bar}], stand_alone), + {ok, Bar} = inets:start(httpc, [{profile, bar}], stand_alone), - tsp("httpc_subtree -> retreive list of httpc instances"), HttpcChildren = supervisor:which_children(httpc_profile_sup), - tsp("httpc_subtree -> HttpcChildren: ~n~p", [HttpcChildren]), - - tsp("httpc_subtree -> verify httpc stand-alone instances"), + {value, {httpc_manager, _, worker, [httpc_manager]}} = lists:keysearch(httpc_manager, 1, HttpcChildren), - tsp("httpc_subtree -> verify httpc (named) instances"), - {value,{{httpc,foo}, Pid, worker, [httpc_manager]}} = + {value,{{httpc,foo}, _Pid, worker, [httpc_manager]}} = lists:keysearch({httpc, foo}, 1, HttpcChildren), false = lists:keysearch({httpc, bar}, 1, HttpcChildren), - tsp("httpc_subtree -> stop inets"), - inets:stop(httpc, Pid), - - tsp("httpc_subtree -> done"), - ok. - -inet_port() -> - {ok, Socket} = gen_tcp:listen(0, [{reuseaddr, true}]), - {ok, Port} = inet:port(Socket), - gen_tcp:close(Socket), - Port. - - -tsp(F) -> - tsp(F, []). -tsp(F, A) -> - test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]). - -tsf(Reason) -> - test_server:fail(Reason). + inets:stop(httpc, Foo), + exit(Bar, normal). diff --git a/lib/inets/test/inets_sup_SUITE_data/mime.types b/lib/inets/test/inets_sup_SUITE_data/mime.types deleted file mode 100644 index e52d345ff7..0000000000 --- a/lib/inets/test/inets_sup_SUITE_data/mime.types +++ /dev/null @@ -1,3 +0,0 @@ -# MIME type Extension -text/html html htm -text/plain asc txt diff --git a/lib/inets/test/inets_sup_SUITE_data/simple.conf b/lib/inets/test/inets_sup_SUITE_data/simple.conf deleted file mode 100644 index e1429b4a28..0000000000 --- a/lib/inets/test/inets_sup_SUITE_data/simple.conf +++ /dev/null @@ -1,6 +0,0 @@ -Port 8888 -ServerName www.test -SocketType ip_comm -Modules mod_get -ServerAdmin [email protected] - diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index 6ccc7b0da1..4be9d9c8b3 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -287,7 +287,9 @@ print(F, A, Mod, Line) -> print("", F, A, Mod, Line). hostname() -> - from($@, atom_to_list(node())). + {ok, Name} = inet:gethostname(), + Name. + from(H, [H | T]) -> T; from(H, [_ | T]) -> from(H, T); from(_, []) -> []. @@ -545,14 +547,14 @@ tsp(F) -> tsp(F, []). tsp(F, A) -> Timestamp = formated_timestamp(), - test_server:format("*** ~s ~p ~p " ++ F ++ "~n", + ct:pal("*** ~s ~p ~p " ++ F ++ "~n", [Timestamp, node(), self() | A]). tsf(Reason) -> - test_server:fail(Reason). + ct:fail(Reason). tss(Time) -> - test_server:sleep(Time). + ct:sleep(Time). timestamp() -> http_util:timestamp(). diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl new file mode 100644 index 0000000000..19c2bc129e --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE.erl @@ -0,0 +1,2485 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% + +-module(old_httpd_SUITE). + +-include_lib("test_server/include/test_server.hrl"). +-include("test_server_line.hrl"). +-include("inets_test_lib.hrl"). + +-include_lib("kernel/include/file.hrl"). + +%% Test server specific exports +-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1]). + +%% Core Server tests +-export([ + ip_mod_alias/1, + ip_mod_actions/1, + ip_mod_security/1, + ip_mod_auth/1, + ip_mod_auth_api/1, + ip_mod_auth_mnesia_api/1, + ip_mod_htaccess/1, + ip_mod_cgi/1, + ip_mod_esi/1, + ip_mod_get/1, + ip_mod_head/1, + ip_mod_all/1, + ip_load_light/1, + ip_load_medium/1, + ip_load_heavy/1, + ip_dos_hostname/1, + ip_time_test/1, + ip_block_disturbing_idle/1, + ip_block_non_disturbing_idle/1, + ip_block_503/1, + ip_block_disturbing_active/1, + ip_block_non_disturbing_active/1, + ip_block_disturbing_active_timeout_not_released/1, + ip_block_disturbing_active_timeout_released/1, + ip_block_non_disturbing_active_timeout_not_released/1, + ip_block_non_disturbing_active_timeout_released/1, + ip_block_disturbing_blocker_dies/1, + ip_block_non_disturbing_blocker_dies/1, + ip_restart_no_block/1, + ip_restart_disturbing_block/1, + ip_restart_non_disturbing_block/1 + ]). + +-export([ + essl_mod_alias/1, + essl_mod_actions/1, + essl_mod_security/1, + essl_mod_auth/1, + essl_mod_auth_api/1, + essl_mod_auth_mnesia_api/1, + essl_mod_htaccess/1, + essl_mod_cgi/1, + essl_mod_esi/1, + essl_mod_get/1, + essl_mod_head/1, + essl_mod_all/1, + essl_load_light/1, + essl_load_medium/1, + essl_load_heavy/1, + essl_dos_hostname/1, + essl_time_test/1, + essl_restart_no_block/1, + essl_restart_disturbing_block/1, + essl_restart_non_disturbing_block/1, + essl_block_disturbing_idle/1, + essl_block_non_disturbing_idle/1, + essl_block_503/1, + essl_block_disturbing_active/1, + essl_block_non_disturbing_active/1, + essl_block_disturbing_active_timeout_not_released/1, + essl_block_disturbing_active_timeout_released/1, + essl_block_non_disturbing_active_timeout_not_released/1, + essl_block_non_disturbing_active_timeout_released/1, + essl_block_disturbing_blocker_dies/1, + essl_block_non_disturbing_blocker_dies/1 + ]). + +%%% HTTP 1.1 tests +-export([ip_host/1, ip_chunked/1, ip_expect/1, ip_range/1, + ip_if_test/1, ip_http_trace/1, ip_http1_1_head/1, + ip_mod_cgi_chunked_encoding_test/1]). + +%%% HTTP 1.0 tests +-export([ip_head_1_0/1, ip_get_1_0/1, ip_post_1_0/1]). + +%%% HTTP 0.9 tests +-export([ip_get_0_9/1]). + +%%% Ticket tests +-export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1, + ticket_7304/1]). + +%%% IPv6 tests +-export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1, + ipv6_address_ipcomm/0, ipv6_address_ipcomm/1, + ipv6_hostname_essl/0, ipv6_hostname_essl/1, + ipv6_address_essl/0, ipv6_address_essl/1]). + +%% Help functions +-export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]). + +-define(IP_PORT, 8898). +-define(SSL_PORT, 8899). +-define(MAX_HEADER_SIZE, 256). +-define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1"). + +%% Minutes before failed auths timeout. +-define(FAIL_EXPIRE_TIME,1). + +%% Seconds before successful auths timeout. +-define(AUTH_TIMEOUT,5). + +-record(httpd_user, {user_name, password, user_data}). +-record(httpd_group, {group_name, userlist}). + + +%%-------------------------------------------------------------------- +%% all(Arg) -> [Doc] | [Case] | {skip, Comment} +%% Arg - doc | suite +%% Doc - string() +%% Case - atom() +%% Name of a test case function. +%% Comment - string() +%% Description: Returns documentation/test cases in this test suite +%% or a skip tuple if the platform is not supported. +%%-------------------------------------------------------------------- +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + {group, ip}, + {group, ssl}, + %%{group, http_1_1_ip}, + %%{group, http_1_0_ip}, + %%{group, http_0_9_ip}, + %%{group, ipv6}, + {group, tickets} + ]. + +groups() -> + [ + {ip, [], + [ + %%ip_mod_alias, + ip_mod_actions, + %%ip_mod_security, + %% ip_mod_auth, + %% ip_mod_auth_api, + ip_mod_auth_mnesia_api, + %%ip_mod_htaccess, + %%ip_mod_cgi, + %%ip_mod_esi, + %%ip_mod_get, + %%ip_mod_head, + %%ip_mod_all, + %% ip_load_light, + %% ip_load_medium, + %% ip_load_heavy, + %%ip_dos_hostname, + ip_time_test, + %% Only used through load_config + %% but we still need these tests + %% should be cleaned up and moved to new test suite + ip_restart_no_block, + ip_restart_disturbing_block, + ip_restart_non_disturbing_block, + ip_block_disturbing_idle, + ip_block_non_disturbing_idle, + ip_block_503, + ip_block_disturbing_active, + ip_block_non_disturbing_active, + ip_block_disturbing_active_timeout_not_released, + ip_block_disturbing_active_timeout_released, + ip_block_non_disturbing_active_timeout_not_released, + ip_block_non_disturbing_active_timeout_released, + ip_block_disturbing_blocker_dies, + ip_block_non_disturbing_blocker_dies + ]}, + {ssl, [], [{group, essl}]}, + {essl, [], + [ + %%essl_mod_alias, + essl_mod_actions, + %% essl_mod_security, + %% essl_mod_auth, + %% essl_mod_auth_api, + essl_mod_auth_mnesia_api, + %%essl_mod_htaccess, + %%essl_mod_cgi, + %%essl_mod_esi, + %%essl_mod_get, + %%essl_mod_head, + %% essl_mod_all, + %% essl_load_light, + %% essl_load_medium, + %% essl_load_heavy, + %%essl_dos_hostname, + essl_time_test + %% Replaced by load_config + %% essl_restart_no_block, + %% essl_restart_disturbing_block, + %% essl_restart_non_disturbing_block, + %% essl_block_disturbing_idle, + %% essl_block_non_disturbing_idle, essl_block_503, + %% essl_block_disturbing_active, + %% essl_block_non_disturbing_active, + %% essl_block_disturbing_active_timeout_not_released, + %% essl_block_disturbing_active_timeout_released, + %% essl_block_non_disturbing_active_timeout_not_released, + %% essl_block_non_disturbing_active_timeout_released, + %% essl_block_disturbing_blocker_dies, + %% essl_block_non_disturbing_blocker_dies + ]}, + %% {http_1_1_ip, [], + %% [ + %% %%ip_host, ip_chunked, ip_expect, + %% %%ip_range, + %% %%ip_if_test + %% %%ip_http_trace, ip_http1_1_head, + %% %%ip_mod_cgi_chunked_encoding_test + %% ]}, + %%{http_1_0_ip, [], + %%[ip_head_1_0, ip_get_1_0, ip_post_1_0]}, + %%{http_0_9_ip, [], [ip_get_0_9]}, + %% {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm, + %% ipv6_hostname_essl, ipv6_address_essl]}, + {tickets, [], + [%%ticket_5775, ticket_5865, + ticket_5913%%, ticket_6003, + %%ticket_7304 + ]}]. + +init_per_group(ipv6 = _GroupName, Config) -> + case inets_test_lib:has_ipv6_support() of + {ok, _} -> + Config; + _ -> + {skip, "Host does not support IPv6"} + end; +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config) -> Config +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + io:format(user, "init_per_suite -> entry with" + "~n Config: ~p" + "~n", [Config]), + + ?PRINT_SYSTEM_INFO([]), + + PrivDir = ?config(priv_dir, Config), + SuiteTopDir = filename:join(PrivDir, ?MODULE), + case file:make_dir(SuiteTopDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + throw({error, {failed_creating_suite_top_dir, Error}}) + end, + + [{has_ipv6_support, inets_test_lib:has_ipv6_support()}, + {suite_top_dir, SuiteTopDir}, + {node, node()}, + {host, inets_test_lib:hostname()}, + {address, getaddr()} | Config]. + + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config) -> _ +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after the whole suite +%%-------------------------------------------------------------------- + +end_per_suite(_Config) -> + %% SuiteTopDir = ?config(suite_top_dir, Config), + %% inets_test_lib:del_dirs(SuiteTopDir), + ok. + + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(Case, Config) -> Config +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_testcase(Case, Config) -> + NewConfig = init_per_testcase2(Case, Config), + init_per_testcase3(Case, NewConfig). + + +init_per_testcase2(Case, Config) -> + + %% tsp("init_per_testcase2 -> entry with" + %% "~n Config: ~p", [Config]), + + IpNormal = integer_to_list(?IP_PORT) ++ ".conf", + IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf", + SslNormal = integer_to_list(?SSL_PORT) ++ ".conf", + SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf", + + DataDir = ?config(data_dir, Config), + SuiteTopDir = ?config(suite_top_dir, Config), + + %% tsp("init_per_testcase2 -> " + %% "~n SuiteDir: ~p" + %% "~n DataDir: ~p", [SuiteTopDir, DataDir]), + + TcTopDir = filename:join(SuiteTopDir, Case), + ?line ok = file:make_dir(TcTopDir), + + %% tsp("init_per_testcase2 -> " + %% "~n TcTopDir: ~p", [TcTopDir]), + + DataSrc = filename:join([DataDir, "server_root"]), + ServerRoot = filename:join([TcTopDir, "server_root"]), + + %% tsp("init_per_testcase2 -> " + %% "~n DataSrc: ~p" + %% "~n ServerRoot: ~p", [DataSrc, ServerRoot]), + + ok = file:make_dir(ServerRoot), + ok = file:make_dir(filename:join([TcTopDir, "logs"])), + + NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config], + + %% tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"), + + inets_test_lib:copy_dirs(DataSrc, ServerRoot), + + %% tsp("init_per_testcase2 -> fix cgi"), + EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]), + {ok, FileInfo} = file:read_file_info(EnvCGI), + ok = file:write_file_info(EnvCGI, + FileInfo#file_info{mode = 8#00755}), + + EchoCGI = case test_server:os_type() of + {win32, _} -> + "cgi_echo.exe"; + _ -> + "cgi_echo" + end, + CGIDir = filename:join([ServerRoot, "cgi-bin"]), + inets_test_lib:copy_file(EchoCGI, DataDir, CGIDir), + NewEchoCGI = filename:join([CGIDir, EchoCGI]), + {ok, FileInfo1} = file:read_file_info(NewEchoCGI), + ok = file:write_file_info(NewEchoCGI, + FileInfo1#file_info{mode = 8#00755}), + + %% To be used by IP test cases + %% tsp("init_per_testcase2 -> ip testcase setups"), + create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig], + normal_access, IpNormal), + create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig], + mod_htaccess, IpHtaccess), + + %% To be used by SSL test cases + %% tsp("init_per_testcase2 -> ssl testcase setups"), + SocketType = + case atom_to_list(Case) of + [X, $s, $s, $l | _] -> + case X of + $p -> ssl; + $e -> essl + end; + _ -> + ssl + end, + + create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig], + normal_access, SslNormal), + create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig], + mod_htaccess, SslHtaccess), + + %% To be used by IPv6 test cases. Case-clause is so that + %% you can do ts:run(inets, httpd_SUITE, <test case>) + %% for all cases except the ipv6 cases as they depend + %% on 'test_host_ipv6_only' that will only be present + %% when you run the whole test suite due to shortcomings + %% of the test server. + + tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"), + NewConfig2 = + case atom_to_list(Case) of + "ipv6_" ++ _ -> + case (catch inets_test_lib:has_ipv6_support(NewConfig)) of + {ok, IPv6Address0} -> + {ok, Hostname} = inet:gethostname(), + IPv6Address = http_transport:ipv6_name(IPv6Address0), + create_ipv6_config([{port, ?IP_PORT}, + {sock_type, ip_comm}, + {ipv6_host, IPv6Address} | + NewConfig], + "ipv6_hostname_ipcomm.conf", + Hostname), + create_ipv6_config([{port, ?IP_PORT}, + {sock_type, ip_comm}, + {ipv6_host, IPv6Address} | + NewConfig], + "ipv6_address_ipcomm.conf", + IPv6Address), + create_ipv6_config([{port, ?SSL_PORT}, + {sock_type, essl}, + {ipv6_host, IPv6Address} | + NewConfig], + "ipv6_hostname_essl.conf", + Hostname), + create_ipv6_config([{port, ?SSL_PORT}, + {sock_type, essl}, + {ipv6_host, IPv6Address} | + NewConfig], + "ipv6_address_essl.conf", + IPv6Address), + [{ipv6_host, IPv6Address} | NewConfig]; + _ -> + NewConfig + end; + + _ -> + NewConfig + end, + + %% tsp("init_per_testcase2 -> done when" + %% "~n NewConfig2: ~p", [NewConfig2]), + + NewConfig2. + + +init_per_testcase3(Case, Config) -> + tsp("init_per_testcase3(~w) -> entry with" + "~n Config: ~p", [Case, Config]), + + +%% %% Create a new fresh node to be used by the server in this test-case + +%% NodeName = list_to_atom(atom_to_list(Case) ++ "_httpd"), +%% Node = inets_test_lib:start_node(NodeName), + + %% Clean up (we do not want this clean up in end_per_testcase + %% if init_per_testcase crashes for some testcase it will + %% have contaminated the environment and there will be no clean up.) + %% This init can take a few different paths so that one crashes + %% does not mean that all invocations will. + + application:unset_env(inets, services), + application:stop(inets), + application:stop(ssl), + cleanup_mnesia(), + + %% Start initialization + tsp("init_per_testcase3(~w) -> start init", [Case]), + + Dog = test_server:timetrap(inets_test_lib:minutes(10)), + NewConfig = lists:keydelete(watchdog, 1, Config), + TcTopDir = ?config(tc_top_dir, Config), + + CaseRest = + case atom_to_list(Case) of + "ip_mod_htaccess" -> + inets_test_lib:start_http_server( + filename:join(TcTopDir, + integer_to_list(?IP_PORT) ++ + "htaccess.conf")), + "mod_htaccess"; + "ip_" ++ Rest -> + inets_test_lib:start_http_server( + filename:join(TcTopDir, + integer_to_list(?IP_PORT) ++ ".conf")), + Rest; + "ticket_5913" -> + HttpdOptions = + [{file, + filename:join(TcTopDir, + integer_to_list(?IP_PORT) ++ ".conf")}, + {accept_timeout,30000}, + {debug,[{exported_functions, + [httpd_manager,httpd_request_handler]}]}], + inets_test_lib:start_http_server(HttpdOptions); + "ticket_"++Rest -> + %% OTP-5913 use the new syntax of inets.config + inets_test_lib:start_http_server([{file, + filename:join(TcTopDir, + integer_to_list(?IP_PORT) ++ ".conf")}]), + Rest; + + [X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] -> + ?ENSURE_STARTED([crypto, public_key, ssl]), + SslTag = + case X of + $p -> ssl; % Plain + $e -> essl % Erlang based ssl + end, + case inets_test_lib:start_http_server_ssl( + filename:join(TcTopDir, + integer_to_list(?SSL_PORT) ++ + "htaccess.conf"), SslTag) of + ok -> + "mod_htaccess"; + Other -> + error_logger:info_msg("Other: ~p~n", [Other]), + {skip, "SSL does not seem to be supported"} + end; + [X, $s, $s, $l, $_ | Rest] -> + ?ENSURE_STARTED([crypto, public_key, ssl]), + SslTag = + case X of + $p -> ssl; + $e -> essl + end, + case inets_test_lib:start_http_server_ssl( + filename:join(TcTopDir, + integer_to_list(?SSL_PORT) ++ + ".conf"), SslTag) of + ok -> + Rest; + Other -> + error_logger:info_msg("Other: ~p~n", [Other]), + {skip, "SSL does not seem to be supported"} + end; + "ipv6_" ++ _ = TestCaseStr -> + case inets_test_lib:has_ipv6_support() of + {ok, _} -> + inets_test_lib:start_http_server( + filename:join(TcTopDir, + TestCaseStr ++ ".conf")); + + _ -> + {skip, "Host does not support IPv6"} + end + end, + + InitRes = + case CaseRest of + {skip, _} = Skip -> + Skip; + "mod_auth_" ++ _ -> + start_mnesia(?config(node, Config)), + [{watchdog, Dog} | NewConfig]; + "mod_htaccess" -> + ServerRoot = ?config(server_root, Config), + Path = filename:join([ServerRoot, "htdocs"]), + catch remove_htaccess(Path), + create_htaccess_data(Path, ?config(address, Config)), + [{watchdog, Dog} | NewConfig]; + "range" -> + ServerRoot = ?config(server_root, Config), + Path = filename:join([ServerRoot, "htdocs"]), + create_range_data(Path), + [{watchdog, Dog} | NewConfig]; + _ -> + [{watchdog, Dog} | NewConfig] + end, + + tsp("init_per_testcase3(~w) -> done when" + "~n InitRes: ~p", [Case, InitRes]), + + InitRes. + + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(Case, Config) -> _ +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Description: Cleanup after each test case +%%-------------------------------------------------------------------- +end_per_testcase(Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)), + ok. + +end_per_testcase2(Case, Config) -> + tsp("end_per_testcase2(~w) -> entry with" + "~n Config: ~p", [Case, Config]), + application:unset_env(inets, services), + application:stop(inets), + application:stop(ssl), + application:stop(crypto), % used by the new ssl (essl test cases) + cleanup_mnesia(), + tsp("end_per_testcase2(~w) -> done", [Case]), + ok. + + +%%------------------------------------------------------------------------- +%% Test cases starts here. +%%------------------------------------------------------------------------- + +%%------------------------------------------------------------------------- +ip_mod_alias(doc) -> + ["Module test: mod_alias"]; +ip_mod_alias(suite) -> + []; +ip_mod_alias(Config) when is_list(Config) -> + httpd_mod:alias(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_actions(doc) -> + ["Module test: mod_actions"]; +ip_mod_actions(suite) -> + []; +ip_mod_actions(Config) when is_list(Config) -> + httpd_mod:actions(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_security(doc) -> + ["Module test: mod_security"]; +ip_mod_security(suite) -> + []; +ip_mod_security(Config) when is_list(Config) -> + ServerRoot = ?config(server_root, Config), + httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_auth(doc) -> + ["Module test: mod_auth"]; +ip_mod_auth(suite) -> + []; +ip_mod_auth(Config) when is_list(Config) -> + httpd_mod:auth(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_auth_api(doc) -> + ["Module test: mod_auth_api"]; +ip_mod_auth_api(suite) -> + []; +ip_mod_auth_api(Config) when is_list(Config) -> + ServerRoot = ?config(server_root, Config), + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_mod:auth_api(ServerRoot, "", ip_comm, ?IP_PORT, Host, Node), + httpd_mod:auth_api(ServerRoot, "dets_", ip_comm, ?IP_PORT, Host, Node), + httpd_mod:auth_api(ServerRoot, "mnesia_", ip_comm, ?IP_PORT, Host, Node), + ok. +%%------------------------------------------------------------------------- +ip_mod_auth_mnesia_api(doc) -> + ["Module test: mod_auth_mnesia_api"]; +ip_mod_auth_mnesia_api(suite) -> + []; +ip_mod_auth_mnesia_api(Config) when is_list(Config) -> + httpd_mod:auth_mnesia_api(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_mod_htaccess(doc) -> + ["Module test: mod_htaccess"]; +ip_mod_htaccess(suite) -> + []; +ip_mod_htaccess(Config) when is_list(Config) -> + httpd_mod:htaccess(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_mod_cgi(doc) -> + ["Module test: mod_cgi"]; +ip_mod_cgi(suite) -> + []; +ip_mod_cgi(Config) when is_list(Config) -> + httpd_mod:cgi(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_mod_esi(doc) -> + ["Module test: mod_esi"]; +ip_mod_esi(suite) -> + []; +ip_mod_esi(Config) when is_list(Config) -> + httpd_mod:esi(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_get(doc) -> + ["Module test: mod_get"]; +ip_mod_get(suite) -> + []; +ip_mod_get(Config) when is_list(Config) -> + httpd_mod:get(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_mod_head(doc) -> + ["Module test: mod_head"]; +ip_mod_head(suite) -> + []; +ip_mod_head(Config) when is_list(Config) -> + httpd_mod:head(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_mod_all(doc) -> + ["All modules test"]; +ip_mod_all(suite) -> + []; +ip_mod_all(Config) when is_list(Config) -> + httpd_mod:all(ip_comm, ?IP_PORT, + ?config(host, Config), ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_load_light(doc) -> + ["Test light load"]; +ip_load_light(suite) -> + []; +ip_load_light(Config) when is_list(Config) -> + httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config), + get_nof_clients(ip_comm, light)), + ok. +%%------------------------------------------------------------------------- +ip_load_medium(doc) -> + ["Test medium load"]; +ip_load_medium(suite) -> + []; +ip_load_medium(Config) when is_list(Config) -> + httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config), + get_nof_clients(ip_comm, medium)), + ok. +%%------------------------------------------------------------------------- +ip_load_heavy(doc) -> + ["Test heavy load"]; +ip_load_heavy(suite) -> + []; +ip_load_heavy(Config) when is_list(Config) -> + httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config), + get_nof_clients(ip_comm, heavy)), + ok. + + +%%------------------------------------------------------------------------- +ip_dos_hostname(doc) -> + ["Denial Of Service (DOS) attack test case"]; +ip_dos_hostname(suite) -> + []; +ip_dos_hostname(Config) when is_list(Config) -> + dos_hostname(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config), ?MAX_HEADER_SIZE), + ok. + + +%%------------------------------------------------------------------------- +ip_time_test(doc) -> + [""]; +ip_time_test(suite) -> + []; +ip_time_test(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_time_test:t(ip_comm, ?config(host, Config), ?IP_PORT), + ok. + +%%------------------------------------------------------------------------- +ip_block_503(doc) -> + ["Check that you will receive status code 503 when the server" + " is blocked and 200 when its not blocked."]; +ip_block_503(suite) -> + []; +ip_block_503(Config) when is_list(Config) -> + httpd_block:block_503(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_disturbing_idle(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "distribing does not really make a difference in this case."]; +ip_block_disturbing_idle(suite) -> + []; +ip_block_disturbing_idle(Config) when is_list(Config) -> + httpd_block:block_disturbing_idle(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_non_disturbing_idle(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "non distribing does not really make a difference in this case."]; +ip_block_non_disturbing_idle(suite) -> + []; +ip_block_non_disturbing_idle(Config) when is_list(Config) -> + httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_disturbing_active(doc) -> + ["Check that you can block/unblock an active server. The strategy " + "distribing means ongoing requests should be terminated."]; +ip_block_disturbing_active(suite) -> + []; +ip_block_disturbing_active(Config) when is_list(Config) -> + httpd_block:block_disturbing_active(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_non_disturbing_active(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "non distribing means the ongoing requests should be compleated."]; +ip_block_non_disturbing_active(suite) -> + []; +ip_block_non_disturbing_active(Config) when is_list(Config) -> + httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_block_disturbing_active_timeout_not_released(doc) -> + ["Check that you can block an active server. The strategy " + "distribing means ongoing requests should be compleated" + "if the timeout does not occur."]; +ip_block_disturbing_active_timeout_not_released(suite) -> + []; +ip_block_disturbing_active_timeout_not_released(Config) + when is_list(Config) -> + httpd_block:block_disturbing_active_timeout_not_released(ip_comm, + ?IP_PORT, + ?config(host, + Config), + ?config(node, + Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_disturbing_active_timeout_released(doc) -> + ["Check that you can block an active server. The strategy " + "distribing means ongoing requests should be terminated when" + "the timeout occurs."]; +ip_block_disturbing_active_timeout_released(suite) -> + []; +ip_block_disturbing_active_timeout_released(Config) + when is_list(Config) -> + httpd_block:block_disturbing_active_timeout_released(ip_comm, + ?IP_PORT, + ?config(host, + Config), + ?config(node, + Config)), + ok. + +%%------------------------------------------------------------------------- +ip_block_non_disturbing_active_timeout_not_released(doc) -> + ["Check that you can block an active server. The strategy " + "non non distribing means ongoing requests should be completed."]; +ip_block_non_disturbing_active_timeout_not_released(suite) -> + []; +ip_block_non_disturbing_active_timeout_not_released(Config) + when is_list(Config) -> + httpd_block: + block_non_disturbing_active_timeout_not_released(ip_comm, + ?IP_PORT, + ?config(host, + Config), + ?config(node, + Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_non_disturbing_active_timeout_released(doc) -> + ["Check that you can block an active server. The strategy " + "non non distribing means ongoing requests should be completed. " + "When the timeout occurs the block operation sohould be canceled." ]; +ip_block_non_disturbing_active_timeout_released(suite) -> + []; +ip_block_non_disturbing_active_timeout_released(Config) + when is_list(Config) -> + httpd_block: + block_non_disturbing_active_timeout_released(ip_comm, + ?IP_PORT, + ?config(host, + Config), + ?config(node, + Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_disturbing_blocker_dies(doc) -> + []; +ip_block_disturbing_blocker_dies(suite) -> + []; +ip_block_disturbing_blocker_dies(Config) when is_list(Config) -> + httpd_block:disturbing_blocker_dies(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_block_non_disturbing_blocker_dies(doc) -> + []; +ip_block_non_disturbing_blocker_dies(suite) -> + []; +ip_block_non_disturbing_blocker_dies(Config) when is_list(Config) -> + httpd_block:non_disturbing_blocker_dies(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_restart_no_block(doc) -> + [""]; +ip_restart_no_block(suite) -> + []; +ip_restart_no_block(Config) when is_list(Config) -> + httpd_block:restart_no_block(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_restart_disturbing_block(doc) -> + [""]; +ip_restart_disturbing_block(suite) -> + []; +ip_restart_disturbing_block(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Condition = + fun() -> + case os:type() of + {unix, linux} -> + HW = string:strip(os:cmd("uname -m"), right, $\n), + case HW of + "ppc" -> + case inet:gethostname() of + {ok, "peach"} -> + true; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end + end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_restart_non_disturbing_block(doc) -> + [""]; +ip_restart_non_disturbing_block(suite) -> + []; +ip_restart_non_disturbing_block(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Condition = + fun() -> + case os:type() of + {unix, linux} -> + HW = string:strip(os:cmd("uname -m"), right, $\n), + case HW of + "ppc" -> + case inet:gethostname() of + {ok, "peach"} -> + true; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end + end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- + +essl_mod_alias(doc) -> + ["Module test: mod_alias - using new of configure new SSL"]; +essl_mod_alias(suite) -> + []; +essl_mod_alias(Config) when is_list(Config) -> + ssl_mod_alias(essl, Config). + + +ssl_mod_alias(Tag, Config) -> + httpd_mod:alias(Tag, ?SSL_PORT, + ?config(host, Config), ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_actions(doc) -> + ["Module test: mod_actions - using new of configure new SSL"]; +essl_mod_actions(suite) -> + []; +essl_mod_actions(Config) when is_list(Config) -> + ssl_mod_actions(essl, Config). + + +ssl_mod_actions(Tag, Config) -> + httpd_mod:actions(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_security(doc) -> + ["Module test: mod_security - using new of configure new SSL"]; +essl_mod_security(suite) -> + []; +essl_mod_security(Config) when is_list(Config) -> + ssl_mod_security(essl, Config). + +ssl_mod_security(Tag, Config) -> + ServerRoot = ?config(server_root, Config), + httpd_mod:security(ServerRoot, + Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_auth(doc) -> + ["Module test: mod_auth - using new of configure new SSL"]; +essl_mod_auth(suite) -> + []; +essl_mod_auth(Config) when is_list(Config) -> + ssl_mod_auth(essl, Config). + +ssl_mod_auth(Tag, Config) -> + httpd_mod:auth(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + + +essl_mod_auth_api(doc) -> + ["Module test: mod_auth - using new of configure new SSL"]; +essl_mod_auth_api(suite) -> + []; +essl_mod_auth_api(Config) when is_list(Config) -> + ssl_mod_auth_api(essl, Config). + +ssl_mod_auth_api(Tag, Config) -> + ServerRoot = ?config(server_root, Config), + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_mod:auth_api(ServerRoot, "", Tag, ?SSL_PORT, Host, Node), + httpd_mod:auth_api(ServerRoot, "dets_", Tag, ?SSL_PORT, Host, Node), + httpd_mod:auth_api(ServerRoot, "mnesia_", Tag, ?SSL_PORT, Host, Node), + ok. + + +%%------------------------------------------------------------------------- + + +essl_mod_auth_mnesia_api(doc) -> + ["Module test: mod_auth_mnesia_api - using new of configure new SSL"]; +essl_mod_auth_mnesia_api(suite) -> + []; +essl_mod_auth_mnesia_api(Config) when is_list(Config) -> + ssl_mod_auth_mnesia_api(essl, Config). + +ssl_mod_auth_mnesia_api(Tag, Config) -> + httpd_mod:auth_mnesia_api(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_htaccess(doc) -> + ["Module test: mod_htaccess - using new of configure new SSL"]; +essl_mod_htaccess(suite) -> + []; +essl_mod_htaccess(Config) when is_list(Config) -> + ssl_mod_htaccess(essl, Config). + +ssl_mod_htaccess(Tag, Config) -> + httpd_mod:htaccess(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_cgi(doc) -> + ["Module test: mod_cgi - using new of configure new SSL"]; +essl_mod_cgi(suite) -> + []; +essl_mod_cgi(Config) when is_list(Config) -> + ssl_mod_cgi(essl, Config). + +ssl_mod_cgi(Tag, Config) -> + httpd_mod:cgi(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_esi(doc) -> + ["Module test: mod_esi - using new of configure new SSL"]; +essl_mod_esi(suite) -> + []; +essl_mod_esi(Config) when is_list(Config) -> + ssl_mod_esi(essl, Config). + +ssl_mod_esi(Tag, Config) -> + httpd_mod:esi(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_get(doc) -> + ["Module test: mod_get - using new of configure new SSL"]; +essl_mod_get(suite) -> + []; +essl_mod_get(Config) when is_list(Config) -> + ssl_mod_get(essl, Config). + +ssl_mod_get(Tag, Config) -> + httpd_mod:get(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_head(doc) -> + ["Module test: mod_head - using new of configure new SSL"]; +essl_mod_head(suite) -> + []; +essl_mod_head(Config) when is_list(Config) -> + ssl_mod_head(essl, Config). + +ssl_mod_head(Tag, Config) -> + httpd_mod:head(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_mod_all(doc) -> + ["All modules test - using new of configure new SSL"]; +essl_mod_all(suite) -> + []; +essl_mod_all(Config) when is_list(Config) -> + ssl_mod_all(essl, Config). + +ssl_mod_all(Tag, Config) -> + httpd_mod:all(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_load_light(doc) -> + ["Test light load - using new of configure new SSL"]; +essl_load_light(suite) -> + []; +essl_load_light(Config) when is_list(Config) -> + ssl_load_light(essl, Config). + +ssl_load_light(Tag, Config) -> + httpd_load:load_test(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config), + get_nof_clients(ssl, light)), + ok. + + +%%------------------------------------------------------------------------- + +essl_load_medium(doc) -> + ["Test medium load - using new of configure new SSL"]; +essl_load_medium(suite) -> + []; +essl_load_medium(Config) when is_list(Config) -> + ssl_load_medium(essl, Config). + +ssl_load_medium(Tag, Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_load:load_test(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config), + get_nof_clients(ssl, medium)), + ok. + + +%%------------------------------------------------------------------------- + +essl_load_heavy(doc) -> + ["Test heavy load - using new of configure new SSL"]; +essl_load_heavy(suite) -> + []; +essl_load_heavy(Config) when is_list(Config) -> + ssl_load_heavy(essl, Config). + +ssl_load_heavy(Tag, Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_load:load_test(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config), + get_nof_clients(ssl, heavy)), + ok. + + +%%------------------------------------------------------------------------- + + +essl_dos_hostname(doc) -> + ["Denial Of Service (DOS) attack test case - using new of configure new SSL"]; +essl_dos_hostname(suite) -> + []; +essl_dos_hostname(Config) when is_list(Config) -> + ssl_dos_hostname(essl, Config). + +ssl_dos_hostname(Tag, Config) -> + dos_hostname(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config), + ?MAX_HEADER_SIZE), + ok. + + +%%------------------------------------------------------------------------- + + +essl_time_test(doc) -> + ["using new of configure new SSL"]; +essl_time_test(suite) -> + []; +essl_time_test(Config) when is_list(Config) -> + ssl_time_test(essl, Config). + +ssl_time_test(Tag, Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + FreeBSDVersionVerify = + fun() -> + case os:version() of + {7, 1, _} -> % We only have one such machine, so... + true; + _ -> + false + end + end, + Skippable = [win32, {unix, [{freebsd, FreeBSDVersionVerify}]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_time_test:t(Tag, + ?config(host, Config), + ?SSL_PORT), + ok. + + +%%------------------------------------------------------------------------- + + +essl_block_503(doc) -> + ["Check that you will receive status code 503 when the server" + " is blocked and 200 when its not blocked - using new of configure new SSL."]; +essl_block_503(suite) -> + []; +essl_block_503(Config) when is_list(Config) -> + ssl_block_503(essl, Config). + +ssl_block_503(Tag, Config) -> + httpd_block:block_503(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_disturbing_idle(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "distribing does not really make a difference in this case." + "Using new of configure new SSL"]; +essl_block_disturbing_idle(suite) -> + []; +essl_block_disturbing_idle(Config) when is_list(Config) -> + ssl_block_disturbing_idle(essl, Config). + +ssl_block_disturbing_idle(Tag, Config) -> + httpd_block:block_disturbing_idle(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_non_disturbing_idle(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "non distribing does not really make a difference in this case." + "Using new of configure new SSL"]; +essl_block_non_disturbing_idle(suite) -> + []; +essl_block_non_disturbing_idle(Config) when is_list(Config) -> + ssl_block_non_disturbing_idle(essl, Config). + +ssl_block_non_disturbing_idle(Tag, Config) -> + httpd_block:block_non_disturbing_idle(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_disturbing_active(doc) -> + ["Check that you can block/unblock an active server. The strategy " + "distribing means ongoing requests should be terminated." + "Using new of configure new SSL"]; +essl_block_disturbing_active(suite) -> + []; +essl_block_disturbing_active(Config) when is_list(Config) -> + ssl_block_disturbing_active(essl, Config). + +ssl_block_disturbing_active(Tag, Config) -> + httpd_block:block_disturbing_active(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_non_disturbing_active(doc) -> + ["Check that you can block/unblock an idle server. The strategy " + "non distribing means the ongoing requests should be compleated." + "Using new of configure new SSL"]; +essl_block_non_disturbing_active(suite) -> + []; +essl_block_non_disturbing_active(Config) when is_list(Config) -> + ssl_block_non_disturbing_active(essl, Config). + +ssl_block_non_disturbing_active(Tag, Config) -> + httpd_block:block_non_disturbing_idle(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_disturbing_active_timeout_not_released(doc) -> + ["Check that you can block an active server. The strategy " + "distribing means ongoing requests should be compleated" + "if the timeout does not occur." + "Using new of configure new SSL"]; +essl_block_disturbing_active_timeout_not_released(suite) -> + []; +essl_block_disturbing_active_timeout_not_released(Config) + when is_list(Config) -> + ssl_block_disturbing_active_timeout_not_released(essl, Config). + +ssl_block_disturbing_active_timeout_not_released(Tag, Config) -> + Port = ?SSL_PORT, + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_block:block_disturbing_active_timeout_not_released(Tag, + Port, Host, Node), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_disturbing_active_timeout_released(doc) -> + ["Check that you can block an active server. The strategy " + "distribing means ongoing requests should be terminated when" + "the timeout occurs." + "Using new of configure new SSL"]; +essl_block_disturbing_active_timeout_released(suite) -> + []; +essl_block_disturbing_active_timeout_released(Config) + when is_list(Config) -> + ssl_block_disturbing_active_timeout_released(essl, Config). + +ssl_block_disturbing_active_timeout_released(Tag, Config) -> + Port = ?SSL_PORT, + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_block:block_disturbing_active_timeout_released(Tag, + Port, + Host, + Node), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_non_disturbing_active_timeout_not_released(doc) -> + ["Check that you can block an active server. The strategy " + "non non distribing means ongoing requests should be completed." + "Using new of configure new SSL"]; +essl_block_non_disturbing_active_timeout_not_released(suite) -> + []; +essl_block_non_disturbing_active_timeout_not_released(Config) + when is_list(Config) -> + ssl_block_non_disturbing_active_timeout_not_released(essl, Config). + +ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) -> + Port = ?SSL_PORT, + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_block:block_non_disturbing_active_timeout_not_released(Tag, + Port, + Host, + Node), + ok. + + +%%------------------------------------------------------------------------- + + +essl_block_non_disturbing_active_timeout_released(doc) -> + ["Check that you can block an active server. The strategy " + "non distribing means ongoing requests should be completed. " + "When the timeout occurs the block operation sohould be canceled." + "Using new of configure new SSL"]; +essl_block_non_disturbing_active_timeout_released(suite) -> + []; +essl_block_non_disturbing_active_timeout_released(Config) + when is_list(Config) -> + ssl_block_non_disturbing_active_timeout_released(essl, Config). + +ssl_block_non_disturbing_active_timeout_released(Tag, Config) + when is_list(Config) -> + Port = ?SSL_PORT, + Host = ?config(host, Config), + Node = ?config(node, Config), + httpd_block:block_non_disturbing_active_timeout_released(Tag, + Port, + Host, + Node), + + ok. + + +%%------------------------------------------------------------------------- + + +essl_block_disturbing_blocker_dies(doc) -> + ["using new of configure new SSL"]; +essl_block_disturbing_blocker_dies(suite) -> + []; +essl_block_disturbing_blocker_dies(Config) when is_list(Config) -> + ssl_block_disturbing_blocker_dies(essl, Config). + +ssl_block_disturbing_blocker_dies(Tag, Config) -> + httpd_block:disturbing_blocker_dies(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + +essl_block_non_disturbing_blocker_dies(doc) -> + ["using new of configure new SSL"]; +essl_block_non_disturbing_blocker_dies(suite) -> + []; +essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) -> + ssl_block_non_disturbing_blocker_dies(essl, Config). + +ssl_block_non_disturbing_blocker_dies(Tag, Config) -> + httpd_block:non_disturbing_blocker_dies(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + + +essl_restart_no_block(doc) -> + ["using new of configure new SSL"]; +essl_restart_no_block(suite) -> + []; +essl_restart_no_block(Config) when is_list(Config) -> + ssl_restart_no_block(essl, Config). + +ssl_restart_no_block(Tag, Config) -> + httpd_block:restart_no_block(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + + +essl_restart_disturbing_block(doc) -> + ["using new of configure new SSL"]; +essl_restart_disturbing_block(suite) -> + []; +essl_restart_disturbing_block(Config) when is_list(Config) -> + ssl_restart_disturbing_block(essl, Config). + +ssl_restart_disturbing_block(Tag, Config) -> + %% <CONDITIONAL-SKIP> + Condition = + fun() -> + case os:type() of + {unix, linux} -> + case ?OSCMD("uname -m") of + "ppc" -> + case file:read_file_info("/etc/fedora-release") of + {ok, _} -> + case ?OSCMD("awk '{print $2}' /etc/fedora-release") of + "release" -> + %% Fedora 7 and later + case ?OSCMD("awk '{print $3}' /etc/fedora-release") of + "7" -> + true; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end + end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_block:restart_disturbing_block(Tag, ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- + + +essl_restart_non_disturbing_block(doc) -> + ["using new of configure new SSL"]; +essl_restart_non_disturbing_block(suite) -> + []; +essl_restart_non_disturbing_block(Config) when is_list(Config) -> + ssl_restart_non_disturbing_block(essl, Config). + +ssl_restart_non_disturbing_block(Tag, Config) -> + %% <CONDITIONAL-SKIP> + Condition = + fun() -> + case os:type() of + {unix, linux} -> + HW = string:strip(os:cmd("uname -m"), right, $\n), + case HW of + "ppc" -> + case inet:gethostname() of + {ok, "peach"} -> + true; + _ -> + false + end; + _ -> + false + end; + _ -> + false + end + end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + httpd_block:restart_non_disturbing_block(Tag, + ?SSL_PORT, + ?config(host, Config), + ?config(node, Config)), + ok. + + +%%------------------------------------------------------------------------- +ip_host(doc) -> + ["Control that the server accepts/rejects requests with/ without host"]; +ip_host(suite)-> + []; +ip_host(Config) when is_list(Config) -> + httpd_1_1:host(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_chunked(doc) -> + ["Control that the server accepts chunked requests"]; +ip_chunked(suite) -> + []; +ip_chunked(Config) when is_list(Config) -> + httpd_1_1:chunked(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_expect(doc) -> + ["Control that the server handles request with the expect header " + "field appropiate"]; +ip_expect(suite)-> + []; +ip_expect(Config) when is_list(Config) -> + httpd_1_1:expect(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_range(doc) -> + ["Control that the server can handle range requests to plain files"]; +ip_range(suite)-> + []; +ip_range(Config) when is_list(Config) -> + httpd_1_1:range(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_if_test(doc) -> + ["Test that the if - request header fields is handled correclty"]; +ip_if_test(suite) -> + []; +ip_if_test(Config) when is_list(Config) -> + ServerRoot = ?config(server_root, Config), + DocRoot = filename:join([ServerRoot, "htdocs"]), + httpd_1_1:if_test(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config), DocRoot), + ok. +%%------------------------------------------------------------------------- +ip_http_trace(doc) -> + ["Test the trace module "]; +ip_http_trace(suite) -> + []; +ip_http_trace(Config) when is_list(Config) -> + httpd_1_1:http_trace(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. +%%------------------------------------------------------------------------- +ip_http1_1_head(doc) -> + ["Test the trace module "]; +ip_http1_1_head(suite)-> + []; +ip_http1_1_head(Config) when is_list(Config) -> + httpd_1_1:head(ip_comm, ?IP_PORT, ?config(host, Config), + ?config(node, Config)), + ok. + +%%------------------------------------------------------------------------- +ip_get_0_9(doc) -> + ["Test simple HTTP/0.9 GET"]; +ip_get_0_9(suite)-> + []; +ip_get_0_9(Config) when is_list(Config) -> + Host = ?config(host, Config), + Node = ?config(node, Config), + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "GET / \r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/0.9"} ]), + %% Without space after uri + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "GET /\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/0.9"} ]), + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "GET / HTTP/0.9\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/0.9"}]), + + ok. +%%------------------------------------------------------------------------- +ip_head_1_0(doc) -> + ["Test HTTP/1.0 HEAD"]; +ip_head_1_0(suite)-> + []; +ip_head_1_0(Config) when is_list(Config) -> + Host = ?config(host, Config), + Node = ?config(node, Config), + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "HEAD / HTTP/1.0\r\n\r\n", [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok. +%%------------------------------------------------------------------------- +ip_get_1_0(doc) -> + ["Test HTTP/1.0 GET"]; +ip_get_1_0(suite)-> + []; +ip_get_1_0(Config) when is_list(Config) -> + Host = ?config(host, Config), + Node = ?config(node, Config), + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "GET / HTTP/1.0\r\n\r\n", [{statuscode, 200}, + {version, "HTTP/1.0"}]), + + ok. +%%------------------------------------------------------------------------- +ip_post_1_0(doc) -> + ["Test HTTP/1.0 POST"]; +ip_post_1_0(suite)-> + []; +ip_post_1_0(Config) when is_list(Config) -> + Host = ?config(host, Config), + Node = ?config(node, Config), + %% Test the post message formatin 1.0! Real post are testes elsewhere + ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node, + "POST / HTTP/1.0\r\n\r\n " + "Content-Length:6 \r\n\r\nfoobar", + [{statuscode, 500}, {version, "HTTP/1.0"}]), + + ok. +%%------------------------------------------------------------------------- +ip_mod_cgi_chunked_encoding_test(doc) -> + ["Test the trace module "]; +ip_mod_cgi_chunked_encoding_test(suite)-> + []; +ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) -> + Host = ?config(host, Config), + Script = + case test_server:os_type() of + {win32, _} -> + "/cgi-bin/printenv.bat"; + _ -> + "/cgi-bin/printenv.sh" + end, + Requests = + ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n", + "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:" + ++ Host ++"\r\n\r\n"], + httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT, + Host, + ?config(node, Config), + Requests), + ok. + +%------------------------------------------------------------------------- + +ipv6_hostname_ipcomm() -> + [{require, ipv6_hosts}]. +ipv6_hostname_ipcomm(X) -> + SocketType = ip_comm, + Port = ?IP_PORT, + ipv6_hostname(SocketType, Port, X). + +ipv6_hostname_essl() -> + [{require, ipv6_hosts}]. +ipv6_hostname_essl(X) -> + SocketType = essl, + Port = ?SSL_PORT, + ipv6_hostname(SocketType, Port, X). + +ipv6_hostname(_SocketType, _Port, doc) -> + ["Test standard ipv6 address"]; +ipv6_hostname(_SocketType, _Port, suite)-> + []; +ipv6_hostname(SocketType, Port, Config) when is_list(Config) -> + tsp("ipv6_hostname -> entry with" + "~n SocketType: ~p" + "~n Port: ~p" + "~n Config: ~p", [SocketType, Port, Config]), + Host = ?config(host, Config), + URI = "GET HTTP://" ++ + Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n", + tsp("ipv6_hostname -> Host: ~p", [Host]), + httpd_test_lib:verify_request(SocketType, Host, Port, [inet6], + node(), + URI, + [{statuscode, 200}, {version, "HTTP/1.1"}]), + ok. + +%%------------------------------------------------------------------------- + +ipv6_address_ipcomm() -> + [{require, ipv6_hosts}]. +ipv6_address_ipcomm(X) -> + SocketType = ip_comm, + Port = ?IP_PORT, + ipv6_address(SocketType, Port, X). + +ipv6_address_essl() -> + [{require, ipv6_hosts}]. +ipv6_address_essl(X) -> + SocketType = essl, + Port = ?SSL_PORT, + ipv6_address(SocketType, Port, X). + +ipv6_address(_SocketType, _Port, doc) -> + ["Test standard ipv6 address"]; +ipv6_address(_SocketType, _Port, suite)-> + []; +ipv6_address(SocketType, Port, Config) when is_list(Config) -> + tsp("ipv6_address -> entry with" + "~n SocketType: ~p" + "~n Port: ~p" + "~n Config: ~p", [SocketType, Port, Config]), + Host = ?config(host, Config), + tsp("ipv6_address -> Host: ~p", [Host]), + URI = "GET HTTP://" ++ + Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n", + httpd_test_lib:verify_request(SocketType, Host, Port, [inet6], + node(), + URI, + [{statuscode, 200}, {version, "HTTP/1.1"}]), + ok. + + +%%-------------------------------------------------------------------- +ticket_5775(doc) -> + ["Tests that content-length is correct"]; +ticket_5775(suite) -> + []; +ticket_5775(Config) -> + ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config), + ?IP_PORT, ?config(node, Config), + "GET /cgi-bin/erl/httpd_example:get_bin " + "HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + ok. +ticket_5865(doc) -> + ["Tests that a header without last-modified is handled"]; +ticket_5865(suite) -> + []; +ticket_5865(Config) -> + ?SKIP(as_of_r15_behaviour_of_calendar_has_changed), + Host = ?config(host,Config), + ServerRoot = ?config(server_root, Config), + DocRoot = filename:join([ServerRoot, "htdocs"]), + File = filename:join([DocRoot,"last_modified.html"]), + + Bad_mtime = case test_server:os_type() of + {win32, _} -> + {{1600,12,31},{23,59,59}}; + {unix, _} -> + {{1969,12,31},{23,59,59}} + end, + + {ok,FI}=file:read_file_info(File), + + case file:write_file_info(File,FI#file_info{mtime=Bad_mtime}) of + ok -> + ok = httpd_test_lib:verify_request(ip_comm, Host, + ?IP_PORT, ?config(node, Config), + "GET /last_modified.html" + " HTTP/1.1\r\nHost:" + ++Host++"\r\n\r\n", + [{statuscode, 200}, + {no_header, + "last-modified"}]), + ok; + {error, Reason} -> + Fault = + io_lib:format("Attempt to change the file info to set the" + " preconditions of the test case failed ~p~n", + [Reason]), + {skip, Fault} + end. + +ticket_5913(doc) -> + ["Tests that a header without last-modified is handled"]; +ticket_5913(suite) -> []; +ticket_5913(Config) -> + ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), + ?IP_PORT, ?config(node, Config), + "GET /cgi-bin/erl/httpd_example:get_bin " + "HTTP/1.0\r\n\r\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + ok. + +ticket_6003(doc) -> + ["Tests that a URI with a bad hexadecimal code is handled"]; +ticket_6003(suite) -> []; +ticket_6003(Config) -> + ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), + ?IP_PORT, ?config(node, Config), + "GET http://www.erlang.org/%skalle " + "HTTP/1.0\r\n\r\n", + [{statuscode, 400}, + {version, "HTTP/1.0"}]), + ok. + +ticket_7304(doc) -> + ["Tests missing CR in delimiter"]; +ticket_7304(suite) -> + []; +ticket_7304(Config) -> + ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config), + ?IP_PORT, ?config(node, Config), + "GET / HTTP/1.0\r\n\n", + [{statuscode, 200}, + {version, "HTTP/1.0"}]), + ok. + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- +dos_hostname(Type, Port, Host, Node, Max) -> + H1 = {"", 200}, + H2 = {"dummy-host.ericsson.se", 200}, + TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")), + H3 = {TooLongHeader, 403}, + Hosts = [H1,H2,H3], + dos_hostname_poll(Type, Host, Port, Node, Hosts). + +%% make_ipv6(T) when is_tuple(T) andalso (size(T) =:= 8) -> +%% make_ipv6(tuple_to_list(T)); + +%% make_ipv6([_, _, _, _, _, _, _, _] = IPV6) -> +%% lists:flatten(io_lib:format("~s:~s:~s:~s:~s:~s:~s:~s", IPV6)). + + +%%-------------------------------------------------------------------- +%% Other help functions +create_config(Config, Access, FileName) -> + ServerRoot = ?config(server_root, Config), + TcTopDir = ?config(tc_top_dir, Config), + Port = ?config(port, Config), + Type = ?config(sock_type, Config), + Host = ?config(host, Config), + Mods = io_lib:format("~p", [httpd_mod]), + Funcs = io_lib:format("~p", [ssl_password_cb]), + MaxHdrSz = io_lib:format("~p", [256]), + MaxHdrAct = io_lib:format("~p", [close]), + + io:format(user, + "create_config -> " + "~n ServerRoot: ~p" + "~n TcTopDir: ~p" + "~n Type: ~p" + "~n Port: ~p" + "~n Host: ~p" + "~n", [ServerRoot, TcTopDir, Type, Port, Host]), + + SSL = + if + (Type =:= ssl) orelse + (Type =:= essl) -> + [cline(["SSLCertificateFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLCertificateKeyFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLCACertificateFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLPasswordCallbackModule ", Mods]), + cline(["SSLPasswordCallbackFunction ", Funcs]), + cline(["SSLVerifyClient 0"]), + cline(["SSLVerifyDepth 1"])]; + true -> + [] + end, + ModOrder = + case Access of + mod_htaccess -> + "Modules mod_alias mod_htaccess mod_auth " + "mod_security " + "mod_responsecontrol mod_trace mod_esi " + "mod_actions mod_cgi mod_include mod_dir " + "mod_range mod_get " + "mod_head mod_log mod_disk_log"; + _ -> + "Modules mod_alias mod_auth mod_security " + "mod_responsecontrol mod_trace mod_esi " + "mod_actions mod_cgi mod_include mod_dir " + "mod_range mod_get " + "mod_head mod_log mod_disk_log" + end, + + %% The test suite currently does not handle an explicit BindAddress. + %% They assume any has been used, that is Addr is always set to undefined! + + %% {ok, Hostname} = inet:gethostname(), + %% {ok, Addr} = inet:getaddr(Hostname, inet6), + %% AddrStr = make_ipv6(Addr), + %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])), + + BindAddress = "*|inet", + %% BindAddress = "*", + + HttpConfig = [ + cline(["Port ", integer_to_list(Port)]), + cline(["ServerName ", Host]), + cline(["SocketType ", atom_to_list(Type)]), + cline([ModOrder]), + %% cline(["LogFormat ", "erlang"]), + cline(["ServerAdmin [email protected]"]), + cline(["BindAddress ", BindAddress]), + cline(["ServerRoot ", ServerRoot]), + cline(["ErrorLog ", TcTopDir, + "/logs/error_log_", integer_to_list(Port)]), + cline(["TransferLog ", TcTopDir, + "/logs/access_log_", integer_to_list(Port)]), + cline(["SecurityLog ", TcTopDir, + "/logs/security_log_", integer_to_list(Port)]), + cline(["ErrorDiskLog ", TcTopDir, + "/logs/error_disk_log_", integer_to_list(Port)]), + cline(["ErrorDiskLogSize ", "190000 ", "11"]), + cline(["TransferDiskLog ", TcTopDir, + "/logs/access_disk_log_", integer_to_list(Port)]), + cline(["TransferDiskLogSize ", "200000 ", "10"]), + cline(["SecurityDiskLog ", TcTopDir, + "/logs/security_disk_log_", integer_to_list(Port)]), + cline(["SecurityDiskLogSize ", "210000 ", "9"]), + cline(["MaxClients 10"]), + cline(["MaxHeaderSize ", MaxHdrSz]), + cline(["MaxHeaderAction ", MaxHdrAct]), + cline(["DocumentRoot ", + filename:join(ServerRoot, "htdocs")]), + cline(["DirectoryIndex ", "index.html ", "welcome.html"]), + cline(["DefaultType ", "text/plain"]), + SSL, + mod_alias_config(ServerRoot), + + config_directory(filename:join([ServerRoot,"htdocs", + "open"]), + "Open Area", + filename:join(ServerRoot, "auth/passwd"), + filename:join(ServerRoot, "auth/group"), + plain, + "user one Aladdin", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join([ServerRoot,"htdocs", + "secret"]), + "Secret Area", + filename:join(ServerRoot, "auth/passwd"), + filename:join(ServerRoot, "auth/group"), + plain, + "group group1 group2", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join([ServerRoot,"htdocs", + "secret", + "top_secret"]), + "Top Secret Area", + filename:join(ServerRoot, "auth/passwd"), + filename:join(ServerRoot, "auth/group"), + plain, + "group group3", + filename:join(ServerRoot, "security_data")), + + config_directory(filename:join([ServerRoot,"htdocs", + "dets_open"]), + "Dets Open Area", + filename:join(ServerRoot, "passwd"), + filename:join(ServerRoot, "group"), + dets, + "user one Aladdin", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join([ServerRoot,"htdocs", + "dets_secret"]), + "Dets Secret Area", + filename:join(ServerRoot, "passwd"), + filename:join(ServerRoot, "group"), + dets, + "group group1 group2", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join([ServerRoot,"htdocs", + "dets_secret", + "top_secret"]), + "Dets Top Secret Area", + filename:join(ServerRoot, "passwd"), + filename:join(ServerRoot, "group"), + dets, + "group group3", + filename:join(ServerRoot, "security_data")), + + config_directory(filename:join([ServerRoot,"htdocs", + "mnesia_open"]), + "Mnesia Open Area", + false, + false, + mnesia, + "user one Aladdin", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join([ServerRoot,"htdocs", + "mnesia_secret"]), + "Mnesia Secret Area", + false, + false, + mnesia, + "group group1 group2", + filename:join(ServerRoot, "security_data")), + config_directory(filename:join( + [ServerRoot, "htdocs", "mnesia_secret", + "top_secret"]), + "Mnesia Top Secret Area", + false, + false, + mnesia, + "group group3", + filename:join(ServerRoot, "security_data")) + ], + ConfigFile = filename:join([TcTopDir, FileName]), + {ok, Fd} = file:open(ConfigFile, [write]), + ok = file:write(Fd, lists:flatten(HttpConfig)), + ok = file:close(Fd). + +config_directory(Dir, AuthName, AuthUserFile, AuthGroupFile, AuthDBType, + Require, SF) -> + file:delete(SF), + [ + cline(["<Directory ", Dir, ">"]), + cline(["SecurityDataFile ", SF]), + cline(["SecurityMaxRetries 3"]), + cline(["SecurityFailExpireTime ", integer_to_list(?FAIL_EXPIRE_TIME)]), + cline(["SecurityBlockTime 1"]), + cline(["SecurityAuthTimeout ", integer_to_list(?AUTH_TIMEOUT)]), + cline(["SecurityCallbackModule ", "httpd_mod"]), + cline_if_set("AuthUserFile", AuthUserFile), + cline_if_set("AuthGroupFile", AuthGroupFile), + cline_if_set("AuthName", AuthName), + cline_if_set("AuthDBType", AuthDBType), + cline(["require ", Require]), + cline(["</Directory>\r\n"]) + ]. + +mod_alias_config(Root) -> + [ + cline(["Alias /icons/ ", filename:join(Root,"icons"), "/"]), + cline(["Alias /pics/ ", filename:join(Root, "icons"), "/"]), + cline(["ScriptAlias /cgi-bin/ ", filename:join(Root, "cgi-bin"), "/"]), + cline(["ScriptAlias /htbin/ ", filename:join(Root, "cgi-bin"), "/"]), + cline(["ErlScriptAlias /cgi-bin/erl httpd_example io"]), + cline(["EvalScriptAlias /eval httpd_example io"]) + ]. + +cline(List) -> + lists:flatten([List, "\r\n"]). + +cline_if_set(_, false) -> + []; +cline_if_set(Name, Var) when is_list(Var) -> + cline([Name, " ", Var]); +cline_if_set(Name, Var) when is_atom(Var) -> + cline([Name, " ", atom_to_list(Var)]). + +getaddr() -> + {ok,HostName} = inet:gethostname(), + {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet), + lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])). + +start_mnesia(Node) -> + case rpc:call(Node, ?MODULE, cleanup_mnesia, []) of + ok -> + ok; + Other -> + tsf({failed_to_cleanup_mnesia, Other}) + end, + case rpc:call(Node, ?MODULE, setup_mnesia, []) of + {atomic, ok} -> + ok; + Other2 -> + tsf({failed_to_setup_mnesia, Other2}) + end, + ok. + +setup_mnesia() -> + setup_mnesia([node()]). + +setup_mnesia(Nodes) -> + ok = mnesia:create_schema(Nodes), + ok = mnesia:start(), + {atomic, ok} = mnesia:create_table(httpd_user, + [{attributes, + record_info(fields, httpd_user)}, + {disc_copies,Nodes}, {type, set}]), + {atomic, ok} = mnesia:create_table(httpd_group, + [{attributes, + record_info(fields, + httpd_group)}, + {disc_copies,Nodes}, {type,bag}]). + +cleanup_mnesia() -> + mnesia:start(), + mnesia:delete_table(httpd_user), + mnesia:delete_table(httpd_group), + stopped = mnesia:stop(), + mnesia:delete_schema([node()]), + ok. + +create_htaccess_data(Path, IpAddress)-> + create_htaccess_dirs(Path), + + create_html_file(filename:join([Path,"ht/open/dummy.html"])), + create_html_file(filename:join([Path,"ht/blocknet/dummy.html"])), + create_html_file(filename:join([Path,"ht/secret/dummy.html"])), + create_html_file(filename:join([Path,"ht/secret/top_secret/dummy.html"])), + + create_htaccess_file(filename:join([Path,"ht/open/.htaccess"]), + Path, "user one Aladdin"), + create_htaccess_file(filename:join([Path,"ht/secret/.htaccess"]), + Path, "group group1 group2"), + create_htaccess_file(filename:join([Path, + "ht/secret/top_secret/.htaccess"]), + Path, "user four"), + create_htaccess_file(filename:join([Path,"ht/blocknet/.htaccess"]), + Path, nouser, IpAddress), + + create_user_group_file(filename:join([Path,"ht","users.file"]), + "one:OnePassword\ntwo:TwoPassword\nthree:" + "ThreePassword\nfour:FourPassword\nAladdin:" + "AladdinPassword"), + create_user_group_file(filename:join([Path,"ht","groups.file"]), + "group1: two one\ngroup2: two three"). + +create_html_file(PathAndFileName)-> + file:write_file(PathAndFileName,list_to_binary( + "<html><head><title>test</title></head> + <body>testar</body></html>")). + +create_htaccess_file(PathAndFileName, BaseDir, RequireData)-> + file:write_file(PathAndFileName, + list_to_binary( + "AuthUserFile "++ BaseDir ++ + "/ht/users.file\nAuthGroupFile "++ BaseDir + ++ "/ht/groups.file\nAuthName Test\nAuthType" + " Basic\n<Limit>\nrequire " ++ RequireData ++ + "\n</Limit>")). + +create_htaccess_file(PathAndFileName, BaseDir, nouser, IpAddress)-> + file:write_file(PathAndFileName,list_to_binary( + "AuthUserFile "++ BaseDir ++ + "/ht/users.file\nAuthGroupFile " ++ + BaseDir ++ "/ht/groups.file\nAuthName" + " Test\nAuthType" + " Basic\n<Limit GET>\n\tallow from " ++ + format_ip(IpAddress, + string:rchr(IpAddress,$.)) ++ + "\n</Limit>")). + +create_user_group_file(PathAndFileName, Data)-> + file:write_file(PathAndFileName, list_to_binary(Data)). + +create_htaccess_dirs(Path)-> + ok = file:make_dir(filename:join([Path,"ht"])), + ok = file:make_dir(filename:join([Path,"ht/open"])), + ok = file:make_dir(filename:join([Path,"ht/blocknet"])), + ok = file:make_dir(filename:join([Path,"ht/secret"])), + ok = file:make_dir(filename:join([Path,"ht/secret/top_secret"])). + +remove_htaccess_dirs(Path)-> + file:del_dir(filename:join([Path,"ht/secret/top_secret"])), + file:del_dir(filename:join([Path,"ht/secret"])), + file:del_dir(filename:join([Path,"ht/blocknet"])), + file:del_dir(filename:join([Path,"ht/open"])), + file:del_dir(filename:join([Path,"ht"])). + +format_ip(IpAddress,Pos)when Pos > 0-> + case lists:nth(Pos,IpAddress) of + $.-> + case lists:nth(Pos-2,IpAddress) of + $.-> + format_ip(IpAddress,Pos-3); + _-> + lists:sublist(IpAddress,Pos-2) ++ "." + end; + _ -> + format_ip(IpAddress,Pos-1) + end; + +format_ip(IpAddress, _Pos)-> + "1" ++ IpAddress. + +remove_htaccess(Path)-> + file:delete(filename:join([Path,"ht/open/dummy.html"])), + file:delete(filename:join([Path,"ht/secret/dummy.html"])), + file:delete(filename:join([Path,"ht/secret/top_secret/dummy.html"])), + file:delete(filename:join([Path,"ht/blocknet/dummy.html"])), + file:delete(filename:join([Path,"ht/blocknet/.htaccess"])), + file:delete(filename:join([Path,"ht/open/.htaccess"])), + file:delete(filename:join([Path,"ht/secret/.htaccess"])), + file:delete(filename:join([Path,"ht/secret/top_secret/.htaccess"])), + file:delete(filename:join([Path,"ht","users.file"])), + file:delete(filename:join([Path,"ht","groups.file"])), + remove_htaccess_dirs(Path). + + +dos_hostname_poll(Type, Host, Port, Node, Hosts) -> + [dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) + || {Host1,Code} <- Hosts]. + +dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) -> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + dos_hostname_request(Host1), + [{statuscode, Code}, + {version, "HTTP/1.0"}]). + +dos_hostname_request(Host) -> + "GET / HTTP/1.0\r\n" ++ Host ++ "\r\n\r\n". + +get_nof_clients(Mode, Load) -> + get_nof_clients(test_server:os_type(), Mode, Load). + +get_nof_clients(_, ip_comm, light) -> 5; +get_nof_clients(_, ssl, light) -> 2; +get_nof_clients(_, ip_comm, medium) -> 10; +get_nof_clients(_, ssl, medium) -> 4; +get_nof_clients(_, ip_comm, heavy) -> 20; +get_nof_clients(_, ssl, heavy) -> 6. + +%% Make a file 100 bytes long containing 012...9*10 +create_range_data(Path) -> + PathAndFileName=filename:join([Path,"range.txt"]), + file:write_file(PathAndFileName,list_to_binary(["12345678901234567890", + "12345678901234567890", + "12345678901234567890", + "12345678901234567890", + "12345678901234567890"])). + +create_ipv6_config(Config, FileName, Ipv6Address) -> + ServerRoot = ?config(server_root, Config), + TcTopDir = ?config(tc_top_dir, Config), + Port = ?config(port, Config), + SockType = ?config(sock_type, Config), + Mods = io_lib:format("~p", [httpd_mod]), + Funcs = io_lib:format("~p", [ssl_password_cb]), + Host = ?config(ipv6_host, Config), + + MaxHdrSz = io_lib:format("~p", [256]), + MaxHdrAct = io_lib:format("~p", [close]), + + Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi" + " mod_include mod_dir mod_get mod_head" + " mod_log mod_disk_log mod_trace", + + SSL = + if + (SockType =:= ssl) orelse + (SockType =:= essl) -> + [cline(["SSLCertificateFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLCertificateKeyFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLCACertificateFile ", + filename:join(ServerRoot, "ssl/ssl_server.pem")]), + cline(["SSLPasswordCallbackModule ", Mods]), + cline(["SSLPasswordCallbackFunction ", Funcs]), + cline(["SSLVerifyClient 0"]), + cline(["SSLVerifyDepth 1"])]; + true -> + [] + end, + + BindAddress = "[" ++ Ipv6Address ++"]|inet6", + + HttpConfig = + [cline(["BindAddress ", BindAddress]), + cline(["Port ", integer_to_list(Port)]), + cline(["ServerName ", Host]), + cline(["SocketType ", atom_to_list(SockType)]), + cline([Mod_order]), + cline(["ServerRoot ", ServerRoot]), + cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]), + cline(["MaxHeaderSize ",MaxHdrSz]), + cline(["MaxHeaderAction ",MaxHdrAct]), + cline(["DirectoryIndex ", "index.html "]), + cline(["DefaultType ", "text/plain"]), + SSL], + ConfigFile = filename:join([TcTopDir,FileName]), + {ok, Fd} = file:open(ConfigFile, [write]), + ok = file:write(Fd, lists:flatten(HttpConfig)), + ok = file:close(Fd). + + +tsp(F) -> + inets_test_lib:tsp("[~w]" ++ F, [?MODULE]). +tsp(F, A) -> + inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]). + +tsf(Reason) -> + inets_test_lib:tsf(Reason). + diff --git a/lib/inets/test/old_httpd_SUITE_data/Makefile.src b/lib/inets/test/old_httpd_SUITE_data/Makefile.src new file mode 100644 index 0000000000..b0fdb43d8d --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/Makefile.src @@ -0,0 +1,14 @@ +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ + +PROGS = cgi_echo@exe@ + +all: $(PROGS) + +cgi_echo@exe@: cgi_echo@obj@ + $(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@ + +cgi_echo@obj@: cgi_echo.c + $(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c diff --git a/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c b/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c new file mode 100644 index 0000000000..580f860e96 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c @@ -0,0 +1,97 @@ +#include <stdlib.h> +#include <stdio.h> + +#if defined __WIN32__ +#include <windows.h> +#include <fcntl.h> +#endif + +static int read_exact(char *buffer, int len); +static int write_exact(char *buffer, int len); + +int main(void) +{ + char msg[100]; + int msg_len; +#ifdef __WIN32__ + _setmode(_fileno( stdin), _O_BINARY); + _setmode(_fileno( stdout), _O_BINARY); +#endif + msg_len = read_exact(msg, 100); + + write_exact("Content-type: text/plain\r\n\r\n", 28); + write_exact(msg, msg_len); + exit(EXIT_SUCCESS); +} + + +/* read from stdin */ +#ifdef __WIN32__ +static int read_exact(char *buffer, int len) +{ + HANDLE standard_input = GetStdHandle(STD_INPUT_HANDLE); + + unsigned read_result; + unsigned sofar = 0; + + if (!len) { /* Happens for "empty packages */ + return 0; + } + for (;;) { + if (!ReadFile(standard_input, buffer + sofar, + len - sofar, &read_result, NULL)) { + return -1; /* EOF */ + } + if (!read_result) { + return -2; /* Interrupted while reading? */ + } + sofar += read_result; + if (sofar == len) { + return len; + } + } +} +#else +static int read_exact(char *buffer, int len) { + int i, got = 0; + + do { + if ((i = read(0, buffer + got, len - got)) <= 0) + return(i); + got += i; + } while (got < len); + return len; + +} +#endif + +/* write to stdout */ +#ifdef __WIN32__ + static int write_exact(char *buffer, int len) + { + HANDLE standard_output = GetStdHandle(STD_OUTPUT_HANDLE); + unsigned written; + + if (!WriteFile(standard_output, buffer, len, &written, NULL)) { + return -1; /* Broken Pipe */ + } + if (written < ((unsigned) len)) { + /* This should not happen, standard output is not blocking? */ + return -2; + } + + return (int) written; +} + +#else + static int write_exact(char *buffer, int len) { + int i, wrote = 0; + + do { + if ((i = write(1, buffer + wrote, len - wrote)) <= 0) + return i; + wrote += i; + } while (wrote < len); + return len; + } +#endif diff --git a/lib/inets/test/httpd_SUITE_data/server_root/Makefile b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile index d7a3231068..d7a3231068 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/Makefile +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group new file mode 100644 index 0000000000..b3da0ccbd3 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group @@ -0,0 +1,3 @@ +group1: one two +group2: two three +group3: three Aladdin diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd new file mode 100644 index 0000000000..8c980ff547 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd @@ -0,0 +1,4 @@ +one:onePassword +two:twoPassword +three:threePassword +Aladdin:AladdinPassword diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat new file mode 100644 index 0000000000..25a49a1536 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat @@ -0,0 +1,9 @@ +@echo off +echo tomrad > c:\cygwin\tmp\hej +echo Content-type: text/html +echo. +echo ^<HTML^> ^<HEAD^> ^<TITLE^>OS Environment^</TITLE^> ^</HEAD^> ^<BODY^>^<PRE^> +set +echo ^</PRE^>^</BODY^>^</HTML^> + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh new file mode 100755 index 0000000000..de81de9bde --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh @@ -0,0 +1,6 @@ +#!/bin/sh +echo "Content-type: text/html" +echo "" +echo "<HTML> <HEAD> <TITLE>OS Environment</TITLE> </HEAD> <BODY><PRE>" +env +echo "</PRE></BODY></HTML>"
\ No newline at end of file diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf index 48e66f0114..48e66f0114 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/conf/8080.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf index 79bb7fcca4..79bb7fcca4 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/conf/8888.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf index ceb94237d2..ceb94237d2 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/conf/httpd.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/mime.types b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types index d2f81e4e5e..d2f81e4e5e 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/conf/mime.types +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf index 8b8c57a98b..8b8c57a98b 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/conf/ssl.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml new file mode 100644 index 0000000000..107e3ff610 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml @@ -0,0 +1,70 @@ +<HTML> +<HEAD> +<TITLE>/ssi.html (17-Apr-1997)</TITLE> +</HEAD> +<BODY> +<H1>/ssi.html</H1> + +<!-- ************* CONFIG ************* --> + +<!--#config timefmt="%a %b %e %T %Z %Y" sizefmt="abbrev"--> +<!--#config errmsg="[an especially ugly error occurred while processing this directive]"--> + +<!-- ************* INCLUDE ************* --> + +<P>Include /misc/friedrich.html: +<!--#include virtual="/misc/friedrich.html"--> +<P>Include /misc/not_defined.html: <!--#include virtual="/misc/not_defined.html"--> +<P>Include misc/friedrich.html: +<!--#include file="misc/friedrich.html"--> +<P>Include not_defined.html: <!--#include file="not_defined.html"--> + +<P><HR> + +<!-- ************* ECHO ************* --> + +<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"--> +<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"--> +<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"--> +<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"--> +<P>DATE_GMT: <!--#echo var="DATE_GMT"--> +<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"--> +<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"--> + +<P><HR> + +<!-- ************* FSIZE ************* --> + +<P>Size of index.html: <!--#fsize file="index.html"--> +<P>Size of not_defined.html: <!--#fsize file="not_defined.html"--> +<!--#config sizefmt="bytes"--> +<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"--> +<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"--> + +<P><HR> + +<!-- ************* FLASTMOD ************* --> + +<P>Last modification of index.html: <!--#flastmod file="index.html"--> +<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"--> +<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"--> +<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"--> + +<!--#exec cmd="ls"--> +<!--#exec cmd="printenv"--> +<!--#exec cmd="sunemaja"--> + +<!--#exec cgi="/cgi-bin/printenv.sh"--> + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html new file mode 100644 index 0000000000..a6e8a35a04 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/open/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/open/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html new file mode 100644 index 0000000000..016b04e540 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/secret/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html new file mode 100644 index 0000000000..34db3d5d1a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html @@ -0,0 +1,9 @@ +<HTML> +<HEAD> +<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE> +<!-- Created by: Mattias Nilsson, 04-Feb-1998 --> +</HEAD> +<BODY> +<H1>/secret/top_secret/index.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml new file mode 100644 index 0000000000..141db5be59 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml @@ -0,0 +1,35 @@ +<HTML> +<HEAD> +<TITLE>/echo.shtml</TITLE> +</HEAD> +<BODY> +<H1>/echo.shtml</H1> + +<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"--> + +<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"--> + +<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"--> + +<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"--> + +<P>DATE_GMT: <!--#echo var="DATE_GMT"--> + +<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"--> + +<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"--> + +<P>[<A HREF="ssi.html">Back</A>] + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml new file mode 100644 index 0000000000..97333da898 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml @@ -0,0 +1,30 @@ +<HTML> +<HEAD> +<TITLE>/exec.shtml</TITLE> +</HEAD> +<BODY> +<H1>/exec.shtml</H1> +<PRE> +<!--#exec cmd="ls"--> +<HR> +<!--#exec cmd="printenv"--> +<HR> +<!--#exec cmd="sunemaja"--> +<HR> +<!--#exec cgi="/cgi-bin/printenv.sh"--> +</PRE> + +<P>[<A HREF="ssi.html">Back</A>] + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml new file mode 100644 index 0000000000..d54c36fe50 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml @@ -0,0 +1,29 @@ +<HTML> +<HEAD> +<TITLE>/flastmod.shtml</TITLE> +</HEAD> +<BODY> +<H1>/flastmod.shtml</H1> + +<P>Last modification of index.html: <!--#flastmod file="index.html"--> + +<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"--> + +<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"--> + +<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"--> + +<P>[<A HREF="ssi.html">Back</A>] + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml new file mode 100644 index 0000000000..570ee9cf6d --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml @@ -0,0 +1,29 @@ +<HTML> +<HEAD> +<TITLE>/fsize.shtml</TITLE> +</HEAD> +<BODY> +<H1>/fsize.shtml</H1> + +<P>Size of index.html: <!--#fsize file="index.html"--> + +<P>Size of not_defined.html: <!--#fsize file="not_defined.html"--> + +<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"--> + +<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"--> + +<P>[<A HREF="ssi.html">Back</A>] + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml new file mode 100644 index 0000000000..529aad0437 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml @@ -0,0 +1,33 @@ +<HTML> +<HEAD> +<TITLE>/include.shtml</TITLE> +</HEAD> +<BODY> +<H1>/include.shtml</H1> + +<P>Include /misc/friedrich.html: +<!--#include virtual="/misc/friedrich.html"--> + +<P>Include /misc/not_defined.html: +<!--#include virtual="/misc/not_defined.html"--> + +<P>Include misc/friedrich.html: +<!--#include file="misc/friedrich.html"--> + +<P>Include not_defined.html: +<!--#include file="not_defined.html"--> + +<P>[<A HREF="ssi.html">Back</A>] + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html new file mode 100644 index 0000000000..cfdc9f9ab7 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html @@ -0,0 +1,25 @@ +<HTML> +<HEAD> +<TITLE>/index.html</TITLE> +</HEAD> +<BODY> +<H1>/index.html</H1> + +<STRONG>Server-Side Include (SSI) commands:</STRONG><BR> +<A HREF="config.shtml">config</A><BR> +<A HREF="echo.shtml">echo</A><BR> +<A HREF="exec.shtml">exec</A><BR> +<A HREF="flastmod.shtml">flastmod</A><BR> +<A HREF="fsize.shtml">fsize</A><BR> +<A HREF="include.shtml">include</A><BR> + +<BR> +<BR> + +<STRONG>ESI callback:</STRING><BR> +<A HREF="cgi-bin/erl/httpd_example/get">cgi-bin/erl/httpd_example/get</A><BR> +<A HREF="cgi-bin/erl/httpd_example/yahoo">cgi-bin/erl/httpd_example/yahoo</A><BR> +<A HREF="cgi-bin/erl/httpd_example/test1">cgi-bin/erl/httpd_example/test1</A><BR> + +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html new file mode 100644 index 0000000000..65c1790813 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html @@ -0,0 +1,22 @@ +<HTML> +<HEAD> +<TITLE>/last_modified.html</TITLE> +</HEAD> +<BODY> +<H1>/last_modified.html</H1> + +<P>This document is only used for test of illegal last-modified date.</P> + + +</BODY> +</HTML> + + + + + + + + + + diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html new file mode 100644 index 0000000000..d7953d5df4 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html @@ -0,0 +1,7 @@ +<P><CITE> +Talking much about oneself can also be a means to conceal oneself.<BR> +-- Friedrich Nietzsche +</CITE> + +<P>Nested Include: +<!--#include file="misc/oech.html"--> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html new file mode 100644 index 0000000000..506064bf04 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html @@ -0,0 +1,4 @@ +<P><CITE> +What excuses stand in your way? How can you eliminate them?<BR> +-- Roger von Oech +</CITE> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html new file mode 100644 index 0000000000..8c17451f91 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html @@ -0,0 +1 @@ +<HTML></HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html new file mode 100644 index 0000000000..a6e8a35a04 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/open/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/open/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html new file mode 100644 index 0000000000..016b04e540 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/secret/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html new file mode 100644 index 0000000000..2d17e8b596 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html @@ -0,0 +1,9 @@ +<HTML> +<HEAD> +<TITLE>/mnesia_secret/top_secret/index.html (04-Feb-1998)</TITLE> +<!-- Created by: Mattias Nilsson, 04-Feb-1998 --> +</HEAD> +<BODY> +<H1>/mnesia_secret/top_secret/index.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html new file mode 100644 index 0000000000..a6e8a35a04 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/open/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/open/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html new file mode 100644 index 0000000000..016b04e540 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html @@ -0,0 +1,10 @@ +<HTML> +<HEAD> +<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE> +<!-- Created by: Joakim Greben�, 17-Apr-1997 --> +<!-- Changed by: Joakim Greben�, 17-Apr-1997 --> +</HEAD> +<BODY> +<H1>/secret/dummy.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html new file mode 100644 index 0000000000..34db3d5d1a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html @@ -0,0 +1,9 @@ +<HTML> +<HEAD> +<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE> +<!-- Created by: Mattias Nilsson, 04-Feb-1998 --> +</HEAD> +<BODY> +<H1>/secret/top_secret/index.html</H1> +</BODY> +</HTML> diff --git a/lib/inets/test/httpd_SUITE_data/server_root/icons/README b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README index a1fc5a5a9c..a1fc5a5a9c 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/icons/README +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif Binary files differnew file mode 100644 index 0000000000..bb23d971f4 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif Binary files differnew file mode 100644 index 0000000000..eaecd2172a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif Binary files differnew file mode 100644 index 0000000000..a423894043 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif Binary files differnew file mode 100644 index 0000000000..3a1c139fc4 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif Binary files differnew file mode 100644 index 0000000000..a694ae1ec3 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif Binary files differnew file mode 100644 index 0000000000..eb84268c4c --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif Binary files differnew file mode 100644 index 0000000000..a8425cb574 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif Binary files differnew file mode 100644 index 0000000000..9a15cbae04 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif Binary files differnew file mode 100644 index 0000000000..62d0363108 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif Binary files differnew file mode 100644 index 0000000000..0ccf01e198 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif Binary files differnew file mode 100644 index 0000000000..270fdb1c06 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif Binary files differnew file mode 100644 index 0000000000..65dcd002ea --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif Binary files differnew file mode 100644 index 0000000000..c43bc4faec --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif Binary files differnew file mode 100644 index 0000000000..9f8cbe9f76 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif Binary files differnew file mode 100644 index 0000000000..fbdcf575f7 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif Binary files differnew file mode 100644 index 0000000000..eb97cb7333 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif Binary files differnew file mode 100644 index 0000000000..fe0c97998c --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif Binary files differnew file mode 100644 index 0000000000..7698455bf9 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif Binary files differnew file mode 100644 index 0000000000..a8b8319232 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif Binary files differnew file mode 100644 index 0000000000..0fd15a0d7f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif Binary files differnew file mode 100644 index 0000000000..64241e5c5d --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif Binary files differnew file mode 100644 index 0000000000..867cfd1212 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif Binary files differnew file mode 100644 index 0000000000..b3f5fb248f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif Binary files differnew file mode 100644 index 0000000000..7a308be8f6 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif Binary files differnew file mode 100644 index 0000000000..9acba576c0 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif Binary files differnew file mode 100644 index 0000000000..3883088e7a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif Binary files differnew file mode 100644 index 0000000000..c4dc3887db --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif Binary files differnew file mode 100644 index 0000000000..7555b6c164 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif Binary files differnew file mode 100644 index 0000000000..f8d76a8c23 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif Binary files differnew file mode 100644 index 0000000000..7664cd0364 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif Binary files differnew file mode 100644 index 0000000000..39e732739f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif Binary files differnew file mode 100644 index 0000000000..b0ffb7e0cc --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif Binary files differnew file mode 100644 index 0000000000..48264601ae --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif Binary files differnew file mode 100644 index 0000000000..a354c871cd --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif Binary files differnew file mode 100644 index 0000000000..791be33105 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif Binary files differnew file mode 100644 index 0000000000..fbe353c282 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif Binary files differnew file mode 100644 index 0000000000..48264601ae --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif Binary files differnew file mode 100644 index 0000000000..30979cb528 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif Binary files differnew file mode 100644 index 0000000000..75332d9e59 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif Binary files differnew file mode 100644 index 0000000000..b2959b4c85 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif Binary files differnew file mode 100644 index 0000000000..de60b2940f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif Binary files differnew file mode 100644 index 0000000000..94743981d9 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif Binary files differnew file mode 100644 index 0000000000..88d5240c3c --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif Binary files differnew file mode 100644 index 0000000000..5cdbc7206d --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif Binary files differnew file mode 100644 index 0000000000..85a5d68317 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif Binary files differnew file mode 100644 index 0000000000..35443fb63a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif Binary files differnew file mode 100644 index 0000000000..ad1686e448 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif Binary files differnew file mode 100644 index 0000000000..01e442bfa9 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif Binary files differnew file mode 100644 index 0000000000..751faeea36 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif Binary files differnew file mode 100644 index 0000000000..4f30484ff6 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif Binary files differnew file mode 100644 index 0000000000..162478fb3a --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif Binary files differnew file mode 100644 index 0000000000..c96338a152 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif Binary files differnew file mode 100644 index 0000000000..279e6710d4 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif Binary files differnew file mode 100644 index 0000000000..c5b6889a76 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif Binary files differnew file mode 100644 index 0000000000..0035183774 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif Binary files differnew file mode 100644 index 0000000000..7b917b4e91 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif Binary files differnew file mode 100644 index 0000000000..39bc90e795 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif Binary files differnew file mode 100644 index 0000000000..c88fd777c4 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif Binary files differnew file mode 100644 index 0000000000..6f7a0ae7a7 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif Binary files differnew file mode 100644 index 0000000000..03aa6be71e --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif Binary files differnew file mode 100644 index 0000000000..b04c5e0908 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif Binary files differnew file mode 100644 index 0000000000..4db9d023ed --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif Binary files differnew file mode 100644 index 0000000000..93471fdd88 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif Binary files differnew file mode 100644 index 0000000000..57aee93f07 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif Binary files differnew file mode 100644 index 0000000000..0dc327b569 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif Binary files differnew file mode 100644 index 0000000000..8661337f06 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif Binary files differnew file mode 100644 index 0000000000..59ddb34ce0 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif Binary files differnew file mode 100644 index 0000000000..0e6e506e00 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif Binary files differnew file mode 100644 index 0000000000..d324ab80ea --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif Binary files differnew file mode 100644 index 0000000000..0f565bc1db --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif Binary files differnew file mode 100644 index 0000000000..818a5cdc7e --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif Binary files differnew file mode 100644 index 0000000000..b256e5f75f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif Binary files differnew file mode 100644 index 0000000000..af6ba2b097 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif Binary files differnew file mode 100644 index 0000000000..06dccb3e44 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif Binary files differnew file mode 100644 index 0000000000..d8a853bc58 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif Binary files differnew file mode 100644 index 0000000000..8efb49f55d --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif Binary files differnew file mode 100644 index 0000000000..48e6a7fb2f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif Binary files differnew file mode 100644 index 0000000000..7067070da2 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif Binary files differnew file mode 100644 index 0000000000..a9e462a377 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif Binary files differnew file mode 100644 index 0000000000..4cfe0a5e0f --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif Binary files differnew file mode 100644 index 0000000000..a0c83cb85b --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif Binary files differnew file mode 100644 index 0000000000..617e779efa --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif Binary files differnew file mode 100644 index 0000000000..45e43233b8 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif Binary files differnew file mode 100644 index 0000000000..4c623909fb --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif Binary files differnew file mode 100644 index 0000000000..33697dbb66 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif Binary files differnew file mode 100644 index 0000000000..32b1ea23fb --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif Binary files differnew file mode 100644 index 0000000000..6d6d6d1ebf --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif Binary files differnew file mode 100644 index 0000000000..4387d529f6 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif Binary files differnew file mode 100644 index 0000000000..4387d529f6 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif Binary files differnew file mode 100644 index 0000000000..05b4ec2058 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif Binary files differnew file mode 100644 index 0000000000..e3203f7a88 --- /dev/null +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif diff --git a/lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip b/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip index 8d1c8b69c3..8d1c8b69c3 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip diff --git a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem index 427447958d..427447958d 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem diff --git a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem index 4aac86db49..4aac86db49 100644 --- a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 3c20348322..cbcf0362c9 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2001-2013. All Rights Reserved. +# Copyright Ericsson AB 2001-2014. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -18,7 +18,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.9.7 +INETS_VSN = 5.10 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" - |