diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/inets/test/httpd_SUITE.erl | 1275 |
1 files changed, 1275 insertions, 0 deletions
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index 854ffa8981..bc6b0d5c79 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -97,6 +97,1281 @@ groups() -> {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]}, {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, {custom, [], [customize]}, + {reload, [], [non_disturbing_reconfiger_dies, + disturbing_reconfiger_dies, + non_disturbing_1_1, + non_disturbing_1_0, + non_disturbing_0_9, + disturbing_1_1, + disturbing_1_0, + disturbing_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()} + ]. + +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, + content_length, + bad_hex, + missing_CR, + max_header, + max_content_length, + ipv6 + ]. + +load() -> + [light, medium + %%,heavy + ]. + +init_per_suite(Config) -> + PrivDir = ?config(priv_dir, Config), + 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), + {ok, Hostname0} = inet:gethostname(), + Inet = + case (catch ct:get_config(ipv6_hosts)) of + undefined -> + inet; + Hosts when is_list(Hosts) -> + case lists:member(list_to_atom(Hostname0), Hosts) of + true -> + inet6; + false -> + inet + end; + _ -> + inet + end, + [{server_root, ServerRoot}, + {doc_root, DocRoot}, + {ipfamily, Inet}, + {node, node()}, + {host, inets_test_lib:hostname()}, + {address, getaddr()} | Config]. + +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +init_per_group(Group, Config0) when Group == https_basic; + Group == https_limit; + Group == https_custom; + Group == https_basic_auth; + Group == https_auth_api; + Group == https_auth_api_dets; + Group == https_auth_api_mnesia; + Group == https_security; + Group == https_reload + -> + init_ssl(Group, Config0); +init_per_group(Group, Config0) when Group == http_basic; + Group == http_limit; + Group == http_custom; + Group == http_basic_auth; + Group == http_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == http_security; + Group == http_reload; + Group == http_mime_types + -> + 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_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; + Group == http_reload; + Group == http_mime_types + -> + inets:stop(); +end_per_group(Group, _Config) 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_htaccess; + Group == https_security; + Group == https_reload + -> + ssl:stop(), + inets:stop(); + +end_per_group(auth_api_mnesia, _) -> + cleanup_mnesia(); + +end_per_group(_, _) -> + ok. + +%%-------------------------------------------------------------------- +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. + +end_per_testcase(_Case, _Config) -> + ok. + +%%------------------------------------------------------------------------- +%% Test cases starts here. +%%------------------------------------------------------------------------- + +head() -> + [{doc, "HTTP HEAD request for static page"}]. + +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}]). + +get() -> + [{doc, "HTTP GET request for static page"}]. + +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}]). + +basic_auth_1_1(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/1.1"} | Config]). + +basic_auth_1_0(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/1.0"} | Config]). + +basic_auth_0_9(Config) when is_list(Config) -> + basic_auth([{http_version, "HTTP/0.9"} | Config]). + +basic_auth() -> + [{doc, "Test Basic authentication with WWW-Authenticate header"}]. + +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"}]), + + %% 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"), + + %% Test /*open, require user one Aladdin + remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "open"), + + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "one", "onePassword", Version, Host), Config, + [{statuscode, 401}]), + + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "two", "twoPassword", Version, Host), Config, + [{statuscode, 401}]), + + ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", + "Aladdin", "onePassword", Version, Host), + Config, [{statuscode, 401}]), + + 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. + +%%------------------------------------------------------------------------- +htaccess_1_1(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/1.1"} | Config]). + +htaccess_1_0(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/1.0"} | Config]). + +htaccess_0_9(Config) when is_list(Config) -> + htaccess([{http_version, "HTTP/0.9"} | Config]). + +htaccess() -> + [{doc, "Test mod_auth API"}]. + +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), + %% 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"}]), + + %% 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, + + %%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}]), + + 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, + 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_1_1() -> + [{doc, "Test mod_alias"}]. + +alias_1_1(Config) when is_list(Config) -> + alias([{http_version, "HTTP/1.1"} | Config]). + +alias_1_0() -> + [{doc, "Test mod_alias"}]. + +alias_1_0(Config) when is_list(Config) -> + alias([{http_version, "HTTP/1.0"} | Config]). + +alias_0_9() -> + [{doc, "Test mod_alias"}]. + +alias_0_9(Config) when is_list(Config) -> + alias([{http_version, "HTTP/0.9"} | Config]). + +alias() -> + [{doc, "Test mod_alias"}]. + +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"}]. + +actions(Config) when is_list(Config) -> + ok = http_status("GET /", Config, [{statuscode, 200}]). + +%%------------------------------------------------------------------------- +range() -> + [{doc, "Test Range header"}]. + +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"}]. + +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"}]. + +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)). +%%------------------------------------------------------------------------- +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). +%%------------------------------------------------------------------------- +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). +%%------------------------------------------------------------------------- +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), + 1000). +%%------------------------------------------------------------------------- +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}]). +%%------------------------------------------------------------------------- +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}]). +%%------------------------------------------------------------------------- +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}]). + +%%------------------------------------------------------------------------- +customize() -> + [{doc, "Test filtering of headers with custom callback"}]. + +customize(Config) when is_list(Config) -> + Version = "HTTP/1.1", + 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"}, + {no_header, "Server"}, + {version, Version}]). + +response_header({"server", _}) -> + false; +response_header(Header) -> + {true, Header}. + +%%------------------------------------------------------------------------- +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, not_implemented}; + _ -> + dos_hostname(?config(type, Config), ?config(port, Config), Host, + ?config(node, Config), Version, ?MAX_HEADER_SIZE) + end. + +%%------------------------------------------------------------------------- +max_content_length() -> + ["Denial Of Service (DOS) attack, prevented by max_content_length"]. +max_content_length(Config) when is_list(Config) -> + Version = ?config(http_version, Config), + Host = ?config(host, Config), + garbage_content_length(?config(type, Config), ?config(port, Config), Host, + ?config(node, Config), Version). + +%%------------------------------------------------------------------------- +security_1_1(Config) when is_list(Config) -> + security([{http_version, "HTTP/1.1"} | Config]). + +security_1_0(Config) when is_list(Config) -> + security([{http_version, "HTTP/1.0"} | Config]). + +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), + + OpenDir = filename:join([ServerRoot, "htdocs", "open"]), + + %% Test blocking / unblocking of users. + + %% /open, require user one Aladdin + remove_users(Node, ServerRoot, Host, Port, "", "open"), + + 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), + + 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, + + [{"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}]), + + %% Test list_auth_users & auth_timeout + + ["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), + + + ["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), + + %% Wait for successful auth to timeout. + test_server:sleep(?AUTH_TIMEOUT*1001), + + [] = list_auth_users(Node, Port), + + [] = list_auth_users(Node, Port, OpenDir), + + %% "two" is blocked. + + true = unblock_user(Node, "two", Port, OpenDir), + + + %% 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). + +%%------------------------------------------------------------------------- +non_disturbing_reconfiger_dies(Config) when is_list(Config) -> + do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], non_disturbing). +disturbing_reconfiger_dies(Config) when is_list(Config) -> + do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], disturbing). + +do_reconfiger_dies(Config, DisturbingType) -> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + + HttpdConfig = httpd:info(Server), + 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 + Pid = spawn(fun() -> httpd:reload_config([{server_name, "httpd_kill_" ++ Version}, + {port, Port}| + proplists:delete(server_name, HttpdConfig)], DisturbingType) + end), + + monitor(process, Pid), + exit(Pid, kill), + receive + {'DOWN', _, _, _, _} -> + ok + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_test"}] = httpd:info(Server, [server_name]). +%%------------------------------------------------------------------------- +disturbing_1_1(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/1.1"} | Config]). + +disturbing_1_0(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/1.0"} | Config]). + +disturbing_0_9(Config) when is_list(Config) -> + disturbing([{http_version, "HTTP/0.9"} | Config]). + +disturbing(Config) when is_list(Config)-> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + HttpdConfig = httpd:info(Server), + 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:reload_config([{server_name, "httpd_disturbing_" ++ Version}, {port, Port}| + proplists:delete(server_name, HttpdConfig)], disturbing), + Close = list_to_atom((typestr(Type)) ++ "_closed"), + receive + {Close, Socket} -> + ok; + Msg -> + ct:fail({{expected, {Close, Socket}}, {got, Msg}}) + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). +%%------------------------------------------------------------------------- +non_disturbing_1_1(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/1.1"} | Config]). + +non_disturbing_1_0(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/1.0"} | Config]). + +non_disturbing_0_9(Config) when is_list(Config) -> + non_disturbing([{http_version, "HTTP/0.9"} | Config]). + +non_disturbing(Config) when is_list(Config)-> + Server = ?config(server_pid, Config), + Version = ?config(http_version, Config), + Host = ?config(host, Config), + Port = ?config(port, Config), + Type = ?config(type, Config), + + HttpdConfig = httpd:info(Server), + 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:reload_config([{server_name, "httpd_non_disturbing_" ++ Version}, {port, Port}| + proplists:delete(server_name, HttpdConfig)], non_disturbing), + Transport = type(Type), + receive + {Transport, Socket, Msg} -> + ct:pal("Received message ~p~n", [Msg]), + ok + after 2000 -> + ct:fail(timeout) + end, + inets_test_lib:close(Type, Socket), + [{server_name, "httpd_non_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). + + +%%-------------------------------------------------------------------- +%% Internal functions ----------------------------------- +%%-------------------------------------------------------------------- +url(http, End, Config) -> + Port = ?config(port, Config), + {ok,Host} = inet:gethostname(), + ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End. + +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"), + ConfigDir = filename:join(ServerRoot, "config"), + + 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), + ok = file:make_dir(ConfigDir), + + 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"), + ConfigSrc = filename:join(DataDir, "server_root/config"), + + 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), + inets_test_lib:copy_dirs(ConfigSrc, ConfigDir), + + Cgi = case test_server:os_type() of + {win32, _} -> + "cgi_echo.exe"; + _ -> + "cgi_echo" + end, + + 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}), + + 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}). + +start_apps(Group) when Group == https_basic; + Group == https_limit; + Group == https_custom; + Group == https_basic_auth; + Group == https_auth_api; + Group == https_auth_api_dets; + Group == https_auth_api_mnesia; + Group == https_htaccess; + Group == https_security; + Group == https_reload + -> + inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]); +start_apps(Group) when Group == http_basic; + Group == http_limit; + Group == http_custom; + Group == http_basic_auth; + Group == http_auth_api; + Group == http_auth_api_dets; + Group == http_auth_api_mnesia; + Group == https_htaccess; + Group == https_security; + Group == https_reload; + Group == http_mime_types-> inets_test_lib:start_apps([inets]). server_start(_, HttpdConfig) -> |