aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/Makefile2
-rw-r--r--lib/inets/doc/src/Makefile22
-rw-r--r--lib/inets/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/inets/doc/src/book.xml2
-rw-r--r--lib/inets/doc/src/fascicules.xml19
-rw-r--r--lib/inets/doc/src/ftp.xml2
-rw-r--r--lib/inets/doc/src/ftp_client.xml2
-rw-r--r--lib/inets/doc/src/http_client.xml2
-rw-r--r--lib/inets/doc/src/http_server.xml36
-rw-r--r--lib/inets/doc/src/http_uri.xml23
-rw-r--r--lib/inets/doc/src/httpc.xml12
-rw-r--r--lib/inets/doc/src/httpd.xml31
-rw-r--r--lib/inets/doc/src/httpd_socket.xml2
-rw-r--r--lib/inets/doc/src/httpd_util.xml2
-rw-r--r--lib/inets/doc/src/inets.gifbin9763 -> 0 bytes
-rw-r--r--lib/inets/doc/src/inets.xml2
-rw-r--r--lib/inets/doc/src/inets_services.xml2
-rw-r--r--lib/inets/doc/src/introduction.xml2
-rw-r--r--lib/inets/doc/src/min_head.gifbin2652 -> 0 bytes
-rw-r--r--lib/inets/doc/src/mod_alias.xml2
-rw-r--r--lib/inets/doc/src/mod_auth.xml4
-rw-r--r--lib/inets/doc/src/mod_esi.xml193
-rw-r--r--lib/inets/doc/src/mod_security.xml2
-rw-r--r--lib/inets/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/inets/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/inets/doc/src/notes.xml401
-rw-r--r--lib/inets/doc/src/notes_history.xml2
-rw-r--r--lib/inets/doc/src/part.xml2
-rw-r--r--lib/inets/doc/src/part_notes.xml40
-rw-r--r--lib/inets/doc/src/part_notes_history.xml35
-rw-r--r--lib/inets/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/inets/doc/src/summary.html.src1
-rw-r--r--lib/inets/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/inets/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/inets/examples/Makefile2
-rw-r--r--lib/inets/examples/httpd_load_test/Makefile2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt.sh.skel2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_client.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_ctrl.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_logger.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_logger.hrl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_server.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_slave.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/modules.mk2
-rw-r--r--lib/inets/examples/server_root/Makefile2
-rw-r--r--lib/inets/examples/server_root/conf/8080.conf2
-rw-r--r--lib/inets/examples/server_root/conf/8888.conf2
-rw-r--r--lib/inets/examples/server_root/conf/httpd.conf4
-rw-r--r--lib/inets/examples/server_root/conf/ssl.conf2
-rw-r--r--lib/inets/include/httpd.hrl2
-rw-r--r--lib/inets/include/mod_auth.hrl2
-rw-r--r--lib/inets/priv/Makefile2
-rw-r--r--lib/inets/src/Makefile2
-rw-r--r--lib/inets/src/ftp/Makefile2
-rw-r--r--lib/inets/src/ftp/ftp.erl199
-rw-r--r--lib/inets/src/ftp/ftp_internal.hrl2
-rw-r--r--lib/inets/src/ftp/ftp_progress.erl28
-rw-r--r--lib/inets/src/ftp/ftp_response.erl21
-rw-r--r--lib/inets/src/ftp/ftp_sup.erl2
-rw-r--r--lib/inets/src/http_client/Makefile2
-rw-r--r--lib/inets/src/http_client/httpc.erl104
-rw-r--r--lib/inets/src/http_client/httpc_cookie.erl2
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl827
-rw-r--r--lib/inets/src/http_client/httpc_handler_sup.erl2
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl53
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl6
-rw-r--r--lib/inets/src/http_client/httpc_profile_sup.erl2
-rw-r--r--lib/inets/src/http_client/httpc_request.erl31
-rw-r--r--lib/inets/src/http_client/httpc_response.erl82
-rw-r--r--lib/inets/src/http_client/httpc_sup.erl2
-rw-r--r--lib/inets/src/http_lib/Makefile2
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl2
-rw-r--r--lib/inets/src/http_lib/http_internal.hrl5
-rw-r--r--lib/inets/src/http_lib/http_request.erl20
-rw-r--r--lib/inets/src/http_lib/http_response.erl2
-rw-r--r--lib/inets/src/http_lib/http_transport.erl2
-rw-r--r--lib/inets/src/http_lib/http_uri.erl75
-rw-r--r--lib/inets/src/http_lib/http_util.erl6
-rw-r--r--lib/inets/src/http_server/httpd.erl11
-rw-r--r--lib/inets/src/http_server/httpd.hrl2
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl2
-rw-r--r--lib/inets/src/http_server/httpd_acceptor_sup.erl2
-rw-r--r--lib/inets/src/http_server/httpd_cgi.erl2
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl14
-rw-r--r--lib/inets/src/http_server/httpd_connection_sup.erl2
-rw-r--r--lib/inets/src/http_server/httpd_esi.erl29
-rw-r--r--lib/inets/src/http_server/httpd_example.erl40
-rw-r--r--lib/inets/src/http_server/httpd_file.erl2
-rw-r--r--lib/inets/src/http_server/httpd_instance_sup.erl2
-rw-r--r--lib/inets/src/http_server/httpd_internal.hrl2
-rw-r--r--lib/inets/src/http_server/httpd_log.erl2
-rw-r--r--lib/inets/src/http_server/httpd_manager.erl2
-rw-r--r--lib/inets/src/http_server/httpd_misc_sup.erl2
-rw-r--r--lib/inets/src/http_server/httpd_request.erl48
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl184
-rw-r--r--lib/inets/src/http_server/httpd_response.erl29
-rw-r--r--lib/inets/src/http_server/httpd_script_env.erl16
-rw-r--r--lib/inets/src/http_server/httpd_socket.erl2
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl2
-rw-r--r--lib/inets/src/http_server/httpd_util.erl6
-rw-r--r--lib/inets/src/http_server/mod_actions.erl2
-rw-r--r--lib/inets/src/http_server/mod_alias.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth.hrl2
-rw-r--r--lib/inets/src/http_server/mod_auth_dets.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth_mnesia.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth_plain.erl2
-rw-r--r--lib/inets/src/http_server/mod_auth_server.erl4
-rw-r--r--lib/inets/src/http_server/mod_browser.erl2
-rw-r--r--lib/inets/src/http_server/mod_cgi.erl2
-rw-r--r--lib/inets/src/http_server/mod_dir.erl2
-rw-r--r--lib/inets/src/http_server/mod_disk_log.erl29
-rw-r--r--lib/inets/src/http_server/mod_esi.erl184
-rw-r--r--lib/inets/src/http_server/mod_get.erl2
-rw-r--r--lib/inets/src/http_server/mod_head.erl2
-rw-r--r--lib/inets/src/http_server/mod_htaccess.erl6
-rw-r--r--lib/inets/src/http_server/mod_log.erl6
-rw-r--r--lib/inets/src/http_server/mod_range.erl2
-rw-r--r--lib/inets/src/http_server/mod_responsecontrol.erl2
-rw-r--r--lib/inets/src/http_server/mod_security.erl2
-rw-r--r--lib/inets/src/http_server/mod_security_server.erl2
-rw-r--r--lib/inets/src/http_server/mod_trace.erl2
-rw-r--r--lib/inets/src/inets_app/Makefile6
-rw-r--r--lib/inets/src/inets_app/inets.app.src4
-rw-r--r--lib/inets/src/inets_app/inets.appup.src6
-rw-r--r--lib/inets/src/inets_app/inets.erl2
-rw-r--r--lib/inets/src/inets_app/inets.mk2
-rw-r--r--lib/inets/src/inets_app/inets_app.erl2
-rw-r--r--lib/inets/src/inets_app/inets_internal.hrl2
-rw-r--r--lib/inets/src/inets_app/inets_lib.erl4
-rw-r--r--lib/inets/src/inets_app/inets_regexp.erl414
-rw-r--r--lib/inets/src/inets_app/inets_service.erl2
-rw-r--r--lib/inets/src/inets_app/inets_sup.erl2
-rw-r--r--lib/inets/src/inets_app/inets_time_compat.erl72
-rw-r--r--lib/inets/src/tftp/Makefile2
-rw-r--r--lib/inets/src/tftp/tftp.erl2
-rw-r--r--lib/inets/src/tftp/tftp.hrl2
-rw-r--r--lib/inets/src/tftp/tftp_binary.erl2
-rw-r--r--lib/inets/src/tftp/tftp_engine.erl5
-rw-r--r--lib/inets/src/tftp/tftp_file.erl2
-rw-r--r--lib/inets/src/tftp/tftp_lib.erl2
-rw-r--r--lib/inets/src/tftp/tftp_logger.erl4
-rw-r--r--lib/inets/src/tftp/tftp_sup.erl4
-rw-r--r--lib/inets/test/Makefile7
-rw-r--r--lib/inets/test/erl_make_certs.erl2
-rw-r--r--lib/inets/test/ftp_SUITE.erl765
-rw-r--r--lib/inets/test/ftp_format_SUITE.erl126
-rw-r--r--lib/inets/test/ftp_property_test_SUITE.erl2
-rw-r--r--lib/inets/test/ftp_suite_lib.erl1696
-rw-r--r--lib/inets/test/http_format_SUITE.erl17
-rw-r--r--lib/inets/test/httpc_SUITE.erl278
-rw-r--r--lib/inets/test/httpc_cookie_SUITE.erl373
-rw-r--r--lib/inets/test/httpc_proxy_SUITE.erl18
-rw-r--r--lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf2
-rwxr-xr-xlib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh2
-rw-r--r--lib/inets/test/httpd_1_0.erl2
-rw-r--r--lib/inets/test/httpd_1_1.erl14
-rw-r--r--lib/inets/test/httpd_SUITE.erl621
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl48
-rw-r--r--lib/inets/test/httpd_block.erl4
-rw-r--r--lib/inets/test/httpd_load.erl9
-rw-r--r--lib/inets/test/httpd_mod.erl196
-rw-r--r--lib/inets/test/httpd_mod_SUITE.erl2
-rw-r--r--lib/inets/test/httpd_poll.erl2
-rw-r--r--lib/inets/test/httpd_test_data/server_root/Makefile2
-rw-r--r--lib/inets/test/httpd_test_data/server_root/conf/8080.conf2
-rw-r--r--lib/inets/test/httpd_test_data/server_root/conf/8888.conf2
-rw-r--r--lib/inets/test/httpd_test_data/server_root/conf/httpd.conf6
-rw-r--r--lib/inets/test/httpd_test_data/server_root/conf/ssl.conf2
-rw-r--r--lib/inets/test/httpd_test_lib.erl2
-rw-r--r--lib/inets/test/httpd_time_test.erl4
-rw-r--r--lib/inets/test/inets_SUITE.erl131
-rw-r--r--lib/inets/test/inets_app_test.erl245
-rw-r--r--lib/inets/test/inets_appup_test.erl71
-rw-r--r--lib/inets/test/inets_socketwrap_SUITE.erl8
-rw-r--r--lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c2
-rw-r--r--lib/inets/test/inets_sup_SUITE.erl109
-rw-r--r--lib/inets/test/inets_test_lib.hrl90
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl491
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/Makefile2
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf2
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf2
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf6
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf2
-rw-r--r--lib/inets/test/property_test/ftp_simple_client_server.erl2
-rw-r--r--lib/inets/test/tftp_SUITE.erl2
-rw-r--r--lib/inets/test/tftp_test_lib.erl2
-rw-r--r--lib/inets/test/tftp_test_lib.hrl2
-rw-r--r--lib/inets/test/uri_SUITE.erl106
-rw-r--r--lib/inets/vsn.mk4
191 files changed, 3689 insertions, 5373 deletions
diff --git a/lib/inets/Makefile b/lib/inets/Makefile
index 3fff719cf3..872df9d055 100644
--- a/lib/inets/Makefile
+++ b/lib/inets/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index cb71fbeb9c..14f12ee949 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -58,7 +58,7 @@ XML_REF3_FILES = \
mod_alias.xml \
mod_auth.xml \
mod_esi.xml \
- mod_security.xml
+ mod_security.xml
XML_PART_FILES = \
part.xml
@@ -83,7 +83,7 @@ HTML_FILES = \
$(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
+EXTRA_FILES = \
$(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
$(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \
$(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
@@ -95,10 +95,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -119,25 +119,25 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-man: $(MAN3_FILES)
+man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
-clean_pdf:
+clean_pdf:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
-clean_html:
+clean_html:
rm -rf $(TOP_HTML_FILES) $(HTMLDIR)/*
clean_man:
- rm -f $(MAN3_FILES)
+ rm -f $(MAN3_FILES)
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/inets/doc/src/book.gif b/lib/inets/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/inets/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/book.xml b/lib/inets/doc/src/book.xml
index 80db82ee45..29f0c6a6d8 100644
--- a/lib/inets/doc/src/book.xml
+++ b/lib/inets/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</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
deleted file mode 100644
index c075478967..0000000000
--- a/lib/inets/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml
index f64bc0e18b..42bece4d38 100644
--- a/lib/inets/doc/src/ftp.xml
+++ b/lib/inets/doc/src/ftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</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 89e66db814..990dd68604 100644
--- a/lib/inets/doc/src/ftp_client.xml
+++ b/lib/inets/doc/src/ftp_client.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</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 f4d7b751ac..212958f17f 100644
--- a/lib/inets/doc/src/http_client.xml
+++ b/lib/inets/doc/src/http_client.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</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 aeda961714..65b3dcde95 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2015</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,8 +40,8 @@
<item>Secure Sockets Layer (SSL)</item>
<item>Erlang Scripting Interface (ESI)</item>
<item>Common Gateway Interface (CGI)</item>
- <item>User Authentication (using <c>Mnesia</c>,
- <c>Dets</c> or plain text database)</item>
+ <item>User Authentication (using Mnesia,
+ Dets or plain text database)</item>
<item>Common Logfile Format (with or without disk_log(3) support)</item>
<item>URL Aliasing</item>
<item>Action Mappings</item>
@@ -563,7 +563,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<title>mod_auth - User Authentication</title>
<p>The <seealso marker="mod_auth">mod_auth(3)</seealso>
module provides for basic user authentication using
- textual files, <c>Dets</c> databases as well as <c>Mnesia</c> databases.</p>
+ textual files, Dets databases as well as Mnesia databases.</p>
<p>Uses the following Erlang Web Server API interaction data:
</p>
<list type="bulleted">
@@ -580,15 +580,15 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<section>
<title>Mnesia As Authentication Database</title>
- <p>If <c>Mnesia</c> is used as storage method, <c>Mnesia</c> must be
- started before the HTTP server. The first time <c>Mnesia</c> is
+ <p>If Mnesia is used as storage method, Mnesia must be
+ started before the HTTP server. The first time Mnesia is
started, the schema and the tables must be created before
- <c>Mnesia</c> is started. A simple example of a module with two
- functions that creates and start <c>Mnesia</c> is provided
+ Mnesia is started. A simple example of a module with two
+ functions that creates and start Mnesia is provided
here. Function <c>first_start/0</c> is to be used the first
time. It creates the schema and the tables.
<c>start/0</c> is to be used in consecutive startups.
- <c>start/0</c> starts <c>Mnesia</c> and waits for the tables to
+ <c>start/0</c> starts Mnesia and waits for the tables to
be initiated. This function must only be used when the
schema and the tables are already created.</p>
@@ -616,25 +616,25 @@ start() ->
mnesia:start(),
mnesia:wait_for_tables([httpd_user, httpd_group], 60000). </code>
- <p>To create the <c>Mnesia</c> tables, we use two records defined in
+ <p>To create the Mnesia tables, we use two records defined in
<c>mod_auth.hrl</c>, so that file must be included. <c>first_start/0</c>
creates a schema that specifies on which nodes the database is to reside.
- Then it starts <c>Mnesia</c> and creates the tables. The first argument
+ Then it starts Mnesia and creates the tables. The first argument
is the name of the tables, the second argument is a list of options of
how to create the table, see
- <seealso marker="mnesia:mnesia"><c>mnesia</c></seealso>, documentation for
+ <seealso marker="mnesia:mnesia"><c>mnesia(3)</c></seealso>, documentation for
more information. As the implementation of the <c>mod_auth_mnesia</c>
saves one row for each user, the type must be <c>bag</c>.
When the schema and the tables are created, function
<seealso marker="mnesia:mnesia#start-0">mnesia:start/0</seealso>
- is used to start <c>Mnesia</c> and
- waits for the tables to be loaded. <c>Mnesia</c> uses the
+ is used to start Mnesia and
+ waits for the tables to be loaded. Mnesia uses the
directory specified as <c>mnesia_dir</c> at startup if specified,
- otherwise <c>Mnesia</c> uses the current directory. For security
- reasons, ensure that the <c>Mnesia</c> tables are stored outside
+ otherwise Mnesia uses the current directory. For security
+ reasons, ensure that the Mnesia tables are stored outside
the document tree of the HTTP server. If they are placed in the
directory which it protects, clients can download the tables.
- Only the <c>Dets</c> and <c>Mnesia</c> storage
+ Only the Dets and Mnesia storage
methods allow writing of dynamic user data to disk. <c>plain</c> is
a read only method.</p>
</section>
@@ -669,7 +669,7 @@ start() ->
<section>
<title>mod_disk_log - Logging Using Disk_Log.</title>
<p>Standard logging using the "Common Logfile Format" and
- <seealso marker="kernel:disk_log">kernel:disk_log(3)</seealso>.</p>
+ <seealso marker="kernel:disk_log">disk_log(3)</seealso>.</p>
<p>Uses the following Erlang Web Server API interaction data:
</p>
<list type="bulleted">
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 8e0301c520..20c042c202 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2012</year><year>2015</year>
+ <year>2012</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,6 +45,7 @@
this module:</p>
<p><c>boolean() = true | false</c></p>
<p><c>string()</c> = list of ASCII characters</p>
+ <p><c>unicode_binary()</c> = binary() with characters encoded in the UTF-8 coding standard</p>
</section>
@@ -53,22 +54,22 @@
<p>Type definitions that are related to URI:</p>
<taglist>
- <tag><c>uri() = string()</c></tag>
+ <tag><c>uri() = string() | unicode:unicode_binary()</c></tag>
<item><p>Syntax according to the URI definition in RFC 3986,
for example, "http://www.erlang.org/"</p></item>
- <tag><c>user_info() = string()</c></tag>
+ <tag><c>user_info() = string() | unicode:unicode_binary()</c></tag>
<item><p></p></item>
<tag><c>scheme() = atom()</c></tag>
<item><p>Example: http, https</p></item>
- <tag><c>host() = string()</c></tag>
+ <tag><c>host() = string() | unicode:unicode_binary()</c></tag>
<item><p></p></item>
<tag><c>port() = pos_integer()</c></tag>
<item><p></p></item>
- <tag><c>path() = string()</c></tag>
+ <tag><c>path() = string() | unicode:unicode_binary()</c></tag>
<item><p>Represents a file path or directory path</p></item>
- <tag><c>query() = string()</c></tag>
+ <tag><c>query() = string() | unicode:unicode_binary()</c></tag>
<item><p></p></item>
- <tag><c>fragment() = string()</c></tag>
+ <tag><c>fragment() = string() | unicode:unicode_binary()</c></tag>
<item><p></p></item>
</taglist>
@@ -83,7 +84,7 @@
<fsummary>Decodes a hexadecimal encoded URI.</fsummary>
<type>
- <v>HexEncodedURI = string() - A possibly hexadecimal encoded URI</v>
+ <v>HexEncodedURI = string() | unicode:unicode_binary() - A possibly hexadecimal encoded URI</v>
<v>URI = uri()</v>
</type>
@@ -98,7 +99,7 @@
<fsummary>Encodes a hexadecimal encoded URI.</fsummary>
<type>
<v>URI = uri()</v>
- <v>HexEncodedURI = string() - Hexadecimal encoded URI</v>
+ <v>HexEncodedURI = string() | unicode:unicode_binary() - Hexadecimal encoded URI</v>
</type>
<desc>
@@ -118,7 +119,7 @@
<v>Option = {ipv6_host_with_brackets, boolean()} |
{scheme_defaults, scheme_defaults()} |
{fragment, boolean()} |
- {schema_validation_fun, fun()}]</v>
+ {scheme_validation_fun, fun()}]</v>
<v>Result = {Scheme, UserInfo, Host, Port, Path, Query} |
{Scheme, UserInfo, Host, Port, Path, Query, Fragment}</v>
<v>UserInfo = user_info()</v>
@@ -145,7 +146,7 @@
<p>Scheme validation fun is to be defined as follows:</p>
<code>
-fun(SchemeStr :: string()) ->
+fun(SchemeStr :: string() | unicode:unicode_binary()) ->
valid | {error, Reason :: term()}.
</code>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index ca9b268a03..29e4b22632 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2015</year>
+ <year>2004</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -68,11 +68,11 @@
this module:</p>
<p><c>boolean() = true | false</c></p>
<p><c>string()</c> = list of ASCII characters</p>
- <p><c>request_id() = ref()</c></p>
+ <p><c>request_id() = reference()</c></p>
<p><c>profile() = atom()</c></p>
<p><c>path() = string()</c> representing a file path or directory path</p>
<p><c>ip_address()</c> = See the
- <seealso marker="kernel:inet">inet(3)</seealso> manual page in <c>Kernel</c>.</p>
+ <seealso marker="kernel:inet">inet(3)</seealso> manual page in Kernel.</p>
<p><c>socket_opt()</c> = See the options used by
<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> <c>gen_tcp(3)</c> and
<seealso marker="ssl:ssl">ssl(3)</seealso> connect(s)</p>
@@ -83,7 +83,7 @@
<title>HTTP DATA TYPES</title>
<p>Type definitions related to HTTP:</p>
- <p><c>method() = head | get | put | post | trace | options | delete</c></p>
+ <p><c>method() = head | get | put | post | trace | options | delete | patch</c></p>
<taglist>
<tag><c>request()</c></tag>
<item><p>= <c>{url(), headers()}</c></p>
@@ -344,7 +344,7 @@
<tag><c><![CDATA[ssl]]></c></tag>
<item>
<p>This is the <c>SSL/TLS</c> connectin configuration option.</p>
- <p>Defaults to <c>[]</c>. See <seealso marker="ssl:ssl">ssl:connect/[2, 3,4]</seealso> for availble options.</p>
+ <p>Defaults to <c>[]</c>. See <seealso marker="ssl:ssl">ssl:connect/[2,3,4]</seealso> for available options.</p>
</item>
<tag><c><![CDATA[autoredirect]]></c></tag>
@@ -408,7 +408,7 @@
<c>{self, once}</c>, the first message has an extra
element, that is, <c>{http, {RequestId, stream_start, Headers, Pid}}</c>.
This is the process id to be used as an argument to
- <c>http:stream_next/1</c> to trigger the next message to be sent to
+ <c>httpc:stream_next/1</c> to trigger the next message to be sent to
the calling process.</p>
<p>Notice that chunked encoding can add
headers so that there are more headers in the <c>stream_end</c>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 62b92b8356..edf8731a82 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2015</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -279,7 +279,18 @@
requests defined by <c>max_keep_alive_requests</c>, the server
closes the connection. The server closes it even if there are
queued request. Default is no limit.</p>
- </item>
+ </item>
+
+
+ <tag><marker id="max_client_body_chunk"></marker>{max_client_body_chunk, integer()}</tag>
+ <item>
+ <p>Enforces chunking of a HTTP PUT or POST body data to be deliverd
+ to the mod_esi callback. Note this is not supported for mod_cgi.
+ Default is no limit e.i the whole body is deliverd as one entity, which could
+ be very memory consuming. <seealso marker="mod_esi">mod_esi(3)</seealso>.
+ </p>
+ </item>
+
</taglist>
<marker id="props_admin"></marker>
@@ -455,7 +466,7 @@ text/plain asc txt</pre>
directory. Several files can be given, in which case the server
returns the first it finds, for example:</p>
- <code>{directory_index, ["index.hml", "welcome.html"]}</code>
+ <code>{directory_index, ["index.html", "welcome.html"]}</code>
<p>Access to http://your.server.org/docs/ would return
http://your.server.org/docs/index.html or
@@ -711,7 +722,7 @@ text/plain asc txt</pre>
<item>
<p>Sets the type of authentication database that is used for the
directory. The key difference between the different methods is
- that dynamic data can be saved when <c>Mnesia</c> and <c>Dets</c>
+ that dynamic data can be saved when Mnesia and Dets
are used.
This property is called <c>AuthDbType</c> in the Apache-like
configuration files.</p>
@@ -731,10 +742,10 @@ text/plain asc txt</pre>
<code> ragnar:s7Xxv7
edward:wwjau8 </code>
- <p>If the <c>Dets</c> storage method is used, the user database is
- maintained by <c>Dets</c> and must not be edited by hand. Use the
+ <p>If the Dets storage method is used, the user database is
+ maintained by Dets and must not be edited by hand. Use the
API functions in module <c>mod_auth</c> to create/edit the user
- database. This directive is ignored if the <c>Mnesia</c>
+ database. This directive is ignored if the Mnesia
storage method is used. For security reasons, ensure that
<c>auth_user_file</c> is stored outside the document tree of the web
server. If it is placed in the directory that it protects,
@@ -753,10 +764,10 @@ text/plain asc txt</pre>
<code>group1: bob joe ante</code>
- <p>If the <c>Dets</c> storage method is used, the group database is
- maintained by <c>Dets</c> and must not be edited by hand. Use the
+ <p>If the Dets storage method is used, the group database is
+ maintained by Dets and must not be edited by hand. Use the
API for module <c>mod_auth</c> to create/edit the group database.
- This directive is ignored if the <c>Mnesia</c> storage method is used.
+ This directive is ignored if the Mnesia storage method is used.
For security reasons, ensure that the <c>auth_group_file</c> is
stored outside the document tree of the web server. If it is
placed in the directory that it protects, clients
diff --git a/lib/inets/doc/src/httpd_socket.xml b/lib/inets/doc/src/httpd_socket.xml
index f71dac90b2..d3aa82a540 100644
--- a/lib/inets/doc/src/httpd_socket.xml
+++ b/lib/inets/doc/src/httpd_socket.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</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 0f498ba2fc..220a2ede35 100644
--- a/lib/inets/doc/src/httpd_util.xml
+++ b/lib/inets/doc/src/httpd_util.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/inets.gif b/lib/inets/doc/src/inets.gif
deleted file mode 100644
index 64968ae68a..0000000000
--- a/lib/inets/doc/src/inets.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml
index 5d071c9a48..137381cbe9 100644
--- a/lib/inets/doc/src/inets.xml
+++ b/lib/inets/doc/src/inets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2013</year>
+ <year>2007</year><year>2016</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 d100216ebb..da60c01aa2 100644
--- a/lib/inets/doc/src/inets_services.xml
+++ b/lib/inets/doc/src/inets_services.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/introduction.xml b/lib/inets/doc/src/introduction.xml
index 491835f852..1af2ef5dae 100644
--- a/lib/inets/doc/src/introduction.xml
+++ b/lib/inets/doc/src/introduction.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/min_head.gif b/lib/inets/doc/src/min_head.gif
deleted file mode 100644
index 67948a6378..0000000000
--- a/lib/inets/doc/src/min_head.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml
index 87c950cc6b..6ae19700a5 100644
--- a/lib/inets/doc/src/mod_alias.xml
+++ b/lib/inets/doc/src/mod_alias.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</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 2da2be37ed..c4f844622b 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,7 @@
<modulesummary>User authentication using text files, Dets, or Mnesia database.</modulesummary>
<description>
<p>This module provides for basic user authentication using
- textual files, <c>Dets</c> databases, or <c>Mnesia</c> databases.</p>
+ textual files, Dets databases, or Mnesia databases.</p>
</description>
<funcs>
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index c2fb60c416..d024c8afa8 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,8 +42,7 @@
<taglist>
<tag><c>env() = </c></tag>
<item> <p><c>{EnvKey()::atom(), Value::term()}</c></p>
- </item>
-
+
<p>Currently supported key value pairs</p>
<taglist>
@@ -59,15 +58,16 @@
<tag><c>{server_protocol, string()}</c></tag>
<item><p> HTTP version, currently "HTTP/1.1"</p></item>
- <tag>{server_port, integer()}</tag>
+ <tag><c>{server_port, integer()}</c></tag>
<item><p>Servers port number.</p></item>
- <tag><c>{request_method, "GET | "PUT" | "DELETE | "POST" | "PATCH"}</c></tag>
-
+ <tag><c>{request_method, "GET | "PUT" | "DELETE" | "POST" | "PATCH"}</c></tag>
+ <item><p>HTTP request method.</p></item>
+
<tag><c>{remote_adress, inet:ip_address()} </c></tag>
<item><p>The clients ip address.</p></item>
- <tag><c>{peer_cert, undefined | no_peercert | DER:binary()</c></tag>
+ <tag><c>{peer_cert, undefined | no_peercert | DER:binary()}</c></tag>
<item>
<p>For TLS connections where client certificates are used this will
be an ASN.1 DER-encoded X509-certificate as an Erlang binary.
@@ -81,94 +81,121 @@
<tag><c>{http_LowerCaseHTTPHeaderName, string()}</c></tag>
<item><p>example: {http_content_type, "text/html"}</p></item>
- </taglist>
-
+ </taglist>
+ </item>
</taglist>
+ </section>
- <funcs>
- <func>
- <name>deliver(SessionID, Data) -> ok | {error, Reason}</name>
- <fsummary>Sends <c>Data</c> back to client.</fsummary>
- <type>
+ <funcs>
+ <func>
+ <name>deliver(SessionID, Data) -> ok | {error, Reason}</name>
+ <fsummary>Sends <c>Data</c> back to client.</fsummary>
+ <type>
<v>SessionID = term()</v>
<v>Data = string() | io_list() | binary()</v>
<v>Reason = term()</v>
- </type>
- <desc>
- <marker id="deliver"></marker>
- <p>This function is <em>only</em> intended to be used from
- functions called by the Erl Scheme interface to deliver
- parts of the content to the user.</p>
- <p>Sends data from an Erl Scheme script back to the client.</p>
+ </type>
+ <desc>
+ <marker id="deliver"></marker>
+ <p>This function is <em>only</em> intended to be used from
+ functions called by the Erl Scheme interface to deliver
+ parts of the content to the user.</p>
+ <p>Sends data from an Erl Scheme script back to the client.</p>
- <note>
- <p>If any HTTP header fields are added by the
- script, they must be in the first call to <c>deliver/2</c>,
- and the data in the call must be a string. Calls after the headers
- are complete can contain binary data to reduce copying
- overhead. Do not assume anything about the data type of
- <c>SessionID</c>. <c>SessionID</c> must be the value given
- as input to the ESI callback function that you implemented.</p>
- </note>
- </desc>
- </func>
- </funcs>
- </section>
- <section>
- <title>ESI Callback Functions</title>
- </section>
- <funcs>
- <func>
- <name>Module:Function(SessionID, Env, Input)-> _ </name>
- <fsummary>Creates a dynamic web page and returns it chunk by chunk
- to the server process by calling <c>mod_esi:deliver/2</c>.</fsummary>
- <type>
- <v>SessionID = term()</v>
- <v>Env = env()</v>
- <v>Input = string()</v>
- </type>
+ <note>
+ <p>If any HTTP header fields are added by the
+ script, they must be in the first call to <c>deliver/2</c>,
+ and the data in the call must be a string. Calls after the headers
+ are complete can contain binary data to reduce copying
+ overhead. Do not assume anything about the data type of
+ <c>SessionID</c>. <c>SessionID</c> must be the value given
+ as input to the ESI callback function that you implemented.</p>
+ </note>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>ESI Callback Functions</title>
+ </section>
+
+ <funcs>
+ <func>
+ <name>Module:Function(SessionID, Env, Input)-> {continue, State} | _ </name>
+ <fsummary>Creates a dynamic web page and returns it chunk by chunk
+ to the server process by calling <c>mod_esi:deliver/2</c>.</fsummary>
+ <type>
+ <v>SessionID = term()</v>
+ <v>Env = env()</v>
+ <v>Input = string() | chunked_data()</v>
+ <v>chunked_data() = {first, Data::binary()} |
+ {continue, Data::binary(), State::term()} |
+ {last, Data::binary(), State::term()} </v>
+ <v>State = term()</v>
+ </type>
<desc>
<p><c>Module</c> must be found in the code path and export
- <c>Function</c> with an arity of three. An <c>erlScriptAlias</c> must
- also be set up in the configuration file for the web server.</p>
- <p>If the HTTP request is a 'post' request and a body is sent,
- <c>content_length</c> is the length of the posted
- data. If 'get' is used, <c>query_string</c> is the data after
- <em>?</em> in the URL.</p>
- <p><c>ParsedHeader</c> is the HTTP request as a key-value tuple
- list. The keys in <c>ParsedHeader</c> are in lower case.</p>
- <p><c>SessionID</c> is an identifier
- the server uses when <c>deliver/2</c> is called. Do not
- assume anything about the datatype.</p>
- <p>Use this callback function to generate dynamic web
- content dynamically. When a part of the page is generated, send the
- data back to the client through <c>deliver/2</c>. Notice
- that the first chunk of data sent to the client must at
- least contain all HTTP header fields that the response
- will generate. If the first chunk does not contain the
- <em>end of HTTP header</em>, that is, <c>"\r\n\r\n",</c>
- the server assumes that no HTTP header fields will be generated.</p>
+ <c>Function</c> with an arity of three. An <c>erlScriptAlias</c> must
+ also be set up in the configuration file for the web server.</p>
+
+ <p><c>mod_esi:deliver/2</c> shall be used to generate the response
+ to the client and <c>SessionID</c> is an identifier that shall by used when
+ calling this function, do not assume anything about
+ the datatype. This function may be called
+ several times to chunk the response data. Notice that the
+ first chunk of data sent to the client must at least contain
+ all HTTP header fields that the response will generate. If the
+ first chunk does not contain the <em>end of HTTP header</em>,
+ that is, <c>"\r\n\r\n",</c> the server assumes that no HTTP
+ header fields will be generated.</p>
+
+ <p><c>Env</c> environment data of the request see description above.</p>
+
+ <p><c>Input</c> is query data of a GET request or the body of
+ a PUT or POST request. The default behavior (legacy reasons)
+ for delivering the body, is that the whole body is gathered and
+ converted to a string. But if the httpd config parameter
+ <seealso
+ marker="httpd#max_client_body_chunk">max_client_body_chunk</seealso>
+ is set, the body will be delivered as binary chunks
+ instead. The maximum size of the chunks is either <seealso
+ marker="httpd#max_client_body_chunk">max_client_body_chunk</seealso>
+ or decide by the client if it uses HTTP chunked encoding
+ to send the body. When using the chunking
+ mechanism this callback must return {continue, State::term()}
+ for all calls where <c>Input</c> is <c>{first,
+ Data::binary()}</c> or <c>{continue, Data::binary(),
+ State::term()}</c>. When <c>Input</c> is <c>{last,
+ Data::binary(), State::term()}</c> the return value will be ignored.</p>
+ <note><p>Note that if the body is
+ small all data may be delivered in only one chunk and then the
+ callback will be called with {last, Data::binary(), undefined}
+ without getting called with <c>{first,
+ Data::binary()}</c>.</p></note><p>The input <c>State</c> is
+ the last returned <c>State</c>, in it the callback can include
+ any data that it needs to keep track of when handling the chunks.
+ </p>
</desc>
- </func>
- <func>
- <name>Module:Function(Env, Input)-> Response </name>
- <fsummary>Creates a dynamic web page and returns it as a list.
- This function is deprecated and is only kept for backwards compatibility.</fsummary>
- <type>
- <v>Env = env()</v>
- <v>Input = string()</v>
- <v>Response = string()</v>
- </type>
+ </func>
+
+ <func>
+ <name>Module:Function(Env, Input)-> Response </name>
+ <fsummary>Creates a dynamic web page and returns it as a list.
+ This function is deprecated and is only kept for backwards compatibility.</fsummary>
+ <type>
+ <v>Env = env()</v>
+ <v>Input = string() </v>
+ <v>Response = string()</v>
+ </type>
<desc>
<p>This callback format consumes much memory, as the
- whole response must be generated before it is sent to the
- user. This function is deprecated and is only kept for backwards
- compatibility.
- For new development, use <c>Module:Function/3</c>.</p>
+ whole response must be generated before it is sent to the
+ user. This callback format is deprecated.
+ For new development, use <c>Module:Function/3</c>.</p>
</desc>
- </func>
- </funcs>
-
+ </func>
+ </funcs>
+
</erlref>
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index 9dc32b971b..ec8d6ec42c 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2013</year>
+ <year>1998</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/note.gif b/lib/inets/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/inets/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/notes.gif b/lib/inets/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/inets/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index e41b81044e..07e29b5542 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2015</year>
+ <year>2002</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,12 +33,233 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.2.4.1</title>
+ <section><title>Inets 6.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
+ Correct the handling of location headers so that the
+ status code is not hard coded. This should have been
+ fixed by commit 2cc5ba70cbbc6b3ace81a2a0324417c3b65265bb
+ but unfortunately was broken during a code refactoring
+ and unnoticed due to a faulty placed test case.</p>
+ <p>
+ Own Id: OTP-14761</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix broken handling of POST requests</p>
+ <p>
+ New chunk mechanism of body data in POST requests added
+ in 5d01c70ca399edf28e99dc760506329689fab6ba broke
+ handling of POST body data not using the new mechanism.</p>
+ <p>
+ Own Id: OTP-14656</p>
+ </item>
+ <item>
+ <p>
+ Make sure ints:stop/2 of the service httpd is synchronous</p>
+ <p>
+ Own Id: OTP-14696</p>
+ </item>
+ <item>
+ <p>
+ Honor status code returned by ESI script and modernize
+ "location" header handling.</p>
+ <p>
+ Own Id: OTP-14716</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make sure mod_log uses the correct status code</p>
+ <p>
+ Own Id: OTP-14510</p>
+ </item>
+ <item>
+ <p>
+ Correct behaviour of mod_disk_log to proparly handle
+ repair options</p>
+ <p>
+ Own Id: OTP-14530</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ http_uri aligned to follow RFC 3986 and not convert "+"
+ to space when decoding URIs.</p>
+ <p>
+ Own Id: OTP-14573</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added new option max_client_body_chunk to httpd server to
+ allow chunked delivery of PUT and POST data to mod_esi
+ callback. Note, new mod_esi callback implementation is
+ required.</p>
+ <p>
+ Also correct value provided by server_name environment
+ variable</p>
+ <p>
+ Own Id: OTP-14450</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ httpd_util:rfc1123_date/1 gracefully handle invalid DST
+ dates by returning the original time in the expected
+ rfc1123 format.</p>
+ <p>
+ Own Id: OTP-14394</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add unicode binary support to http_uri functions</p>
+ <p>
+ Own Id: OTP-14404</p>
+ </item>
+ <item>
+ <p>
+ httpc - Change timeout handling so the redirects cause a
+ new timer to be set. This means that a simple redirected
+ request could return after 2*timeout milliseconds.</p>
+ <p>
+ Own Id: OTP-14429</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The close of a chunked file reception crashed in a
+ certain timing sequence.</p>
+ <p>
+ Own Id: OTP-14391 Aux Id: seq13306 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added missing release note for inets-6.3.7</p>
+ <p>
+ Own Id: OTP-14383</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a bug in ftp that made further operations after a
+ recv_chunk operation impossible.</p>
+ <p>
+ Own Id: OTP-14242</p>
+ </item>
+
+ <item>
+ <p>Make default port, 80 and 443, implicit in automatic redirection.
+ </p>
+ <p> Own Id: OTP-14301
+ </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Chunk size decoding could fail. The symptom was that
+ chunk decoding sometimes failed depending on timing of
+ the received stream. If chunk size was split into two
+ different packets decoding would fail.</p>
+ <p>
+ Own Id: OTP-13571 Aux Id: ERL-116 </p>
+ </item>
+ <item>
+ <p>
+ Prevent httpc user process to hang if httpc_handler
+ process terminates unexpectedly</p>
+ <p>
+ Own Id: OTP-14091</p>
+ </item>
+ <item>
+ <p>
+ Correct Host header, to include port number, when
+ redirecting requests.</p>
+ <p>
+ Own Id: OTP-14097</p>
+ </item>
+ <item>
+ <p>
Shutdown gracefully on connection or TLS handshake errors</p>
<p>
Own Id: OTP-14173 Aux Id: seq13262 </p>
@@ -48,6 +269,180 @@
</section>
+<section><title>Inets 6.3.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct misstakes in ftp client introduced in inets-6.3.4</p>
+ <p>
+ Own Id: OTP-14203 Aux Id: OTP-13982 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes a bug that makes the ftp client end up in bad state
+ if there is a multi line response from the server and the
+ response number is in the message being sent.</p>
+ <p>
+ Own Id: OTP-13960 Aux Id: PR1196 </p>
+ </item>
+ <item>
+ <p>
+ The ftp client could stop consuming messages when the
+ multiline response handling was corrected.</p>
+ <p>
+ Own Id: OTP-13967</p>
+ </item>
+ <item>
+ <p>
+ Fix keep-alive https through proxy connections so that
+ all requests, following the first one, will run as
+ expected instead of failing.</p>
+ <p>
+ Own Id: OTP-14041</p>
+ </item>
+ <item>
+ <p>
+ Fix bug from commit
+ fdfda2fab0921d409789174556582db28141448e that could make
+ listing of group members in mod_auth callbacks fail.</p>
+ <p>
+ Own Id: OTP-14082</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update behavior of httpc:request to match RFC-7231</p>
+ <p>
+ Own Id: OTP-13902</p>
+ </item>
+ <item>
+ <p>
+ Fixed dialyzer warnings as well as some white-space
+ issues. Thanks to Kostis.</p>
+ <p>
+ Own Id: OTP-13982 Aux Id: PR-1207 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The legacy option 'inet6fb4' for inets had stopped
+ working. This bug has now been corrected. Fix by Edwin
+ Fine in bugs.erlang.org ERL-200 and Github PR#1132.</p>
+ <p>
+ Own Id: OTP-13776 Aux Id: ERL-200 PR-1132 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ PUT and DELETE support has been added to mod_esi</p>
+ <p>
+ Own Id: OTP-13688 Aux Id: seq13149 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A debug message was accidently left enabled in the ftp
+ client.</p>
+ <p>
+ Own Id: OTP-13712 Aux Id: seq13143 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Ftp client fixes: 1) Corrected a bug that the ftp client
+ gen_server crashed if the listening data socket was
+ closed.</p>
+ <p>
+ 2) Corrections of ftp client error codes so they are as
+ defined in the reference manual</p>
+ <p>
+ Own Id: OTP-13644</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Remove usage of erlang:now(). </p>
+ <p>
+ Own Id: OTP-12441</p>
+ </item>
+ <item>
+ <p> Add handling of DELETE Body to http client. </p>
+ <p>
+ Own Id: OTP-13383 Aux Id: PR-972 </p>
+ </item>
+ <item>
+ <p>
+ Removed references to mod_include and webtool from
+ examples and tests.</p>
+ <p>
+ Own Id: OTP-13445 Aux Id: PR-988 </p>
+ </item>
+ <item>
+ <p>
+ Remove module inets_regexp. Module re should be used
+ instead.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13561</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Inets 6.2.4</title>
<section><title>Improvements and New Features</title>
@@ -569,7 +964,7 @@
<list>
<item>
<p>
- Gracefully handle invalid content-lenght headers instead
+ Gracefully handle invalid content-length headers instead
of crashing in list_to_integer.</p>
<p>
Own Id: OTP-12429</p>
diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml
index 411c62b7f1..c12899e614 100644
--- a/lib/inets/doc/src/notes_history.xml
+++ b/lib/inets/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</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 3b817eecf2..f777481b5c 100644
--- a/lib/inets/doc/src/part.xml
+++ b/lib/inets/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</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
deleted file mode 100644
index 702e3dc09c..0000000000
--- a/lib/inets/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?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>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Inets</title>
- <prepared>Micael Karlberg</prepared>
- <docno></docno>
- <date>2002-02-28</date>
- <rev>3.0</rev>
- <file>part_notes.sgml</file>
- </header>
- <description>
- <p>A set of services such as a Web server and a ftp client etc. </p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include file="notes.xml"/>
-</part>
-
-
diff --git a/lib/inets/doc/src/part_notes_history.xml b/lib/inets/doc/src/part_notes_history.xml
deleted file mode 100644
index 56c44c9e9e..0000000000
--- a/lib/inets/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Inets</title>
- <prepared>Micael Karlberg</prepared>
- <docno></docno>
- <date>2002-02-28</date>
- <rev>3.0</rev>
- <file>part_notes.sgml</file>
- </header>
- <include file="notes_history"></include>
-</part>
-
-
diff --git a/lib/inets/doc/src/ref_man.gif b/lib/inets/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/inets/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/summary.html.src b/lib/inets/doc/src/summary.html.src
deleted file mode 100644
index 17637a0787..0000000000
--- a/lib/inets/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-A set of services such as a web server and a ftp client etc \ No newline at end of file
diff --git a/lib/inets/doc/src/user_guide.gif b/lib/inets/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/inets/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/warning.gif b/lib/inets/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/inets/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/examples/Makefile b/lib/inets/examples/Makefile
index 9a852cf023..7892185bd4 100644
--- a/lib/inets/examples/Makefile
+++ b/lib/inets/examples/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Ericsson AB 2010-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/Makefile b/lib/inets/examples/httpd_load_test/Makefile
index aab62e7305..8b1b654593 100644
--- a/lib/inets/examples/httpd_load_test/Makefile
+++ b/lib/inets/examples/httpd_load_test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+# Copyright Ericsson AB 2010-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt.erl b/lib/inets/examples/httpd_load_test/hdlt.erl
index ae12606bb2..f4b81c8102 100644
--- a/lib/inets/examples/httpd_load_test/hdlt.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt.sh.skel b/lib/inets/examples/httpd_load_test/hdlt.sh.skel
index 537a555e50..1797a53d1d 100644
--- a/lib/inets/examples/httpd_load_test/hdlt.sh.skel
+++ b/lib/inets/examples/httpd_load_test/hdlt.sh.skel
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Ericsson AB 2010-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_client.erl b/lib/inets/examples/httpd_load_test/hdlt_client.erl
index a6273a11b8..8e929fbf2b 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_client.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_client.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl b/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
index 880ce99e72..fcf5b4505f 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_logger.erl b/lib/inets/examples/httpd_load_test/hdlt_logger.erl
index e444030d7f..29fbaab3ae 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_logger.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_logger.hrl b/lib/inets/examples/httpd_load_test/hdlt_logger.hrl
index 240add0147..ac03df2e22 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_logger.hrl
+++ b/lib/inets/examples/httpd_load_test/hdlt_logger.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_server.erl b/lib/inets/examples/httpd_load_test/hdlt_server.erl
index dde09a46df..cd454c82cd 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_server.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/hdlt_slave.erl b/lib/inets/examples/httpd_load_test/hdlt_slave.erl
index f05a1046d3..5ee005629d 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_slave.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/httpd_load_test/modules.mk b/lib/inets/examples/httpd_load_test/modules.mk
index 3349664230..80974819e9 100644
--- a/lib/inets/examples/httpd_load_test/modules.mk
+++ b/lib/inets/examples/httpd_load_test/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010. All Rights Reserved.
+# Copyright Ericsson AB 2010-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/server_root/Makefile b/lib/inets/examples/server_root/Makefile
index 45118aeae0..d11389f0a7 100644
--- a/lib/inets/examples/server_root/Makefile
+++ b/lib/inets/examples/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/server_root/conf/8080.conf b/lib/inets/examples/server_root/conf/8080.conf
index 48e66f0114..7b1b4a15b2 100644
--- a/lib/inets/examples/server_root/conf/8080.conf
+++ b/lib/inets/examples/server_root/conf/8080.conf
@@ -1,7 +1,7 @@
Port 8080
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8080
diff --git a/lib/inets/examples/server_root/conf/8888.conf b/lib/inets/examples/server_root/conf/8888.conf
index 79bb7fcca4..042779fcd0 100644
--- a/lib/inets/examples/server_root/conf/8888.conf
+++ b/lib/inets/examples/server_root/conf/8888.conf
@@ -1,7 +1,7 @@
Port 8888
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8888
diff --git a/lib/inets/examples/server_root/conf/httpd.conf b/lib/inets/examples/server_root/conf/httpd.conf
index f99563d14b..3f9fde03b5 100644
--- a/lib/inets/examples/server_root/conf/httpd.conf
+++ b/lib/inets/examples/server_root/conf/httpd.conf
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ SocketType ip_comm
# WARNING! Do not tamper with this directive unless you are familiar with
# EWSAPI.
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.
diff --git a/lib/inets/examples/server_root/conf/ssl.conf b/lib/inets/examples/server_root/conf/ssl.conf
index 8b8c57a98b..de49ceafd0 100644
--- a/lib/inets/examples/server_root/conf/ssl.conf
+++ b/lib/inets/examples/server_root/conf/ssl.conf
@@ -1,7 +1,7 @@
Port 8088
#ServerName your.server.net
SocketType ssl
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8088
diff --git a/lib/inets/include/httpd.hrl b/lib/inets/include/httpd.hrl
index 8d2803ad3b..fb338d5c68 100644
--- a/lib/inets/include/httpd.hrl
+++ b/lib/inets/include/httpd.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/include/mod_auth.hrl b/lib/inets/include/mod_auth.hrl
index bd3577b9ee..224b2edb5e 100644
--- a/lib/inets/include/mod_auth.hrl
+++ b/lib/inets/include/mod_auth.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/priv/Makefile b/lib/inets/priv/Makefile
index b0e65f8f9c..ddd35e8625 100644
--- a/lib/inets/priv/Makefile
+++ b/lib/inets/priv/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/Makefile b/lib/inets/src/Makefile
index a2a70a7b8f..281dd388cb 100644
--- a/lib/inets/src/Makefile
+++ b/lib/inets/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/ftp/Makefile b/lib/inets/src/ftp/Makefile
index f8daa2b894..6b99694ea7 100644
--- a/lib/inets/src/ftp/Makefile
+++ b/lib/inets/src/ftp/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index db6260c7af..e0430654eb 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -100,6 +100,12 @@
ftp_extension = ?FTP_EXT_DEFAULT
}).
+-record(recv_chunk_closing, {
+ dconn_closed = false,
+ pos_compl_received = false,
+ client_called_us = false
+ }).
+
-type shortage_reason() :: 'etnospc' | 'epnospc'.
-type restriction_reason() :: 'epath' | 'efnamena' | 'elogin' | 'enotbinary'.
@@ -108,6 +114,7 @@
-define(DBG(F,A), 'n/a').
%%-define(DBG(F,A), io:format(F,A)).
+%%-define(DBG(F,A), ct:pal("~p:~p " ++ if is_list(F) -> F; is_atom(F) -> atom_to_list(F) end, [?MODULE,?LINE|A])).
%%%=========================================================================
%%% API - CLIENT FUNCTIONS
@@ -1095,7 +1102,7 @@ init(Options) ->
erlang:monitor(process, Client),
%% Make sure inet is started
- inet_db:start(),
+ _ = inet_db:start(),
%% Where are we
{ok, Dir} = file:get_cwd(),
@@ -1105,15 +1112,17 @@ init(Options) ->
trace ->
dbg:tracer(),
dbg:p(all, [call]),
- dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
- dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
- dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]);
+ {ok, _} = dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
debug ->
dbg:tracer(),
dbg:p(all, [call]),
- dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
- dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
- dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]);
+ {ok, _} = dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
_ ->
%% Keep silent
ok
@@ -1295,8 +1304,7 @@ handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State) ->
activate_ctrl_connection(State),
{noreply, State#state{client = From}};
-handle_call({_,{type, Type}}, From, #state{chunk = false}
- = State) ->
+handle_call({_,{type, Type}}, From, #state{chunk = false} = State) ->
case Type of
ascii ->
send_ctrl_message(State, mk_cmd("TYPE A", [])),
@@ -1341,6 +1349,25 @@ handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false}
handle_call({_, recv_chunk}, _, #state{chunk = false} = State) ->
{reply, {error, "ftp:recv_chunk_start/2 not called"}, State};
+handle_call({_, recv_chunk}, _From, #state{chunk = true,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ pos_compl_received = true
+ }
+ } = State0) ->
+ %% The ftp:recv_chunk call was the last event we waited for, finnish and clean up
+ ?DBG("recv_chunk_closing ftp:recv_chunk, last event",[]),
+ activate_ctrl_connection(State0),
+ {reply, ok, State0#state{caller = undefined,
+ chunk = false,
+ client = undefined}};
+
+handle_call({_, recv_chunk}, From, #state{chunk = true,
+ caller = #recv_chunk_closing{} = R
+ } = State) ->
+ %% Waiting for more, don't care what
+ ?DBG("recv_chunk_closing ftp:recv_chunk, get more",[]),
+ {noreply, State#state{client = From, caller = R#recv_chunk_closing{client_called_us=true}}};
+
handle_call({_, recv_chunk}, From, #state{chunk = true} = State0) ->
State = activate_data_connection(State0),
{noreply, State#state{client = From, caller = recv_chunk}};
@@ -1383,12 +1410,18 @@ handle_call({_, {transfer_chunk, Bin}}, _, #state{chunk = true} = State) ->
send_data_message(State, Bin),
{reply, ok, State};
+handle_call({_, {transfer_chunk, _}}, _, #state{chunk = false} = State) ->
+ {reply, {error, echunk}, State};
+
handle_call({_, chunk_end}, From, #state{chunk = true} = State) ->
close_data_connection(State),
activate_ctrl_connection(State),
{noreply, State#state{client = From, dsock = undefined,
caller = end_chunk_transfer, chunk = false}};
+handle_call({_, chunk_end}, _, #state{chunk = false} = State) ->
+ {reply, {error, echunk}, State};
+
handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State) ->
send_ctrl_message(State, mk_cmd(Cmd, [])),
activate_ctrl_connection(State),
@@ -1448,7 +1481,7 @@ handle_info({Trpt, Socket, Data},
#state{dsock = {Trpt,Socket},
caller = {recv_file, Fd}} = State0) when Trpt==tcp;Trpt==ssl ->
?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
- file_write(binary_to_list(Data), Fd),
+ ok = file_write(binary_to_list(Data), Fd),
progress_report({binary, Data}, State0),
State = activate_data_connection(State0),
{noreply, State};
@@ -1467,24 +1500,29 @@ handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}} = State0) when T
Data/binary>>}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}}
- = State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ caller = {recv_file, Fd}} = State)
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
file_close(Fd),
progress_report({transfer_size, 0}, State),
activate_ctrl_connection(State),
+ ?DBG("Data channel close",[]),
{noreply, State#state{dsock = undefined, data = <<>>}};
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, client = From,
- caller = recv_chunk}
- = State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- gen_server:reply(From, ok),
- {noreply, State#state{dsock = undefined, client = undefined,
- data = <<>>, caller = undefined,
- chunk = false}};
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
+ client = Client,
+ caller = recv_chunk} = State)
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close recv_chunk",[]),
+ activate_ctrl_connection(State),
+ {noreply, State#state{dsock = undefined,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ client_called_us = Client =/= undefined}
+ }};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
data = Data} = State)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close",[]),
activate_ctrl_connection(State),
{noreply, State#state{dsock = undefined, data = <<>>,
caller = {recv_bin, Data}}};
@@ -1492,6 +1530,7 @@ handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, data = Data,
caller = {handle_dir_result, Dir}}
= State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close",[]),
activate_ctrl_connection(State),
{noreply, State#state{dsock = undefined,
caller = {handle_dir_result, Dir, Data},
@@ -1593,13 +1632,13 @@ terminate(normal, State) ->
%% If terminate reason =/= normal the progress reporting process will
%% be killed by the exit signal.
progress_report(stop, State),
- do_termiante({error, econn}, State);
+ do_terminate({error, econn}, State);
terminate(Reason, State) ->
Report = io_lib:format("Ftp connection closed due to: ~p~n", [Reason]),
error_logger:error_report(Report),
- do_termiante({error, eclosed}, State).
+ do_terminate({error, eclosed}, State).
-do_termiante(ErrorMsg, State) ->
+do_terminate(ErrorMsg, State) ->
close_data_connection(State),
close_ctrl_connection(State),
case State#state.client of
@@ -1769,12 +1808,12 @@ handle_ctrl_result({pos_compl, _Lines},
{LSock, Caller}}} = State) ->
handle_caller(State#state{caller = Caller, dsock = {lsock, LSock}});
-handle_ctrl_result({Status, Lines},
+handle_ctrl_result({Status, _Lines},
#state{mode = active,
caller = {setup_data_connection, {LSock, _}}}
= State) ->
- close_connection(LSock),
- ctrl_result_response(Status, State, {error, Lines});
+ close_connection({tcp,LSock}),
+ ctrl_result_response(Status, State, {error, Status});
%% Data connection setup passive mode
handle_ctrl_result({pos_compl, Lines},
@@ -1965,7 +2004,7 @@ handle_ctrl_result(_, #state{caller = {handle_dir_data_third_phase, DirData},
{noreply, State#state{client = undefined, caller = undefined}};
handle_ctrl_result({Status, _}, #state{caller = cd} = State) ->
- ctrl_result_response(Status, State, {error, epath});
+ ctrl_result_response(Status, State, {error, Status});
handle_ctrl_result(Status={epath, _}, #state{caller = {dir,_}} = State) ->
ctrl_result_response(Status, State, {error, epath});
@@ -1980,11 +2019,11 @@ handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
handle_ctrl_result({Status, _},
#state{caller = {rename, _}} = State) ->
- ctrl_result_response(Status, State, {error, epath});
+ ctrl_result_response(Status, State, {error, Status});
handle_ctrl_result({Status, _},
#state{caller = rename_second_phase} = State) ->
- ctrl_result_response(Status, State, {error, epath});
+ ctrl_result_response(Status, State, {error, Status});
%%--------------------------------------------------------------------------
%% File handling - recv_bin
@@ -2038,6 +2077,30 @@ handle_ctrl_result({pos_prel, _}, #state{client = From,
end;
%%--------------------------------------------------------------------------
+%% File handling - chunk_transfer complete
+
+handle_ctrl_result({pos_compl, _}, #state{client = From,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ client_called_us = true,
+ pos_compl_received = false
+ }}
+ = State0) when From =/= undefined ->
+ %% The pos_compl was the last event we waited for, finnish and clean up
+ ?DBG("recv_chunk_closing pos_compl, last event",[]),
+ gen_server:reply(From, ok),
+ activate_ctrl_connection(State0),
+ {noreply, State0#state{caller = undefined,
+ chunk = false,
+ client = undefined}};
+
+handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
+ = State0) ->
+ %% Waiting for more, don't care what
+ ?DBG("recv_chunk_closing pos_compl, wait more",[]),
+ {noreply, State0#state{caller = R#recv_chunk_closing{pos_compl_received=true}}};
+
+
+%%--------------------------------------------------------------------------
%% File handling - recv_file
handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State0) ->
case accept_data_connection(State0) of
@@ -2093,9 +2156,9 @@ handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
%%--------------------------------------------------------------------------
%% Default
-handle_ctrl_result({Status, Lines}, #state{client = From} = State)
+handle_ctrl_result({Status, _Lines}, #state{client = From} = State)
when From =/= undefined ->
- ctrl_result_response(Status, State, {error, Lines}).
+ ctrl_result_response(Status, State, {error, Status}).
%%--------------------------------------------------------------------------
%% Help functions to handle_ctrl_result
@@ -2113,7 +2176,6 @@ ctrl_result_response(Status, #state{client = From} = State, _)
(Status =:= epnospc) orelse
(Status =:= efnamena) orelse
(Status =:= econn) ->
-%Status == etnospc; Status == epnospc; Status == econn ->
gen_server:reply(From, {error, Status}),
%% {stop, normal, {error, Status}, State#state{client = undefined}};
{stop, normal, State#state{client = undefined}};
@@ -2177,7 +2239,7 @@ handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
setup_ctrl_connection(Host, Port, Timeout, State) ->
- MsTime = inets_time_compat:monotonic_time(),
+ MsTime = erlang:monotonic_time(),
case connect(Host, Port, Timeout, State) of
{ok, IpFam, CSock} ->
NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
@@ -2215,16 +2277,16 @@ setup_data_connection(#state{mode = active,
{ok, Port} = inet:port(LSock),
case FtpExt of
false ->
- {IP1, IP2, IP3, IP4} = IP,
- {Port1, Port2} = {Port div 256, Port rem 256},
- send_ctrl_message(State,
- mk_cmd("PORT ~w,~w,~w,~w,~w,~w",
- [IP1, IP2, IP3, IP4, Port1, Port2]));
- true ->
- IpAddress = inet_parse:ntoa(IP),
- Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
- send_ctrl_message(State, Cmd)
- end,
+ {IP1, IP2, IP3, IP4} = IP,
+ {Port1, Port2} = {Port div 256, Port rem 256},
+ send_ctrl_message(State,
+ mk_cmd("PORT ~w,~w,~w,~w,~w,~w",
+ [IP1, IP2, IP3, IP4, Port1, Port2]));
+ true ->
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
+ send_ctrl_message(State, Cmd)
+ end,
activate_ctrl_connection(State),
{noreply, State#state{caller = {setup_data_connection,
{LSock, Caller}}}}
@@ -2332,7 +2394,7 @@ accept_data_connection(#state{mode = passive} = State) ->
send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
verbose(lists:flatten(Message),Verbose,send),
?DBG('<--ctrl ~p ---- ~s~p~n',[Socket,Message,_S]),
- send_message(Socket, Message).
+ _ = send_message(Socket, Message).
send_data_message(_S=#state{dsock = Socket}, Message) ->
?DBG('<==data ~p ==== ~s~n~p~n',[Socket,Message,_S]),
@@ -2353,24 +2415,34 @@ send_message({tcp, Socket}, Message) ->
send_message({ssl, Socket}, Message) ->
ssl:send(Socket, Message).
-activate_ctrl_connection(#state{csock = Socket, ctrl_data = {<<>>, _, _}}) ->
- activate_connection(Socket);
-activate_ctrl_connection(#state{csock = Socket}) ->
+activate_ctrl_connection(#state{csock = CSock, ctrl_data = {<<>>, _, _}}) ->
+ activate_connection(CSock);
+activate_ctrl_connection(#state{csock = CSock}) ->
+ activate_connection(CSock),
%% We have already received at least part of the next control message,
%% that has been saved in ctrl_data, process this first.
- self() ! {tcp, unwrap_socket(Socket), <<>>}.
-
-unwrap_socket({tcp,Socket}) -> Socket;
-unwrap_socket({ssl,Socket}) -> Socket;
-unwrap_socket(Socket) -> Socket.
-
+ self() ! {socket_type(CSock), unwrap_socket(CSock), <<>>},
+ ok.
-activate_data_connection(#state{dsock = Socket} = State) ->
- activate_connection(Socket),
+activate_data_connection(#state{dsock = DSock} = State) ->
+ activate_connection(DSock),
State.
-activate_connection({tcp, Socket}) -> inet:setopts(Socket, [{active, once}]);
-activate_connection({ssl, Socket}) -> ssl:setopts(Socket, [{active, once}]).
+activate_connection(Socket) ->
+ ignore_return_value(
+ case socket_type(Socket) of
+ tcp -> inet:setopts(unwrap_socket(Socket), [{active, once}]);
+ ssl -> ssl:setopts(unwrap_socket(Socket), [{active, once}])
+ end).
+
+
+ignore_return_value(_) -> ok.
+
+unwrap_socket({tcp,Socket}) -> Socket;
+unwrap_socket({ssl,Socket}) -> Socket.
+
+socket_type({tcp,_Socket}) -> tcp;
+socket_type({ssl,_Socket}) -> ssl.
close_ctrl_connection(#state{csock = undefined}) -> ok;
close_ctrl_connection(#state{csock = Socket}) -> close_connection(Socket).
@@ -2378,15 +2450,16 @@ close_ctrl_connection(#state{csock = Socket}) -> close_connection(Socket).
close_data_connection(#state{dsock = undefined}) -> ok;
close_data_connection(#state{dsock = Socket}) -> close_connection(Socket).
-close_connection({tcp, Socket}) -> gen_tcp:close(Socket);
-close_connection({ssl, Socket}) -> ssl:close(Socket).
+close_connection({lsock,Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
+close_connection({tcp, Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
+close_connection({ssl, Socket}) -> ignore_return_value( ssl:close(Socket) ).
-%% ------------ FILE HANDELING ----------------------------------------
+%% ------------ FILE HANDLING ----------------------------------------
send_file(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Fd) ->
{noreply, State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_file, Fd}}};
send_file(State, Fd) ->
case file_read(Fd) of
- {ok, N, Bin} when N > 0->
+ {ok, N, Bin} when N > 0 ->
send_data_message(State, Bin),
progress_report({binary, Bin}, State),
send_file(State, Fd);
@@ -2406,7 +2479,7 @@ file_open(File, Option) ->
file:open(File, [raw, binary, Option]).
file_close(Fd) ->
- file:close(Fd).
+ ignore_return_value( file:close(Fd) ).
file_read(Fd) ->
case file:read(Fd, ?FILE_BUFSIZE) of
@@ -2498,7 +2571,7 @@ progress_report(stop, #state{progress = ProgressPid}) ->
ftp_progress:stop(ProgressPid);
progress_report({binary, Data}, #state{progress = ProgressPid}) ->
ftp_progress:report(ProgressPid, {transfer_size, size(Data)});
-progress_report(Report, #state{progress = ProgressPid}) ->
+progress_report(Report, #state{progress = ProgressPid}) ->
ftp_progress:report(ProgressPid, Report).
diff --git a/lib/inets/src/ftp/ftp_internal.hrl b/lib/inets/src/ftp/ftp_internal.hrl
index a6c9fa098a..f29bb4a099 100644
--- a/lib/inets/src/ftp/ftp_internal.hrl
+++ b/lib/inets/src/ftp/ftp_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/ftp/ftp_progress.erl b/lib/inets/src/ftp/ftp_progress.erl
index 9c42723a07..a6263e5cd7 100644
--- a/lib/inets/src/ftp/ftp_progress.erl
+++ b/lib/inets/src/ftp/ftp_progress.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,11 +36,11 @@
-include_lib("kernel/include/file.hrl").
-record(progress, {
- file, % string()
- cb_module, % atom()
- cb_function, % atom()
- init_progress_term, % term()
- current_progress_term % term()
+ file :: string() | 'undefined',
+ cb_module :: module(),
+ cb_function :: atom(),
+ init_progress_term :: term(),
+ current_progress_term :: term()
}).
%%%=========================================================================
@@ -53,13 +53,15 @@
%% Description: Starts the progress report process unless progress reporting
%% should not be performed.
%%--------------------------------------------------------------------------
+-type options() :: 'ignore' | {module(), atom(), term()}.
+-spec start_link(options()) -> 'ignore' | pid().
start_link(ignore) ->
ignore;
start_link(Options) ->
spawn_link(?MODULE, init, [Options]).
%%--------------------------------------------------------------------------
-%% report_progress(Pid, Report) -> _
+%% report_progress(Pid, Report) -> ok
%% Pid = pid()
%% Report = {local_file, File} | {remote_file, File} |
%% {transfer_size, Size}
@@ -68,17 +70,23 @@ start_link(Options) ->
%% Description: Reports progress to the reporting process that calls the
%% user defined callback function.
%%--------------------------------------------------------------------------
+-type report() :: {'local_file', string()} | {'remote_file', string()}
+ | {'transfer_size', non_neg_integer()}.
+-spec report(pid(), report()) -> 'ok'.
report(Pid, Report) ->
- Pid ! {progress_report, Report}.
+ Pid ! {progress_report, Report},
+ ok.
%%--------------------------------------------------------------------------
-%% stop(Pid) -> _
+%% stop(Pid) -> ok
%% Pid = pid()
%%
%% Description:
%%--------------------------------------------------------------------------
+-spec stop(pid()) -> 'ok'.
stop(Pid) ->
- Pid ! stop.
+ Pid ! stop,
+ ok.
%%%=========================================================================
%%% Internal functions
diff --git a/lib/inets/src/ftp/ftp_response.erl b/lib/inets/src/ftp/ftp_response.erl
index 0aac15ef6c..d54d97dc91 100644
--- a/lib/inets/src/ftp/ftp_response.erl
+++ b/lib/inets/src/ftp/ftp_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -90,19 +90,23 @@ parse_lines(<<C1, C2, C3, ?WHITE_SPACE, Bin/binary>>, Lines, start) ->
parse_lines(Bin, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);
%% Last line found
-parse_lines(<<C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2, C3}) ->
- parse_lines(Rest, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);
+parse_lines(<<?CR, ?LF, C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2, C3}) ->
+ parse_lines(Rest, [?WHITE_SPACE, C3, C2, C1, ?LF, ?CR | Lines], finish);
%% Potential end found wait for more data
-parse_lines(<<C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) ->
+parse_lines(<<?CR, ?LF, C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) ->
{continue, {Bin, Lines, {C1, C2, C3}}};
%% Intermidate line begining with status code
-parse_lines(<<C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) ->
- parse_lines(Rest, [C3, C2, C1 | Lines], {C1, C2, C3});
+parse_lines(<<?CR, ?LF, C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) ->
+ parse_lines(Rest, [C3, C2, C1, ?LF, ?CR | Lines], {C1, C2, C3});
%% Potential last line wait for more data
-parse_lines(<<C1, C2>> = Data, Lines, {C1, C2, _} = StatusCode) ->
+parse_lines(<<?CR, ?LF, C1, C2>> = Data, Lines, {C1, C2, _} = StatusCode) ->
{continue, {Data, Lines, StatusCode}};
-parse_lines(<<C1>> = Data, Lines, {C1, _, _} = StatusCode) ->
+parse_lines(<<?CR, ?LF, C1>> = Data, Lines, {C1, _, _} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<?CR, ?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
{continue, {Data, Lines, StatusCode}};
parse_lines(<<>> = Data, Lines, {_,_,_} = StatusCode) ->
{continue, {Data, Lines, StatusCode}};
@@ -194,5 +198,6 @@ interpret_status(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;
interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,0) -> epath;
interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> epnospc;
interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> efnamena;
+interpret_status(?PERM_NEG_COMPL,?AUTH_ACC,0) -> elogin;
interpret_status(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
diff --git a/lib/inets/src/ftp/ftp_sup.erl b/lib/inets/src/ftp/ftp_sup.erl
index b5b3f6a105..21dcfb6ab2 100644
--- a/lib/inets/src/ftp/ftp_sup.erl
+++ b/lib/inets/src/ftp/ftp_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index cb97b525f6..a1c1f36b70 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 4554881d79..bf2da82603 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -147,6 +147,26 @@ request(Method, Request, HttpOptions, Options) ->
request(Method, Request, HttpOptions, Options, default_profile()).
request(Method,
+ {Url, Headers, ContentType, TupleBody},
+ HTTPOptions, Options, Profile)
+ when ((Method =:= post) orelse (Method =:= patch) orelse (Method =:= put) orelse (Method =:= delete))
+ andalso (is_atom(Profile) orelse is_pid(Profile)) andalso
+ is_list(ContentType) andalso is_tuple(TupleBody)->
+ case check_body_gen(TupleBody) of
+ ok ->
+ do_request(Method, {Url, Headers, ContentType, TupleBody}, HTTPOptions, Options, Profile);
+ Error ->
+ Error
+ end;
+request(Method,
+ {Url, Headers, ContentType, Body},
+ HTTPOptions, Options, Profile)
+ when ((Method =:= post) orelse (Method =:= patch) orelse (Method =:= put) orelse (Method =:= delete))
+ andalso (is_atom(Profile) orelse is_pid(Profile)) andalso
+ is_list(ContentType) andalso (is_list(Body) orelse is_binary(Body)) ->
+ do_request(Method, {Url, Headers, ContentType, Body}, HTTPOptions, Options, Profile);
+
+request(Method,
{Url, Headers},
HTTPOptions, Options, Profile)
when (Method =:= options) orelse
@@ -155,12 +175,6 @@ request(Method,
(Method =:= delete) orelse
(Method =:= trace) andalso
(is_atom(Profile) orelse is_pid(Profile)) ->
- ?hcrt("request", [{method, Method},
- {url, Url},
- {headers, Headers},
- {http_options, HTTPOptions},
- {options, Options},
- {profile, Profile}]),
case uri_parse(Url, Options) of
{error, Reason} ->
{error, Reason};
@@ -172,21 +186,9 @@ request(Method,
handle_request(Method, Url, ParsedUrl, Headers, [], [],
HTTPOptions, Options, Profile)
end
- end;
-
-request(Method,
- {Url, Headers, ContentType, Body},
- HTTPOptions, Options, Profile)
- when ((Method =:= post) orelse (Method =:= patch) orelse (Method =:= put) orelse
- (Method =:= delete)) andalso (is_atom(Profile) orelse is_pid(Profile)) ->
- ?hcrt("request", [{method, Method},
- {url, Url},
- {headers, Headers},
- {content_type, ContentType},
- {body, Body},
- {http_options, HTTPOptions},
- {options, Options},
- {profile, Profile}]),
+ end.
+
+do_request(Method, {Url, Headers, ContentType, Body}, HTTPOptions, Options, Profile) ->
case uri_parse(Url, Options) of
{error, Reason} ->
{error, Reason};
@@ -196,7 +198,6 @@ request(Method,
HTTPOptions, Options, Profile)
end.
-
%%--------------------------------------------------------------------------
%% cancel_request(RequestId) -> ok
%% cancel_request(RequestId, Profile) -> ok
@@ -209,7 +210,6 @@ cancel_request(RequestId) ->
cancel_request(RequestId, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
- ?hcrt("cancel request", [{request_id, RequestId}, {profile, Profile}]),
httpc_manager:cancel_request(RequestId, profile_name(Profile)).
@@ -232,7 +232,6 @@ cancel_request(RequestId, Profile)
set_options(Options) ->
set_options(Options, default_profile()).
set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) ->
- ?hcrt("set options", [{options, Options}, {profile, Profile}]),
case validate_options(Options) of
{ok, Opts} ->
httpc_manager:set_options(Opts, profile_name(Profile));
@@ -272,7 +271,6 @@ get_options(all = _Options, Profile) ->
get_options(Options, Profile)
when (is_list(Options) andalso
(is_atom(Profile) orelse is_pid(Profile))) ->
- ?hcrt("get options", [{options, Options}, {profile, Profile}]),
case Options -- get_options() of
[] ->
try
@@ -314,9 +312,6 @@ store_cookies(SetCookieHeaders, Url) ->
store_cookies(SetCookieHeaders, Url, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
- ?hcrt("store cookies", [{set_cookie_headers, SetCookieHeaders},
- {url, Url},
- {profile, Profile}]),
try
begin
%% Since the Address part is not actually used
@@ -353,9 +348,6 @@ cookie_header(Url, Opts) when is_list(Opts) ->
cookie_header(Url, Opts, Profile)
when (is_list(Opts) andalso (is_atom(Profile) orelse is_pid(Profile))) ->
- ?hcrt("cookie header", [{url, Url},
- {opts, Opts},
- {profile, Profile}]),
try
begin
httpc_manager:which_cookies(Url, Opts, profile_name(Profile))
@@ -398,7 +390,6 @@ which_sessions() ->
which_sessions(default_profile()).
which_sessions(Profile) ->
- ?hcrt("which sessions", [{profile, Profile}]),
try
begin
httpc_manager:which_sessions(profile_name(Profile))
@@ -419,7 +410,6 @@ info() ->
info(default_profile()).
info(Profile) ->
- ?hcrt("info", [{profile, Profile}]),
try
begin
httpc_manager:info(profile_name(Profile))
@@ -440,7 +430,6 @@ reset_cookies() ->
reset_cookies(default_profile()).
reset_cookies(Profile) ->
- ?hcrt("reset cookies", [{profile, Profile}]),
try
begin
httpc_manager:reset_cookies(profile_name(Profile))
@@ -458,7 +447,6 @@ reset_cookies(Profile) ->
%% same behavior as active once for sockets.
%%-------------------------------------------------------------------------
stream_next(Pid) ->
- ?hcrt("stream next", [{handler, Pid}]),
httpc_handler:stream_next(Pid).
@@ -466,7 +454,6 @@ stream_next(Pid) ->
%%% Behaviour callbacks
%%%========================================================================
start_standalone(PropList) ->
- ?hcrt("start standalone", [{proplist, PropList}]),
case proplists:get_value(profile, PropList) of
undefined ->
{error, no_profile};
@@ -477,14 +464,11 @@ start_standalone(PropList) ->
end.
start_service(Config) ->
- ?hcrt("start service", [{config, Config}]),
httpc_profile_sup:start_child(Config).
stop_service(Profile) when is_atom(Profile) ->
- ?hcrt("stop service", [{profile, Profile}]),
httpc_profile_sup:stop_child(Profile);
stop_service(Pid) when is_pid(Pid) ->
- ?hcrt("stop service", [{pid, Pid}]),
case service_info(Pid) of
{ok, [{profile, Profile}]} ->
stop_service(Profile);
@@ -510,7 +494,6 @@ service_info(Pid) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
-
handle_request(Method, Url,
{Scheme, UserInfo, Host, Port, Path, Query},
Headers0, ContentType, Body0,
@@ -521,9 +504,6 @@ handle_request(Method, Url,
try
begin
- ?hcrt("begin processing", [{started, Started},
- {new_headers, NewHeaders0}]),
-
{NewHeaders, Body} =
case Body0 of
{chunkify, ProcessBody, Acc}
@@ -544,7 +524,7 @@ handle_request(Method, Url,
Options = request_options(Options0),
Sync = proplists:get_value(sync, Options),
Stream = proplists:get_value(stream, Options),
- Host2 = header_host(Scheme, Host, Port),
+ Host2 = http_request:normalize_host(Scheme, Host, Port),
HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
Receiver = proplists:get_value(receiver, Options),
SocketOpts = proplists:get_value(socket_opts, Options),
@@ -575,16 +555,13 @@ handle_request(Method, Url,
{ok, RequestId} ->
handle_answer(RequestId, Sync, Options);
{error, Reason} ->
- ?hcrd("request failed", [{reason, Reason}]),
{error, Reason}
end
end
catch
error:{noproc, _} ->
- ?hcrv("noproc", [{profile, Profile}]),
{error, {not_started, Profile}};
throw:Error ->
- ?hcrv("throw", [{error, Error}]),
Error
end.
@@ -620,15 +597,10 @@ handle_answer(RequestId, false, _) ->
handle_answer(RequestId, true, Options) ->
receive
{http, {RequestId, saved_to_file}} ->
- ?hcrt("received saved-to-file", [{request_id, RequestId}]),
{ok, saved_to_file};
{http, {RequestId, {_,_,_} = Result}} ->
- ?hcrt("received answer", [{request_id, RequestId},
- {result, Result}]),
return_answer(Options, Result);
{http, {RequestId, {error, Reason}}} ->
- ?hcrt("received error", [{request_id, RequestId},
- {reason, Reason}]),
{error, Reason}
end.
@@ -1063,14 +1035,6 @@ bad_option(Option, BadValue) ->
throw({error, {bad_option, Option, BadValue}}).
-header_host(https, Host, 443 = _Port) ->
- Host;
-header_host(http, Host, 80 = _Port) ->
- Host;
-header_host(_Scheme, Host, Port) ->
- Host ++ ":" ++ integer_to_list(Port).
-
-
header_record(NewHeaders, Host, #http_options{version = Version}) ->
header_record(NewHeaders, #http_request_h{}, Host, Version).
@@ -1257,18 +1221,14 @@ child_name(Pid, [{Name, Pid} | _]) ->
child_name(Pid, [_ | Children]) ->
child_name(Pid, Children).
-%% d(F) ->
-%% d(F, []).
-
-%% d(F, A) ->
-%% d(get(dbg), F, A).
-
-%% d(true, F, A) ->
-%% io:format(user, "~w:~w:" ++ F ++ "~n", [self(), ?MODULE | A]);
-%% d(_, _, _) ->
-%% ok.
-
host_address(Host, false) ->
Host;
host_address(Host, true) ->
string:strip(string:strip(Host, right, $]), left, $[).
+
+check_body_gen({Fun, _}) when is_function(Fun) ->
+ ok;
+check_body_gen({chunkify, Fun, _}) when is_function(Fun) ->
+ ok;
+check_body_gen(Gen) ->
+ {error, {bad_body_generator, Gen}}.
diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index 0c4f44a575..cbf428ab3e 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index d1c52dcc78..6907bf5262 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-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
%% Internal Application API
-export([
start_link/4,
- %% connect_and_send/2,
send/2,
cancel/2,
stream_next/1,
@@ -45,28 +44,30 @@
-record(timers,
{
- request_timers = [], % [ref()]
- queue_timer % ref()
+ request_timers = [] :: [reference()],
+ queue_timer :: reference() | 'undefined'
}).
+-type session_failed() :: {'connect_failed',term()} | {'send_failed',term()}.
+
-record(state,
{
- request, % #request{}
- session, % #session{}
+ request :: request() | 'undefined',
+ session :: session() | session_failed() | 'undefined',
status_line, % {Version, StatusCode, ReasonPharse}
- headers, % #http_response_h{}
- body, % binary()
+ headers :: http_response_h() | 'undefined',
+ body :: binary() | 'undefined',
mfa, % {Module, Function, Args}
- pipeline = queue:new(), % queue:queue()
- keep_alive = queue:new(), % queue: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()
- max_body_size = nolimit, % nolimit | integer()
- options, % #options{}
- timers = #timers{}, % #timers{}
- profile_name, % atom() - id of httpc_manager process.
- once = inactive % inactive | once
+ max_header_size = nolimit :: nolimit | integer(),
+ max_body_size = nolimit :: nolimit | integer(),
+ options :: options(),
+ timers = #timers{} :: #timers{},
+ profile_name :: atom(), % id of httpc_manager process.
+ once = inactive :: 'inactive' | 'once'
}).
@@ -113,7 +114,7 @@ send(Request, Pid) ->
%%--------------------------------------------------------------------
%% Function: cancel(RequestId, Pid) -> ok
-%% RequestId = ref()
+%% RequestId = reference()
%% Pid = pid() - the pid of the http-request handler process.
%%
%% Description: Cancels a request. Intended to be called by the httpc
@@ -163,14 +164,12 @@ info(Pid) ->
%%--------------------------------------------------------------------
%% Request should not be streamed
stream(BodyPart, #request{stream = none} = Request, _) ->
- ?hcrt("stream - none", []),
{false, BodyPart, Request};
%% Stream to caller
stream(BodyPart, #request{stream = Self} = Request, Code)
when ?IS_STREAMED(Code) andalso
((Self =:= self) orelse (Self =:= {self, once})) ->
- ?hcrt("stream - self", [{stream, Self}, {code, Code}]),
httpc_response:send(Request#request.from,
{Request#request.id, stream, BodyPart}),
{true, <<>>, Request};
@@ -180,10 +179,8 @@ stream(BodyPart, #request{stream = Self} = Request, Code)
%% We keep this for backward compatibillity...
stream(BodyPart, #request{stream = Filename} = Request, Code)
when ?IS_STREAMED(Code) andalso is_list(Filename) ->
- ?hcrt("stream - filename", [{stream, Filename}, {code, Code}]),
case file:open(Filename, [write, raw, append, delayed_write]) of
{ok, Fd} ->
- ?hcrt("stream - file open ok", [{fd, Fd}]),
stream(BodyPart, Request#request{stream = Fd}, 200);
{error, Reason} ->
exit({stream_to_file_failed, Reason})
@@ -192,7 +189,6 @@ stream(BodyPart, #request{stream = Filename} = Request, Code)
%% Stream to file
stream(BodyPart, #request{stream = Fd} = Request, Code)
when ?IS_STREAMED(Code) ->
- ?hcrt("stream to file", [{stream, Fd}, {code, Code}]),
case file:write(Fd, BodyPart) of
ok ->
{true, <<>>, Request};
@@ -201,7 +197,6 @@ stream(BodyPart, #request{stream = Fd} = Request, Code)
end;
stream(BodyPart, Request,_) -> % only 200 and 206 responses can be streamed
- ?hcrt("stream - ignore", [{request, Request}]),
{false, BodyPart, Request}.
@@ -255,22 +250,148 @@ init([Parent, Request, Options, ProfileName]) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call(#request{address = Addr} = Request, _,
+handle_call(Request, From, State) ->
+ try do_handle_call(Request, From, State) of
+ Result ->
+ Result
+ catch
+ _:Reason ->
+ {stop, {shutdown, Reason} , State}
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast(Msg, State) ->
+ try do_handle_cast(Msg, State) of
+ Result ->
+ Result
+ catch
+ _:Reason ->
+ {stop, {shutdown, Reason} , State}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info(Info, State) ->
+ try do_handle_info(Info, State) of
+ Result ->
+ Result
+ catch
+ _:Reason ->
+ {stop, {shutdown, Reason} , State}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> _ (ignored by gen_server)
+%% Description: Shutdown the httpc_handler
+%%--------------------------------------------------------------------
+
+%% Init error there is no socket to be closed.
+terminate(normal,
+ #state{request = Request,
+ session = {send_failed, _} = Reason} = State) ->
+ maybe_send_answer(Request,
+ httpc_response:error(Request, Reason),
+ State),
+ ok;
+
+terminate(normal,
+ #state{request = Request,
+ session = {connect_failed, _} = Reason} = State) ->
+ maybe_send_answer(Request,
+ httpc_response:error(Request, Reason),
+ State),
+ ok;
+
+terminate(normal, #state{session = undefined}) ->
+ ok;
+
+%% Init error sending, no session information has been setup but
+%% there is a socket that needs closing.
+terminate(normal,
+ #state{session = #session{id = undefined} = Session}) ->
+ close_socket(Session);
+
+%% Socket closed remotely
+terminate(normal,
+ #state{session = #session{socket = {remote_close, Socket},
+ socket_type = SocketType,
+ id = Id},
+ profile_name = ProfileName,
+ request = Request,
+ timers = Timers,
+ pipeline = Pipeline,
+ keep_alive = KeepAlive} = State) ->
+ %% Clobber session
+ (catch httpc_manager:delete_session(Id, ProfileName)),
+
+ maybe_retry_queue(Pipeline, State),
+ maybe_retry_queue(KeepAlive, State),
+
+ %% Cancel timers
+ cancel_timers(Timers),
+
+ %% Maybe deliver answers to requests
+ deliver_answer(Request),
+
+ %% And, just in case, close our side (**really** overkill)
+ http_transport:close(SocketType, Socket);
+
+terminate(_Reason, #state{session = #session{id = Id,
+ socket = Socket,
+ socket_type = SocketType},
+ request = undefined,
+ profile_name = ProfileName,
+ timers = Timers,
+ pipeline = Pipeline,
+ keep_alive = KeepAlive} = State) ->
+
+ %% Clobber session
+ (catch httpc_manager:delete_session(Id, ProfileName)),
+
+ maybe_retry_queue(Pipeline, State),
+ maybe_retry_queue(KeepAlive, State),
+
+ cancel_timer(Timers#timers.queue_timer, timeout_queue),
+ http_transport:close(SocketType, Socket);
+
+terminate(_Reason, #state{request = undefined}) ->
+ ok;
+
+terminate(Reason, #state{request = Request} = State) ->
+ NewState = maybe_send_answer(Request,
+ httpc_response:error(Request, Reason),
+ State),
+ terminate(Reason, NewState#state{request = undefined}).
+
+%%--------------------------------------------------------------------
+%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
+%% Purpose: Convert process state when code is changed
+%%--------------------------------------------------------------------
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+%%%--------------------------------------------------------------------
+%%% Internal functions
+%%%--------------------------------------------------------------------
+do_handle_call(#request{address = Addr} = Request, _,
#state{status = Status,
session = #session{type = pipeline} = Session,
timers = Timers,
options = #options{proxy = Proxy} = _Options,
profile_name = ProfileName} = State0)
when Status =/= undefined ->
-
- ?hcrv("new request on a pipeline session",
- [{request, Request},
- {profile, ProfileName},
- {status, Status},
- {timers, Timers}]),
-
Address = handle_proxy(Addr, Proxy),
-
case httpc_request:send(Address, Session, Request) of
ok ->
@@ -285,9 +406,8 @@ handle_call(#request{address = Addr} = Request, _,
case State0#state.request of
#request{} = OldRequest -> %% Old request not yet finished
- ?hcrd("old request still not finished", []),
%% Make sure to use the new value of timers in state
- NewTimers = State1#state.timers,
+ NewTimers = State1#state.timers,
NewPipeline = queue:in(Request, State1#state.pipeline),
NewSession =
Session#session{queue_length =
@@ -295,7 +415,6 @@ handle_call(#request{address = Addr} = Request, _,
queue:len(NewPipeline) + 1,
client_close = ClientClose},
insert_session(NewSession, ProfileName),
- ?hcrd("session updated", []),
{reply, ok, State1#state{
request = OldRequest,
pipeline = NewPipeline,
@@ -304,7 +423,6 @@ handle_call(#request{address = Addr} = Request, _,
undefined ->
%% Note: tcp-message receiving has already been
%% activated by handle_pipeline/2.
- ?hcrd("no current request", []),
cancel_timer(Timers#timers.queue_timer,
timeout_queue),
NewSession =
@@ -312,18 +430,16 @@ handle_call(#request{address = Addr} = Request, _,
client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
NewTimers = Timers#timers{queue_timer = undefined},
- ?hcrd("session created", []),
State = init_wait_for_response_state(Request, State1#state{session = NewSession,
timers = NewTimers}),
{reply, ok, State}
end;
{error, Reason} ->
- ?hcri("failed sending request", [{reason, Reason}]),
NewPipeline = queue:in(Request, State0#state.pipeline),
- {stop, shutdown, {pipeline_failed, Reason}, State0#state{pipeline = NewPipeline}}
+ {stop, {shutdown, {pipeline_failed, Reason}}, State0#state{pipeline = NewPipeline}}
end;
-handle_call(#request{address = Addr} = Request, _,
+do_handle_call(#request{address = Addr} = Request, _,
#state{status = Status,
session = #session{type = keep_alive} = Session,
timers = Timers,
@@ -331,17 +447,11 @@ handle_call(#request{address = Addr} = Request, _,
profile_name = ProfileName} = State0)
when Status =/= undefined ->
- ?hcrv("new request on a keep-alive session",
- [{request, Request},
- {profile, ProfileName},
- {status, Status}]),
-
ClientClose = httpc_request:is_client_closing(Request#request.headers),
case State0#state.request of
#request{} -> %% Old request not yet finished
%% Make sure to use the new value of timers in state
- ?hcrd("old request still not finished", []),
NewKeepAlive = queue:in(Request, State0#state.keep_alive),
NewSession =
Session#session{queue_length =
@@ -349,13 +459,11 @@ handle_call(#request{address = Addr} = Request, _,
queue:len(NewKeepAlive) + 1,
client_close = ClientClose},
insert_session(NewSession, ProfileName),
- ?hcrd("session updated", []),
{reply, ok, State0#state{keep_alive = NewKeepAlive,
session = NewSession}};
undefined ->
%% Note: tcp-message receiving has already been
%% activated by handle_pipeline/2.
- ?hcrd("no current request", []),
cancel_timer(Timers#timers.queue_timer,
timeout_queue),
NewTimers = Timers#timers{queue_timer = undefined},
@@ -363,8 +471,6 @@ handle_call(#request{address = Addr} = Request, _,
Address = handle_proxy(Addr, Proxy),
case httpc_request:send(Address, Session, Request) of
ok ->
- ?hcrd("request sent", []),
-
%% Activate the request time out for the new request
State2 =
activate_request_timeout(State1#state{request = Request}),
@@ -375,22 +481,13 @@ handle_call(#request{address = Addr} = Request, _,
State = init_wait_for_response_state(Request, State2#state{session = NewSession}),
{reply, ok, State};
{error, Reason} ->
- ?hcri("failed sending request", [{reason, Reason}]),
- {stop, shutdown, {keepalive_failed, Reason}, State1}
+ {stop, {shutdown, {keepalive_failed, Reason}}, State1}
end
end;
-
-handle_call(info, _, State) ->
+do_handle_call(info, _, State) ->
Info = handler_info(State),
{reply, Info, State}.
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
-
%% When the request in process has been canceled the handler process is
%% stopped and the pipelined requests will be reissued or remaining
%% requests will be sent on a new connection. This is is
@@ -403,145 +500,102 @@ handle_call(info, _, State) ->
%% handle_keep_alive_queue/2 on the other hand will just skip the
%% request as if it was never issued as in this case the request will
%% not have been sent.
-handle_cast({cancel, RequestId},
+do_handle_cast({cancel, RequestId},
#state{request = #request{id = RequestId} = Request,
- profile_name = ProfileName,
canceled = Canceled} = State) ->
- ?hcrv("cancel current request", [{request_id, RequestId},
- {profile, ProfileName},
- {canceled, Canceled}]),
{stop, normal,
State#state{canceled = [RequestId | Canceled],
request = Request#request{from = answer_sent}}};
-handle_cast({cancel, RequestId},
- #state{profile_name = ProfileName,
- request = #request{id = CurrId},
- canceled = Canceled} = State) ->
- ?hcrv("cancel", [{request_id, RequestId},
- {curr_req_id, CurrId},
- {profile, ProfileName},
- {canceled, Canceled}]),
+do_handle_cast({cancel, RequestId},
+ #state{request = #request{},
+ canceled = Canceled} = State) ->
{noreply, State#state{canceled = [RequestId | Canceled]}};
-handle_cast({cancel, RequestId},
- #state{profile_name = ProfileName,
- request = undefined,
- canceled = Canceled} = State) ->
- ?hcrv("cancel", [{request_id, RequestId},
- {curr_req_id, undefined},
- {profile, ProfileName},
- {canceled, Canceled}]),
+do_handle_cast({cancel, _},
+ #state{request = undefined} = State) ->
{noreply, State};
-
-handle_cast(stream_next, #state{session = Session} = State) ->
+do_handle_cast(stream_next, #state{session = Session} = State) ->
activate_once(Session),
%% Inactivate the #state.once here because we don't want
%% next_body_chunk/1 to activate the socket twice.
{noreply, State#state{once = inactive}}.
-
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
-handle_info({Proto, _Socket, Data},
+do_handle_info({Proto, _Socket, Data},
#state{mfa = {Module, Function, Args},
- request = #request{method = Method,
- stream = Stream} = Request,
+ request = #request{method = Method} = Request,
session = Session,
status_line = StatusLine} = State)
when (Proto =:= tcp) orelse
(Proto =:= ssl) orelse
(Proto =:= httpc_handler) ->
- ?hcri("received data", [{proto, Proto},
- {module, Module},
- {function, Function},
- {method, Method},
- {stream, Stream},
- {session, Session},
- {status_line, StatusLine}]),
-
- FinalResult =
- try Module:Function([Data | Args]) of
- {ok, Result} ->
- ?hcrd("data processed - ok", []),
- handle_http_msg(Result, State);
- {_, whole_body, _} when Method =:= head ->
- ?hcrd("data processed - whole body", []),
- handle_response(State#state{body = <<>>});
- {Module, whole_body, [Body, Length]} ->
- ?hcrd("data processed - whole body", [{length, Length}]),
- {_, Code, _} = StatusLine,
- {Streamed, NewBody, NewRequest} = stream(Body, Request, Code),
- %% When we stream we will not keep the already
- %% streamed data, that would be a waste of memory.
- NewLength =
- case Streamed of
- false ->
- Length;
- true ->
- Length - size(Body)
- end,
-
- NewState = next_body_chunk(State, Code),
- NewMFA = {Module, whole_body, [NewBody, NewLength]},
- {noreply, NewState#state{mfa = NewMFA,
- request = NewRequest}};
- {Module, decode_size,
- [TotalChunk, HexList,
- {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize}]}
- when BodySoFar =/= <<>> ->
- ?hcrd("data processed - decode_size", []),
- %% The response body is chunk-encoded. Steal decoded
- %% chunks as much as possible to stream.
- {_, Code, _} = StatusLine,
- {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code),
- NewState = next_body_chunk(State, Code),
- NewMFA = {Module, decode_size,
- [TotalChunk, HexList,
- {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]},
- {noreply, NewState#state{mfa = NewMFA,
- request = NewRequest}};
- {Module, decode_data,
- [ChunkSize, TotalChunk,
+ try Module:Function([Data | Args]) of
+ {ok, Result} ->
+ handle_http_msg(Result, State);
+ {_, whole_body, _} when Method =:= head ->
+ handle_response(State#state{body = <<>>});
+ {Module, whole_body, [Body, Length]} ->
+ {_, Code, _} = StatusLine,
+ {Streamed, NewBody, NewRequest} = stream(Body, Request, Code),
+ %% When we stream we will not keep the already
+ %% streamed data, that would be a waste of memory.
+ NewLength =
+ case Streamed of
+ false ->
+ Length;
+ true ->
+ Length - size(Body)
+ end,
+
+ NewState = next_body_chunk(State, Code),
+ NewMFA = {Module, whole_body, [NewBody, NewLength]},
+ {noreply, NewState#state{mfa = NewMFA,
+ request = NewRequest}};
+ {Module, decode_size,
+ [TotalChunk, HexList, AccHeaderSize,
{MaxBodySize, BodySoFar, AccLength, MaxHeaderSize}]}
- when TotalChunk =/= <<>> orelse BodySoFar =/= <<>> ->
- ?hcrd("data processed - decode_data", []),
- %% The response body is chunk-encoded. Steal decoded
- %% chunks as much as possible to stream.
- ChunkSizeToSteal = min(ChunkSize, byte_size(TotalChunk)),
- <<StolenChunk:ChunkSizeToSteal/binary, NewTotalChunk/binary>> = TotalChunk,
- StolenBody = <<BodySoFar/binary, StolenChunk/binary>>,
- NewChunkSize = ChunkSize - ChunkSizeToSteal,
- {_, Code, _} = StatusLine,
-
- {_, NewBody, NewRequest} = stream(StolenBody, Request, Code),
- NewState = next_body_chunk(State, Code),
- NewMFA = {Module, decode_data,
- [NewChunkSize, NewTotalChunk,
+ when BodySoFar =/= <<>> ->
+ %% The response body is chunk-encoded. Steal decoded
+ %% chunks as much as possible to stream.
+ {_, Code, _} = StatusLine,
+ {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code),
+ NewState = next_body_chunk(State, Code),
+ NewMFA = {Module, decode_size,
+ [TotalChunk, HexList, AccHeaderSize,
{MaxBodySize, NewBody, AccLength, MaxHeaderSize}]},
+ {noreply, NewState#state{mfa = NewMFA,
+ request = NewRequest}};
+ {Module, decode_data,
+ [ChunkSize, TotalChunk,
+ {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize}]}
+ when TotalChunk =/= <<>> orelse BodySoFar =/= <<>> ->
+ %% The response body is chunk-encoded. Steal decoded
+ %% chunks as much as possible to stream.
+ ChunkSizeToSteal = min(ChunkSize, byte_size(TotalChunk)),
+ <<StolenChunk:ChunkSizeToSteal/binary, NewTotalChunk/binary>> = TotalChunk,
+ StolenBody = <<BodySoFar/binary, StolenChunk/binary>>,
+ NewChunkSize = ChunkSize - ChunkSizeToSteal,
+ {_, Code, _} = StatusLine,
+
+ {_, NewBody, NewRequest} = stream(StolenBody, Request, Code),
+ NewState = next_body_chunk(State, Code),
+ NewMFA = {Module, decode_data,
+ [NewChunkSize, NewTotalChunk,
+ {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]},
{noreply, NewState#state{mfa = NewMFA,
request = NewRequest}};
- NewMFA ->
- ?hcrd("data processed - new mfa", []),
- activate_once(Session),
- {noreply, State#state{mfa = NewMFA}}
- catch
- _:_Reason ->
- ?hcrd("data processing exit", [{exit, _Reason}]),
- ClientReason = {could_not_parse_as_http, Data},
- ClientErrMsg = httpc_response:error(Request, ClientReason),
- NewState = answer_request(Request, ClientErrMsg, State),
- {stop, normal, NewState}
- end,
- ?hcri("data processed", [{final_result, FinalResult}]),
- FinalResult;
-
+ NewMFA ->
+ activate_once(Session),
+ {noreply, State#state{mfa = NewMFA}}
+ catch
+ _:Reason ->
+ ClientReason = {could_not_parse_as_http, Data},
+ ClientErrMsg = httpc_response:error(Request, ClientReason),
+ NewState = answer_request(Request, ClientErrMsg, State),
+ {stop, {shutdown, Reason}, NewState}
+ end;
-handle_info({Proto, Socket, Data},
+do_handle_info({Proto, Socket, Data},
#state{mfa = MFA,
request = Request,
session = Session,
@@ -566,200 +620,107 @@ handle_info({Proto, Socket, Data},
{noreply, State};
-
%% The Server may close the connection to indicate that the
%% whole body is now sent instead of sending an length
%% indicator.
-handle_info({tcp_closed, _}, State = #state{mfa = {_, whole_body, Args}}) ->
+do_handle_info({tcp_closed, _}, State = #state{mfa = {_, whole_body, Args}}) ->
handle_response(State#state{body = hd(Args)});
-handle_info({ssl_closed, _}, State = #state{mfa = {_, whole_body, Args}}) ->
+do_handle_info({ssl_closed, _}, State = #state{mfa = {_, whole_body, Args}}) ->
handle_response(State#state{body = hd(Args)});
%%% Server closes idle pipeline
-handle_info({tcp_closed, _}, State = #state{request = undefined}) ->
+do_handle_info({tcp_closed, _}, State = #state{request = undefined}) ->
{stop, normal, State};
-handle_info({ssl_closed, _}, State = #state{request = undefined}) ->
+do_handle_info({ssl_closed, _}, State = #state{request = undefined}) ->
{stop, normal, State};
%%% Error cases
-handle_info({tcp_closed, _}, #state{session = Session0} = State) ->
+do_handle_info({tcp_closed, _}, #state{session = Session0} = State) ->
Socket = Session0#session.socket,
Session = Session0#session{socket = {remote_close, Socket}},
%% {stop, session_remotly_closed, State};
{stop, normal, State#state{session = Session}};
-handle_info({ssl_closed, _}, #state{session = Session0} = State) ->
+do_handle_info({ssl_closed, _}, #state{session = Session0} = State) ->
Socket = Session0#session.socket,
Session = Session0#session{socket = {remote_close, Socket}},
%% {stop, session_remotly_closed, State};
{stop, normal, State#state{session = Session}};
-handle_info({tcp_error, _, _} = Reason, State) ->
+do_handle_info({tcp_error, _, _} = Reason, State) ->
{stop, Reason, State};
-handle_info({ssl_error, _, _} = Reason, State) ->
+do_handle_info({ssl_error, _, _} = Reason, State) ->
{stop, Reason, State};
%% Timeouts
%% Internally, to a request handling process, a request timeout is
%% seen as a canceled request.
-handle_info({timeout, RequestId},
+do_handle_info({timeout, RequestId},
#state{request = #request{id = RequestId} = Request,
canceled = Canceled,
profile_name = ProfileName} = State) ->
- ?hcri("timeout of current request", [{id, RequestId}]),
httpc_response:send(Request#request.from,
httpc_response:error(Request, timeout)),
httpc_manager:request_done(RequestId, ProfileName),
- ?hcrv("response (timeout) sent - now terminate", []),
{stop, normal,
State#state{request = Request#request{from = answer_sent},
canceled = [RequestId | Canceled]}};
-handle_info({timeout, RequestId},
+do_handle_info({timeout, RequestId},
#state{canceled = Canceled,
profile_name = ProfileName} = State) ->
- ?hcri("timeout", [{id, RequestId}]),
Filter =
fun(#request{id = Id, from = From} = Request) when Id =:= RequestId ->
- ?hcrv("found request", [{id, Id}, {from, From}]),
%% Notify the owner
httpc_response:send(From,
httpc_response:error(Request, timeout)),
httpc_manager:request_done(RequestId, ProfileName),
- ?hcrv("response (timeout) sent", []),
[Request#request{from = answer_sent}];
(_) ->
true
end,
case State#state.status of
pipeline ->
- ?hcrd("pipeline", []),
Pipeline = queue:filter(Filter, State#state.pipeline),
{noreply, State#state{canceled = [RequestId | Canceled],
pipeline = Pipeline}};
keep_alive ->
- ?hcrd("keep_alive", []),
KeepAlive = queue:filter(Filter, State#state.keep_alive),
{noreply, State#state{canceled = [RequestId | Canceled],
keep_alive = KeepAlive}}
end;
-handle_info(timeout_queue, State = #state{request = undefined}) ->
+do_handle_info(timeout_queue, State = #state{request = undefined}) ->
{stop, normal, State};
%% Timing was such as the queue_timeout was not canceled!
-handle_info(timeout_queue, #state{timers = Timers} = State) ->
+do_handle_info(timeout_queue, #state{timers = Timers} = State) ->
{noreply, State#state{timers =
Timers#timers{queue_timer = undefined}}};
%% Setting up the connection to the server somehow failed.
-handle_info({init_error, Tag, ClientErrMsg},
+do_handle_info({init_error, Reason, ClientErrMsg},
State = #state{request = Request}) ->
- ?hcrv("init error", [{tag, Tag}, {client_error, ClientErrMsg}]),
NewState = answer_request(Request, ClientErrMsg, State),
- {stop, normal, NewState};
-
+ {stop, {shutdown, Reason}, NewState};
%%% httpc_manager process dies.
-handle_info({'EXIT', _, _}, State = #state{request = undefined}) ->
+do_handle_info({'EXIT', _, _}, State = #state{request = undefined}) ->
{stop, normal, State};
%%Try to finish the current request anyway,
%% there is a fairly high probability that it can be done successfully.
%% Then close the connection, hopefully a new manager is started that
%% can retry requests in the pipeline.
-handle_info({'EXIT', _, _}, State) ->
+do_handle_info({'EXIT', _, _}, State) ->
{noreply, State#state{status = close}}.
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> _ (ignored by gen_server)
-%% Description: Shutdown the httpc_handler
-%%--------------------------------------------------------------------
-
-%% Init error there is no socket to be closed.
-terminate(normal,
- #state{request = Request,
- session = {send_failed, AReason} = Reason} = State) ->
- ?hcrd("terminate", [{send_reason, AReason}, {request, Request}]),
- maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
- State),
- ok;
-
-terminate(normal,
- #state{request = Request,
- session = {connect_failed, AReason} = Reason} = State) ->
- ?hcrd("terminate", [{connect_reason, AReason}, {request, Request}]),
- maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
- State),
- ok;
-
-terminate(normal, #state{session = undefined}) ->
- ok;
-
-%% Init error sending, no session information has been setup but
-%% there is a socket that needs closing.
-terminate(normal,
- #state{session = #session{id = undefined} = Session}) ->
- close_socket(Session);
-
-%% Socket closed remotely
-terminate(normal,
- #state{session = #session{socket = {remote_close, Socket},
- socket_type = SocketType,
- id = Id},
- profile_name = ProfileName,
- request = Request,
- timers = Timers,
- pipeline = Pipeline,
- keep_alive = KeepAlive} = State) ->
- ?hcrt("terminate(normal) - remote close",
- [{id, Id}, {profile, ProfileName}]),
-
- %% Clobber session
- (catch httpc_manager:delete_session(Id, ProfileName)),
-
- maybe_retry_queue(Pipeline, State),
- maybe_retry_queue(KeepAlive, State),
-
- %% Cancel timers
- cancel_timers(Timers),
-
- %% Maybe deliver answers to requests
- deliver_answer(Request),
-
- %% And, just in case, close our side (**really** overkill)
- http_transport:close(SocketType, Socket);
-
-terminate(Reason, #state{session = #session{id = Id,
- socket = Socket,
- socket_type = SocketType},
- request = undefined,
- profile_name = ProfileName,
- timers = Timers,
- pipeline = Pipeline,
- keep_alive = KeepAlive} = State) ->
- ?hcrt("terminate",
- [{id, Id}, {profile, ProfileName}, {reason, Reason}]),
-
- %% Clobber session
- (catch httpc_manager:delete_session(Id, ProfileName)),
-
- maybe_retry_queue(Pipeline, State),
- maybe_retry_queue(KeepAlive, State),
-
- cancel_timer(Timers#timers.queue_timer, timeout_queue),
- http_transport:close(SocketType, Socket);
+call(Msg, Pid) ->
+ call(Msg, Pid, infinity).
-terminate(Reason, #state{request = undefined}) ->
- ?hcrt("terminate", [{reason, Reason}]),
- ok;
+call(Msg, Pid, Timeout) ->
+ gen_server:call(Pid, Msg, Timeout).
-terminate(Reason, #state{request = Request} = State) ->
- ?hcrd("terminate", [{reason, Reason}, {request, Request}]),
- NewState = maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
- State),
- terminate(Reason, NewState#state{request = undefined}).
+cast(Msg, Pid) ->
+ gen_server:cast(Pid, Msg).
maybe_retry_queue(Q, State) ->
case queue:is_empty(Q) of
@@ -774,86 +735,13 @@ maybe_send_answer(#request{from = answer_sent}, _Reason, State) ->
maybe_send_answer(Request, Answer, State) ->
answer_request(Request, Answer, State).
-deliver_answer(#request{id = Id, from = From} = Request)
- when is_pid(From) ->
+deliver_answer(#request{from = From} = Request)
+ when From =/= answer_sent ->
Response = httpc_response:error(Request, socket_closed_remotely),
- ?hcrd("deliver answer", [{id, Id}, {from, From}, {response, Response}]),
httpc_response:send(From, Response);
-deliver_answer(Request) ->
- ?hcrd("skip deliver answer", [{request, Request}]),
+deliver_answer(_Request) ->
ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
-%% Purpose: Convert process state when code is changed
-%%--------------------------------------------------------------------
-
-code_change(_,
- #state{session = OldSession,
- profile_name = ProfileName} = State,
- upgrade_from_pre_5_8_1) ->
- case OldSession of
- {session,
- Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type} ->
- NewSession = #session{id = Id,
- client_close = ClientClose,
- scheme = Scheme,
- socket = Socket,
- socket_type = SocketType,
- queue_length = QueueLen,
- type = Type},
- insert_session(NewSession, ProfileName),
- {ok, State#state{session = NewSession}};
- _ ->
- {ok, State}
- end;
-
-code_change(_,
- #state{session = OldSession,
- profile_name = ProfileName} = State,
- downgrade_to_pre_5_8_1) ->
- case OldSession of
- #session{id = Id,
- client_close = ClientClose,
- scheme = Scheme,
- socket = Socket,
- socket_type = SocketType,
- queue_length = QueueLen,
- type = Type} ->
- NewSession = {session,
- Id, ClientClose, Scheme, Socket, SocketType,
- QueueLen, Type},
- insert_session(NewSession, ProfileName),
- {ok, State#state{session = NewSession}};
- _ ->
- {ok, State}
- end;
-
-code_change(_, State, _) ->
- {ok, State}.
-
-
-%% new_http_options({http_options, TimeOut, AutoRedirect, SslOpts,
-%% Auth, Relaxed}) ->
-%% {http_options, "HTTP/1.1", TimeOut, AutoRedirect, SslOpts,
-%% Auth, Relaxed}.
-
-%% old_http_options({http_options, _, TimeOut, AutoRedirect,
-%% SslOpts, Auth, Relaxed}) ->
-%% {http_options, TimeOut, AutoRedirect, SslOpts, Auth, Relaxed}.
-
-%% new_queue(Queue, Fun) ->
-%% List = queue:to_list(Queue),
-%% NewList =
-%% lists:map(fun(Request) ->
-%% Settings =
-%% Fun(Request#request.settings),
-%% Request#request{settings = Settings}
-%% end, List),
-%% queue:from_list(NewList).
-
-
%%%--------------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -911,31 +799,25 @@ connect(SocketType, ToAddress,
connect_and_send_first_request(Address, Request, #state{options = Options} = State) ->
SocketType = socket_type(Request),
ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
- ?hcri("connect",
- [{address, Address}, {request, Request}, {options, Options}]),
case connect(SocketType, Address, Options, ConnTimeout) of
{ok, Socket} ->
ClientClose =
- httpc_request:is_client_closing(
- Request#request.headers),
+ httpc_request:is_client_closing(
+ Request#request.headers),
SessionType = httpc_manager:session_type(Options),
SocketType = socket_type(Request),
Session = #session{id = {Request#request.address, self()},
scheme = Request#request.scheme,
socket = Socket,
- socket_type = SocketType,
- client_close = ClientClose,
- type = SessionType},
- ?hcri("connected - now send first request", [{socket, Socket}]),
-
+ socket_type = SocketType,
+ client_close = ClientClose,
+ type = SessionType},
case httpc_request:send(Address, Session, Request) of
ok ->
- ?hcri("first request sent", []),
TmpState = State#state{request = Request,
session = Session,
mfa = init_mfa(Request, State),
- status_line =
- init_status_line(Request),
+ status_line = init_status_line(Request),
headers = undefined,
body = undefined,
status = new},
@@ -947,8 +829,7 @@ connect_and_send_first_request(Address, Request, #state{options = Options} = Sta
self() ! {init_error, error_sending,
httpc_response:error(Request, Reason)},
{ok, State#state{request = Request,
- session =
- #session{socket = Socket}}}
+ session = #session{socket = Socket}}}
end;
{error, Reason} ->
self() ! {init_error, error_connecting,
@@ -990,12 +871,6 @@ handler_info(#state{request = Request,
options = _Options,
timers = _Timers} = _State) ->
- ?hcrt("handler info", [{request, Request},
- {session, Session},
- {pipeline, Pipeline},
- {keep_alive, KeepAlive},
- {status, Status}]),
-
%% Info about the current request
RequestInfo =
case Request of
@@ -1006,8 +881,6 @@ handler_info(#state{request = Request,
[{id, Id}, {started, ReqStarted}]
end,
- ?hcrt("handler info", [{request_info, RequestInfo}]),
-
%% Info about the current session/socket
SessionType = Session#session.type,
QueueLen = case SessionType of
@@ -1020,22 +893,12 @@ handler_info(#state{request = Request,
Socket = Session#session.socket,
SocketType = Session#session.socket_type,
- ?hcrt("handler info", [{session_type, SessionType},
- {queue_length, QueueLen},
- {scheme, Scheme},
- {socket, Socket}]),
-
SocketOpts = http_transport:getopts(SocketType, Socket),
SocketStats = http_transport:getstat(SocketType, Socket),
Remote = http_transport:peername(SocketType, Socket),
Local = http_transport:sockname(SocketType, Socket),
- ?hcrt("handler info", [{remote, Remote},
- {local, Local},
- {socket_opts, SocketOpts},
- {socket_stats, SocketStats}]),
-
SocketInfo = [{remote, Remote},
{local, Local},
{socket_opts, SocketOpts},
@@ -1055,7 +918,6 @@ handler_info(#state{request = Request,
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
State = #state{request = Request}) ->
- ?hcrt("handle_http_msg", [{headers, Headers}]),
case Headers#http_response_h.'content-type' of
"multipart/byteranges" ++ _Param ->
exit({not_yet_implemented, multypart_byteranges});
@@ -1069,15 +931,12 @@ handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
end;
handle_http_msg({ChunkedHeaders, Body},
#state{status_line = {_, Code, _}, headers = Headers} = State) ->
- ?hcrt("handle_http_msg",
- [{chunked_headers, ChunkedHeaders}, {headers, Headers}]),
NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
{_, NewBody, NewRequest} = stream(Body, State#state.request, Code),
handle_response(State#state{headers = NewHeaders,
body = NewBody,
request = NewRequest});
handle_http_msg(Body, #state{status_line = {_,Code, _}} = State) ->
- ?hcrt("handle_http_msg", [{code, Code}]),
{_, NewBody, NewRequest} = stream(Body, State#state.request, Code),
handle_response(State#state{body = NewBody, request = NewRequest}).
@@ -1092,41 +951,28 @@ handle_http_body(_, #state{status = {ssl_tunnel, Request},
{stop, normal, NewState};
handle_http_body(<<>>, #state{status_line = {_,304, _}} = State) ->
- ?hcrt("handle_http_body - 304", []),
handle_response(State#state{body = <<>>});
handle_http_body(<<>>, #state{status_line = {_,204, _}} = State) ->
- ?hcrt("handle_http_body - 204", []),
handle_response(State#state{body = <<>>});
handle_http_body(<<>>, #state{request = #request{method = head}} = State) ->
- ?hcrt("handle_http_body - head", []),
handle_response(State#state{body = <<>>});
handle_http_body(Body, #state{headers = Headers,
max_body_size = MaxBodySize,
status_line = {_,Code, _},
request = Request} = State) ->
- ?hcrt("handle_http_body",
- [{max_body_size, MaxBodySize}, {headers, Headers}, {code, Code}]),
TransferEnc = Headers#http_response_h.'transfer-encoding',
case case_insensitive_header(TransferEnc) of
"chunked" ->
- ?hcrt("handle_http_body - chunked", []),
try http_chunk:decode(Body, State#state.max_body_size,
State#state.max_header_size) of
{Module, Function, Args} ->
- ?hcrt("handle_http_body - new mfa",
- [{module, Module},
- {function, Function},
- {args, Args}]),
NewState = next_body_chunk(State, Code),
{noreply, NewState#state{mfa =
{Module, Function, Args}}};
{ok, {ChunkedHeaders, NewBody}} ->
- ?hcrt("handle_http_body - new body",
- [{chunked_headers, ChunkedHeaders},
- {new_body, NewBody}]),
NewHeaders = http_chunk:handle_headers(Headers,
ChunkedHeaders),
case Body of
@@ -1148,7 +994,6 @@ handle_http_body(Body, #state{headers = Headers,
{stop, normal, NewState}
end;
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
@@ -1172,7 +1017,6 @@ handle_http_body(Body, #state{headers = Headers,
{stop, normal, NewState}
end;
Encoding when is_list(Encoding) ->
- ?hcrt("handle_http_body - other", [{encoding, Encoding}]),
NewState = answer_request(Request,
httpc_response:error(Request,
unknown_encoding),
@@ -1193,18 +1037,10 @@ handle_response(#state{request = Request,
options = Options,
profile_name = ProfileName} = State)
when Status =/= new ->
-
- ?hcrd("handle response", [{profile, ProfileName},
- {status, Status},
- {request, Request},
- {session, Session},
- {status_line, StatusLine}]),
-
handle_cookies(Headers, Request, Options, ProfileName),
case httpc_response:result({StatusLine, Headers, Body}, Request) of
%% 100-continue
continue ->
- ?hcrd("handle response - continue", []),
%% Send request body
{_, RequestBody} = Request#request.content,
send_raw(Session, RequestBody),
@@ -1221,7 +1057,6 @@ handle_response(#state{request = Request,
%% Ignore unexpected 100-continue response and receive the
%% actual response that the server will send right away.
{ignore, Data} ->
- ?hcrd("handle response - ignore", [{data, Data}]),
Relaxed = (Request#request.settings)#http_options.relaxed,
MFA = {httpc_response, parse,
[State#state.max_header_size, Relaxed]},
@@ -1235,23 +1070,17 @@ handle_response(#state{request = Request,
%% obsolete and the manager will create a new request
%% with the same id as the current.
{redirect, NewRequest, Data} ->
- ?hcrt("handle response - redirect",
- [{new_request, NewRequest}, {data, Data}]),
ok = httpc_manager:redirect_request(NewRequest, ProfileName),
handle_queue(State#state{request = undefined}, Data);
{retry, TimeNewRequest, Data} ->
- ?hcrt("handle response - retry",
- [{time_new_request, TimeNewRequest}, {data, Data}]),
ok = httpc_manager:retry_request(TimeNewRequest, ProfileName),
handle_queue(State#state{request = undefined}, Data);
{ok, Msg, Data} ->
- ?hcrd("handle response - ok", []),
stream_remaining_body(Body, Request, StatusLine),
end_stream(StatusLine, Request),
NewState = maybe_send_answer(Request, Msg, State),
handle_queue(NewState, Data);
{stop, Msg} ->
- ?hcrd("handle response - stop", [{msg, Msg}]),
end_stream(StatusLine, Request),
NewState = maybe_send_answer(Request, Msg, State),
{stop, normal, NewState}
@@ -1286,28 +1115,19 @@ handle_pipeline(#state{status = pipeline,
profile_name = ProfileName,
options = #options{pipeline_timeout = TimeOut}} = State,
Data) ->
-
- ?hcrd("handle pipeline", [{profile, ProfileName},
- {session, Session},
- {timeout, TimeOut}]),
-
case queue:out(State#state.pipeline) of
{empty, _} ->
- ?hcrd("pipeline queue empty", []),
handle_empty_queue(Session, ProfileName, TimeOut, State);
{{value, NextRequest}, Pipeline} ->
- ?hcrd("pipeline queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
- ?hcrv("next request had been cancelled", []),
%% See comment for handle_cast({cancel, RequestId})
{stop, normal,
State#state{request =
NextRequest#request{from = answer_sent},
pipeline = Pipeline}};
false ->
- ?hcrv("next request", [{request, NextRequest}]),
NewSession =
Session#session{queue_length =
%% Queue + current
@@ -1324,25 +1144,16 @@ handle_keep_alive_queue(#state{status = keep_alive,
options = #options{keep_alive_timeout = TimeOut,
proxy = Proxy}} = State,
Data) ->
-
- ?hcrd("handle keep_alive", [{profile, ProfileName},
- {session, Session},
- {timeout, TimeOut}]),
-
case queue:out(State#state.keep_alive) of
{empty, _} ->
- ?hcrd("keep_alive queue empty", []),
handle_empty_queue(Session, ProfileName, TimeOut, State);
{{value, NextRequest}, KeepAlive} ->
- ?hcrd("keep_alive queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
- ?hcrv("next request has already been canceled", []),
handle_keep_alive_queue(
State#state{keep_alive = KeepAlive}, Data);
false ->
- ?hcrv("next request", [{request, NextRequest}]),
#request{address = Addr} = NextRequest,
Address = handle_proxy(Addr, Proxy),
case httpc_request:send(Address, Session, NextRequest) of
@@ -1355,7 +1166,6 @@ handle_keep_alive_queue(#state{status = keep_alive,
end
end
end.
-
handle_empty_queue(Session, ProfileName, TimeOut, State) ->
%% The server may choose too terminate an idle pipline| keep_alive session
%% in this case we want to receive the close message
@@ -1365,17 +1175,20 @@ handle_empty_queue(Session, ProfileName, TimeOut, State) ->
%% If a pipline | keep_alive session has been idle for some time is not
%% closed by the server, the client may want to close it.
NewState = activate_queue_timeout(TimeOut, State),
- update_session(ProfileName, Session, #session.queue_length, 0),
- %% Note mfa will be initialized when a new request
- %% arrives.
- {noreply,
- NewState#state{request = undefined,
- mfa = undefined,
- status_line = undefined,
- headers = undefined,
- body = undefined
- }
- }.
+ case update_session(ProfileName, Session, #session.queue_length, 0) of
+ {stop, Reason} ->
+ {stop, {shutdown, Reason}, State};
+ _ ->
+ %% Note mfa will be initialized when a new request
+ %% arrives.
+ {noreply,
+ NewState#state{request = undefined,
+ mfa = undefined,
+ status_line = undefined,
+ headers = undefined,
+ body = undefined
+ }}
+ end.
receive_response(Request, Session, Data, State) ->
NewState = init_wait_for_response_state(Request, State),
@@ -1391,7 +1204,6 @@ init_wait_for_response_state(Request, State) ->
status_line = undefined,
headers = undefined,
body = undefined}.
-
gather_data(<<>>, Session, State) ->
activate_once(Session),
{noreply, State};
@@ -1415,29 +1227,29 @@ close_socket(#session{socket = Socket, socket_type = SocketType}) ->
http_transport:close(SocketType, Socket).
activate_request_timeout(
- #state{request = #request{timer = undefined} = Request} = State) ->
+ #state{request = #request{timer = OldRef} = Request} = State) ->
Timeout = (Request#request.settings)#http_options.timeout,
case Timeout of
infinity ->
State;
_ ->
ReqId = Request#request.id,
- ?hcrt("activate request timer",
- [{request_id, ReqId},
- {time_consumed, t() - Request#request.started},
- {timeout, Timeout}]),
Msg = {timeout, ReqId},
+ case OldRef of
+ undefined ->
+ ok;
+ _ ->
+ %% Timer is already running! This is the case for a redirect or retry
+ %% We need to restart the timer because the handler pid has changed
+ cancel_timer(OldRef, Msg)
+ end,
Ref = erlang:send_after(Timeout, self(), Msg),
Request2 = Request#request{timer = Ref},
ReqTimers = [{Request#request.id, Ref} |
(State#state.timers)#timers.request_timers],
Timers = #timers{request_timers = ReqTimers},
State#state{request = Request2, timers = Timers}
- end;
-
-%% Timer is already running! This is the case for a redirect or retry
-activate_request_timeout(State) ->
- State.
+ end.
activate_queue_timeout(infinity, State) ->
State;
@@ -1468,10 +1280,6 @@ try_to_enable_pipeline_or_keep_alive(
status_line = {Version, _, _},
headers = Headers,
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
true ->
@@ -1496,7 +1304,6 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg,
#state{session = Session,
timers = Timers,
profile_name = ProfileName} = State) ->
- ?hcrt("answer request", [{request, Request}, {msg, Msg}]),
httpc_response:send(From, Msg),
RequestTimers = Timers#timers.request_timers,
TimerRef =
@@ -1643,42 +1450,32 @@ socket_type(#request{scheme = http}) ->
ip_comm;
socket_type(#request{scheme = https, settings = Settings}) ->
Settings#http_options.ssl.
-%% socket_type(http) ->
-%% ip_comm;
-%% socket_type(https) ->
-%% {ssl1, []}. %% Dummy value ok for ex setopts that does not use this value
start_stream({_Version, _Code, _ReasonPhrase}, _Headers,
#request{stream = none} = Request) ->
- ?hcrt("start stream - none", []),
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, Headers,
#request{stream = self} = Request)
when ?IS_STREAMED(Code) ->
- ?hcrt("start stream - self", [{code, Code}]),
Msg = httpc_response:stream_start(Headers, Request, ignore),
httpc_response:send(Request#request.from, Msg),
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, Headers,
#request{stream = {self, once}} = Request)
when ?IS_STREAMED(Code) ->
- ?hcrt("start stream - self:once", [{code, Code}]),
Msg = httpc_response:stream_start(Headers, Request, self()),
httpc_response:send(Request#request.from, Msg),
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, _Headers,
#request{stream = Filename} = Request)
when ?IS_STREAMED(Code) andalso is_list(Filename) ->
- ?hcrt("start stream", [{code, Code}, {filename, Filename}]),
case file:open(Filename, [write, raw, append, delayed_write]) of
{ok, Fd} ->
- ?hcri("start stream - file open ok", [{fd, Fd}]),
{ok, Request#request{stream = Fd}};
{error, Reason} ->
exit({stream_to_file_failed, Reason})
end;
start_stream(_StatusLine, _Headers, Request) ->
- ?hcrt("start stream - no op", []),
{ok, Request}.
stream_remaining_body(<<>>, _, _) ->
@@ -1689,16 +1486,12 @@ stream_remaining_body(Body, Request, {_, Code, _}) ->
%% Note the end stream message is handled by httpc_response and will
%% be sent by answer_request
end_stream(_, #request{stream = none}) ->
- ?hcrt("end stream - none", []),
ok;
end_stream(_, #request{stream = self}) ->
- ?hcrt("end stream - self", []),
ok;
end_stream(_, #request{stream = {self, once}}) ->
- ?hcrt("end stream - self:once", []),
ok;
end_stream({_,200,_}, #request{stream = Fd}) ->
- ?hcrt("end stream - 200", [{stream, Fd}]),
case file:close(Fd) of
ok ->
ok;
@@ -1706,15 +1499,13 @@ end_stream({_,200,_}, #request{stream = Fd}) ->
file:close(Fd)
end;
end_stream({_,206,_}, #request{stream = Fd}) ->
- ?hcrt("end stream - 206", [{stream, Fd}]),
case file:close(Fd) of
ok ->
ok;
{error, enospc} -> % Could be due to delayed_write
file:close(Fd)
end;
-end_stream(SL, R) ->
- ?hcrt("end stream", [{status_line, SL}, {request, R}]),
+end_stream(_, _) ->
ok.
@@ -1743,11 +1534,8 @@ handle_verbose(trace) ->
handle_verbose(_) ->
ok.
-
-
send_raw(#session{socket = Socket, socket_type = SocketType},
{ProcessBody, Acc}) when is_function(ProcessBody, 1) ->
- ?hcrt("send raw", [{acc, Acc}]),
send_raw(SocketType, Socket, ProcessBody, Acc);
send_raw(#session{socket = Socket, socket_type = SocketType}, Body) ->
http_transport:send(SocketType, Socket, Body).
@@ -1758,7 +1546,6 @@ send_raw(SocketType, Socket, ProcessBody, Acc) ->
ok;
{ok, Data, NewAcc} ->
DataBin = iolist_to_binary(Data),
- ?hcrd("send", [{data, DataBin}]),
case http_transport:send(SocketType, Socket, DataBin) of
ok ->
send_raw(SocketType, Socket, ProcessBody, NewAcc);
@@ -1790,14 +1577,16 @@ tls_tunnel(Address, Request, #state{session = #session{socket = Socket,
tls_tunnel_request(#request{headers = Headers,
settings = Options,
+ id = RequestId,
+ from = From,
address = {Host, Port}= Adress,
ipv6_host_with_brackets = IPV6}) ->
URI = Host ++":" ++ integer_to_list(Port),
#request{
- id = make_ref(),
- from = self(),
+ id = RequestId,
+ from = From,
scheme = http, %% Use tcp-first and then upgrade!
address = Adress,
path = URI,
@@ -1887,10 +1676,13 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
httpc_manager:update_session(ProfileName, SessionId, Pos, Value)
end
catch
- error:undef -> % This could happen during code upgrade
+ error:undef -> %% This could happen during code upgrade
Session2 = erlang:setelement(Pos, Session, Value),
insert_session(Session2, ProfileName);
- T:E ->
+ error:badarg ->
+ {stop, normal};
+ T:E ->
+ %% Unexpected this must be an error!
Stacktrace = erlang:get_stacktrace(),
error_logger:error_msg("Failed updating session: "
"~n ProfileName: ~p"
@@ -1908,27 +1700,14 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
Session,
(catch httpc_manager:lookup_session(SessionId, ProfileName)),
T, E]),
- exit({failed_updating_session,
- [{profile, ProfileName},
- {session_id, SessionId},
- {pos, Pos},
- {value, Value},
- {etype, T},
- {error, E},
- {stacktrace, Stacktrace}]})
+ {stop, {failed_updating_session,
+ [{profile, ProfileName},
+ {session_id, SessionId},
+ {pos, Pos},
+ {value, Value},
+ {etype, T},
+ {error, E},
+ {stacktrace, Stacktrace}]}}
end.
-%% ---------------------------------------------------------------------
-
-call(Msg, Pid) ->
- Timeout = infinity,
- call(Msg, Pid, Timeout).
-call(Msg, Pid, Timeout) ->
- gen_server:call(Pid, Msg, Timeout).
-
-cast(Msg, Pid) ->
- gen_server:cast(Pid, Msg).
-
-t() ->
- http_util:timestamp().
diff --git a/lib/inets/src/http_client/httpc_handler_sup.erl b/lib/inets/src/http_client/httpc_handler_sup.erl
index 403512fc25..ad70afe2ae 100644
--- a/lib/inets/src/http_client/httpc_handler_sup.erl
+++ b/lib/inets/src/http_client/httpc_handler_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index bb8c0e20fa..5f8c70f28d 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,32 +43,32 @@
%%% HTTP Client per request settings
-record(http_options,
{
- %% string() - "HTTP/1.1" | "HTTP/1.0" | "HTTP/0.9"
- version,
+ %% "HTTP/1.1" | "HTTP/1.0" | "HTTP/0.9"
+ version :: 'undefined' | string(),
- %% integer() | infinity - ms before a request times out
- timeout = ?HTTP_REQUEST_TIMEOUT,
+ %% ms before a request times out
+ timeout = ?HTTP_REQUEST_TIMEOUT :: timeout(),
- %% bool() - true if auto redirect on 30x response
- autoredirect = true,
+ %% true if auto redirect on 30x response
+ autoredirect = true :: boolean(),
%% ssl socket options
- ssl = [],
+ ssl = [],
%% {User, Password} = {string(), string()}
proxy_auth,
- %% bool() - true if not strictly std compliant
- relaxed = false,
+ %% true if not strictly std compliant
+ relaxed = false :: boolean(),
%% integer() - ms before a connect times out
- connect_timeout = ?HTTP_REQUEST_CTIMEOUT,
-
- %% bool() - Use %-encoding rfc 2396
- url_encode
+ connect_timeout = ?HTTP_REQUEST_CTIMEOUT :: timeout(),
+ %% Use %-encoding rfc 2396
+ url_encode :: 'undefined' | boolean()
}
).
+-type http_options() :: #http_options{}.
%%% HTTP Client per profile setting.
-record(options,
@@ -82,18 +82,19 @@
keep_alive_timeout = ?HTTP_KEEP_ALIVE_TIMEOUT, % Used when pipeline_timeout = 0
max_sessions = ?HTTP_MAX_TCP_SESSIONS,
cookies = disabled, % enabled | disabled | verify
- verbose = false,
+ verbose = false, % boolean(),
ipfamily = inet, % inet | inet6 | inet6fb4
ip = default, % specify local interface
port = default, % specify local port
socket_opts = [] % other socket options
}
).
+-type options() :: #options{}.
%%% All data associated to a specific HTTP request
-record(request,
{
- id, % ref() - Request Id
+ id :: 'undefined' | reference(), % Request Id
from, % pid() - Caller
redircount = 0,% Number of redirects made for this request
scheme, % http | https
@@ -103,7 +104,7 @@
method, % atom() - HTTP request Method
headers, % #http_request_h{}
content, % {ContentType, Body} - Current HTTP request
- settings, % #http_options{} - User defined settings
+ settings :: http_options(), % User defined settings
abs_uri, % string() ex: "http://www.erlang.org"
userinfo, % string() - optinal "<userinfo>@<host>:<port>"
stream, % boolean() - stream async reply?
@@ -112,20 +113,19 @@
% for testing purposes.
started, % integer() > 0 - When we started processing the
% request
- timer, % undefined | ref()
+ timer :: undefined | reference(),
socket_opts, % undefined | [socket_option()]
ipv6_host_with_brackets % boolean()
}
- ).
-
+ ).
+-type request() :: #request{}.
-record(session,
{
%% {{Host, Port}, HandlerPid}
id,
- %% true | false
- client_close,
+ client_close :: 'undefined' | boolean(),
%% http (HTTP/TCP) | https (HTTP/SSL/TCP)
scheme,
@@ -140,14 +140,13 @@
queue_length = 1,
%% pipeline | keep_alive (wait for response before sending new request)
- type,
+ type :: 'undefined' | 'pipeline' | 'keep_alive',
- %% true | false
%% This will be true, when a response has been received for
%% the first request. See type above.
- available = false
+ available = false :: boolean()
}).
-
+-type session() :: #session{}.
-record(http_cookie,
{
@@ -162,7 +161,7 @@
secure = false,
version = "0"
}).
-
+-type http_cookie() :: #http_cookie{}.
%% -record(parsed_uri,
%% {
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index c7974836c2..a63864493f 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -137,7 +137,7 @@ redirect_request(Request, ProfileName) ->
%%--------------------------------------------------------------------
%% Function: cancel_request(RequestId, ProfileName) -> ok
-%% RequestId - ref()
+%% RequestId - reference()
%% ProfileName = atom()
%%
%% Description: Cancels the request with <RequestId>.
@@ -148,7 +148,7 @@ cancel_request(RequestId, ProfileName) ->
%%--------------------------------------------------------------------
%% Function: request_done(RequestId, ProfileName) -> ok
-%% RequestId - ref()
+%% RequestId - reference()
%% ProfileName = atom()
%%
%% Description: Inform tha manager that a request has been completed.
diff --git a/lib/inets/src/http_client/httpc_profile_sup.erl b/lib/inets/src/http_client/httpc_profile_sup.erl
index b83aeaa4e0..334f2eb1c7 100644
--- a/lib/inets/src/http_client/httpc_profile_sup.erl
+++ b/lib/inets/src/http_client/httpc_profile_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index af4c3f75f2..89872a3831 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -88,9 +88,11 @@ send(SendAddr, Socket, SocketType,
case Address of
SendAddr ->
{TmpHdrs2, Path ++ Query};
- _Proxy ->
+ _Proxy when SocketType == ip_comm ->
TmpHdrs3 = handle_proxy(HttpOptions, TmpHdrs2),
- {TmpHdrs3, AbsUri}
+ {TmpHdrs3, AbsUri};
+ _ ->
+ {TmpHdrs2, Path ++ Query}
end,
FinalHeaders =
@@ -186,16 +188,19 @@ is_client_closing(Headers) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
-post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
- when (Method =:= post) orelse (Method =:= put)
- orelse (Method =:= patch) ->
+post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
+ when (Method =:= post)
+ orelse (Method =:= put)
+ orelse (Method =:= patch)
+ orelse (Method =:= delete) ->
+
NewBody = case Headers#http_request_h.expect of
- "100-continue" ->
- "";
- _ ->
- Body
- end,
-
+ "100-continue" ->
+ "";
+ _ ->
+ Body
+ end,
+
NewHeaders = case HeadersAsIs of
[] ->
Headers#http_request_h{
@@ -213,7 +218,7 @@ post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
_ ->
HeadersAsIs
end,
-
+
{NewHeaders, NewBody};
post_data(_, Headers, _, []) ->
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 4bf2ba2b9b..91638f5d2e 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -110,27 +110,30 @@ result(Response = {{_, 300, _}, _, _},
redirect(Response, Request);
result(Response = {{_, Code, _}, _, _},
+ Request = #request{settings =
+ #http_options{autoredirect = true},
+ method = post}) when (Code =:= 301) orelse
+ (Code =:= 302) orelse
+ (Code =:= 303) ->
+ redirect(Response, Request#request{method = get});
+result(Response = {{_, Code, _}, _, _},
+ Request = #request{settings =
+ #http_options{autoredirect = true},
+ method = post}) when (Code =:= 307) ->
+ redirect(Response, Request);
+result(Response = {{_, Code, _}, _, _},
Request = #request{settings =
#http_options{autoredirect = true},
- method = head}) when (Code =:= 301) orelse
+ method = Method}) when (Code =:= 301) orelse
(Code =:= 302) orelse
(Code =:= 303) orelse
(Code =:= 307) ->
- redirect(Response, Request);
-result(Response = {{_, Code, _}, _, _},
- Request = #request{settings =
- #http_options{autoredirect = true},
- method = get}) when (Code =:= 301) orelse
- (Code =:= 302) orelse
- (Code =:= 303) orelse
- (Code =:= 307) ->
- redirect(Response, Request);
-result(Response = {{_, 303, _}, _, _},
- Request = #request{settings =
- #http_options{autoredirect = true},
- method = post}) ->
- redirect(Response, Request#request{method = get});
-
+ case lists:member(Method, [get, head, options, trace]) of
+ true ->
+ redirect(Response, Request);
+ false ->
+ transparent(Response, Request)
+ end;
result(Response = {{_,503,_}, _, _}, Request) ->
status_service_unavailable(Response, Request);
@@ -266,7 +269,7 @@ parse_headers(<<?LF,?LF,Body/binary>>, Header, Headers,
MaxHeaderSize, Result, Relaxed);
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers,
- MaxHeaderSize, Result, _) ->
+ MaxHeaderSize, Result, Relaxed) ->
HTTPHeaders = [lists:reverse(Header) | Headers],
Length = lists:foldl(fun(H, Acc) -> length(H) + Acc end,
0, HTTPHeaders),
@@ -274,8 +277,42 @@ parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers,
true ->
ResponseHeaderRcord =
http_response:headers(HTTPHeaders, #http_response_h{}),
- {ok, list_to_tuple(
- lists:reverse([Body, ResponseHeaderRcord | Result]))};
+
+ %% RFC7230, Section 3.3.3
+ %% If a message is received with both a Transfer-Encoding and a
+ %% Content-Length header field, the Transfer-Encoding overrides the
+ %% Content-Length. Such a message might indicate an attempt to
+ %% perform request smuggling (Section 9.5) or response splitting
+ %% (Section 9.4) and ought to be handled as an error. A sender MUST
+ %% remove the received Content-Length field prior to forwarding such
+ %% a message downstream.
+ case ResponseHeaderRcord#http_response_h.'transfer-encoding' of
+ undefined ->
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcord | Result]))};
+ Value ->
+ TransferEncoding = string:lowercase(Value),
+ ContentLength = ResponseHeaderRcord#http_response_h.'content-length',
+ if
+ %% Respond without error but remove Content-Length field in relaxed mode
+ (Relaxed =:= true)
+ andalso (TransferEncoding =:= "chunked")
+ andalso (ContentLength =/= "-1") ->
+ ResponseHeaderRcordFixed =
+ ResponseHeaderRcord#http_response_h{'content-length' = "-1"},
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcordFixed | Result]))};
+ %% Respond with error in default (not relaxed) mode
+ (Relaxed =:= false)
+ andalso (TransferEncoding =:= "chunked")
+ andalso (ContentLength =/= "-1") ->
+ throw({error, {headers_conflict, {'content-length',
+ 'transfer-encoding'}}});
+ true ->
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcord | Result]))}
+ end
+ end;
false ->
throw({error, {header_too_long, MaxHeaderSize,
MaxHeaderSize-Length}})
@@ -359,8 +396,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) ->
{ok, error(Request, Reason), Data};
%% Automatic redirection
{ok, {Scheme, _, Host, Port, Path, Query}} ->
+ HostPort = http_request:normalize_host(Scheme, Host, Port),
NewHeaders =
- (Request#request.headers)#http_request_h{host = Host},
+ (Request#request.headers)#http_request_h{host = HostPort},
NewRequest =
Request#request{redircount =
Request#request.redircount+1,
@@ -431,7 +469,7 @@ format_response({StatusLine, Headers, Body}) ->
Length = list_to_integer(Headers#http_response_h.'content-length'),
{NewBody, Data} =
case Length of
- -1 -> % When no lenght indicator is provided
+ -1 -> % When no length indicator is provided
{Body, <<>>};
Length when (Length =< size(Body)) ->
<<BodyThisReq:Length/binary, Next/binary>> = Body,
diff --git a/lib/inets/src/http_client/httpc_sup.erl b/lib/inets/src/http_client/httpc_sup.erl
index 2b2ee0f34a..b2d944c834 100644
--- a/lib/inets/src/http_client/httpc_sup.erl
+++ b/lib/inets/src/http_client/httpc_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_lib/Makefile b/lib/inets/src/http_lib/Makefile
index 4a4eef9f24..8248e37c44 100644
--- a/lib/inets/src/http_lib/Makefile
+++ b/lib/inets/src/http_lib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 7325f24809..742d634577 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_lib/http_internal.hrl b/lib/inets/src/http_lib/http_internal.hrl
index ae92b5df8f..ca1dad07cd 100644
--- a/lib/inets/src/http_lib/http_internal.hrl
+++ b/lib/inets/src/http_lib/http_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@
'last-modified',
other=[] % list() - Key/Value list with other headers
}).
-
+-type http_response_h() :: #http_response_h{}.
%%% Request headers
-record(http_request_h,{
@@ -118,5 +118,6 @@
'last-modified',
other=[] % list() - Key/Value list with other headers
}).
+-type http_request_h() :: #http_request_h{}.
-endif. % -ifdef(http_internal_hrl).
diff --git a/lib/inets/src/http_lib/http_request.erl b/lib/inets/src/http_lib/http_request.erl
index c77b616f0d..f68b233e10 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-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
-include("http_internal.hrl").
--export([headers/2, http_headers/1, is_absolut_uri/1, key_value/1]).
+-export([headers/2, http_headers/1, is_absolut_uri/1, key_value/1, normalize_host/3]).
key_value(KeyValueStr) ->
@@ -85,6 +85,22 @@ is_absolut_uri("https://" ++ _) ->
is_absolut_uri(_) ->
false.
+%%-------------------------------------------------------------------------
+%% normalize_host(Scheme, Host, Port) -> string()
+%% Scheme - http | https
+%% Host - string()
+%% Port - integer()
+%%
+%% Description: returns a normalized Host header value, with the port
+%% number omitted for well-known ports
+%%-------------------------------------------------------------------------
+normalize_host(https, Host, 443 = _Port) ->
+ Host;
+normalize_host(http, Host, 80 = _Port) ->
+ Host;
+normalize_host(_Scheme, Host, Port) ->
+ Host ++ ":" ++ integer_to_list(Port).
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl
index 42e5dd263d..cbdea82523 100644
--- a/lib/inets/src/http_lib/http_response.erl
+++ b/lib/inets/src/http_lib/http_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index ab6afe9c6c..2e3e099e5b 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index 9940136f5a..7f1ca02014 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -102,15 +102,20 @@ parse(AbsURI, Opts) ->
reserved() ->
sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
- $#, $[, $], $<, $>, $\", ${, $}, $|,
+ $#, $[, $], $<, $>, $\", ${, $}, $|, %"
$\\, $', $^, $%, $ ]).
-encode(URI) ->
+encode(URI) when is_list(URI) ->
Reserved = reserved(),
- lists:append([uri_encode(Char, Reserved) || Char <- URI]).
+ lists:append([uri_encode(Char, Reserved) || Char <- URI]);
+encode(URI) when is_binary(URI) ->
+ Reserved = reserved(),
+ << <<(uri_encode_binary(Char, Reserved))/binary>> || <<Char>> <= URI >>.
-decode(String) ->
- do_decode(String).
+decode(String) when is_list(String) ->
+ do_decode(String);
+decode(String) when is_binary(String) ->
+ do_decode_binary(String).
do_decode([$%,Hex1,Hex2|Rest]) ->
[hex2dec(Hex1)*16+hex2dec(Hex2)|do_decode(Rest)];
@@ -119,6 +124,12 @@ do_decode([First|Rest]) ->
do_decode([]) ->
[].
+do_decode_binary(<<$%, Hex:2/binary, Rest/bits>>) ->
+ <<(binary_to_integer(Hex, 16)), (do_decode_binary(Rest))/binary>>;
+do_decode_binary(<<First:1/binary, Rest/bits>>) ->
+ <<First/binary, (do_decode_binary(Rest))/binary>>;
+do_decode_binary(<<>>) ->
+ <<>>.
%%%========================================================================
%%% Internal functions
@@ -162,9 +173,30 @@ extract_scheme(Str, Opts) ->
{error, Error}
end;
_ ->
- {ok, list_to_atom(http_util:to_lower(Str))}
+ {ok, to_atom(http_util:to_lower(Str))}
end.
+to_atom(S) when is_list(S) ->
+ list_to_atom(S);
+to_atom(S) when is_binary(S) ->
+ binary_to_atom(S, unicode).
+
+parse_uri_rest(Scheme, DefaultPort, <<"//", URIPart/binary>>, Opts) ->
+ {Authority, PathQueryFragment} =
+ split_uri(URIPart, "[/?#]", {URIPart, <<"">>}, 1, 0),
+ {RawPath, QueryFragment} =
+ split_uri(PathQueryFragment, "[?#]", {PathQueryFragment, <<"">>}, 1, 0),
+ {Query, Fragment} =
+ split_uri(QueryFragment, "#", {QueryFragment, <<"">>}, 1, 0),
+ {UserInfo, HostPort} = split_uri(Authority, "@", {<<"">>, Authority}, 1, 1),
+ {Host, Port} = parse_host_port(Scheme, DefaultPort, HostPort, Opts),
+ Path = path(RawPath),
+ case lists:keyfind(fragment, 1, Opts) of
+ {fragment, true} ->
+ {ok, {Scheme, UserInfo, Host, Port, Path, Query, Fragment}};
+ _ ->
+ {ok, {Scheme, UserInfo, Host, Port, Path, Query}}
+ end;
parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) ->
{Authority, PathQueryFragment} =
split_uri(URIPart, "[/?#]", {URIPart, ""}, 1, 0),
@@ -185,6 +217,11 @@ parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) ->
%% In this version of the function, we no longer need
%% the Scheme argument, but just in case...
+parse_host_port(_Scheme, DefaultPort, <<"[", HostPort/binary>>, Opts) -> %ipv6
+ {Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, <<"">>}, 1, 1),
+ Host2 = maybe_ipv6_host_with_brackets(Host, Opts),
+ {_, Port} = split_uri(ColonPort, ":", {<<"">>, DefaultPort}, 0, 1),
+ {Host2, int_port(Port)};
parse_host_port(_Scheme, DefaultPort, "[" ++ HostPort, Opts) -> %ipv6
{Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, ""}, 1, 1),
Host2 = maybe_ipv6_host_with_brackets(Host, Opts),
@@ -198,12 +235,19 @@ parse_host_port(_Scheme, DefaultPort, HostPort, _Opts) ->
split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
case re:run(UriPart, SplitChar, [{capture, first}]) of
{match, [{Match, _}]} ->
- {string:substr(UriPart, 1, Match + 1 - SkipLeft),
- string:substr(UriPart, Match + 1 + SkipRight, length(UriPart))};
+ {string:slice(UriPart, 0, Match + 1 - SkipLeft),
+ string:slice(UriPart, Match + SkipRight, string:length(UriPart))};
nomatch ->
NoMatchResult
end.
+maybe_ipv6_host_with_brackets(Host, Opts) when is_binary(Host) ->
+ case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of
+ {value, {ipv6_host_with_brackets, true}} ->
+ <<"[", Host/binary, "]">>;
+ _ ->
+ Host
+ end;
maybe_ipv6_host_with_brackets(Host, Opts) ->
case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of
{value, {ipv6_host_with_brackets, true}} ->
@@ -212,15 +256,18 @@ maybe_ipv6_host_with_brackets(Host, Opts) ->
Host
end.
-
int_port(Port) when is_integer(Port) ->
Port;
+int_port(Port) when is_binary(Port) ->
+ binary_to_integer(Port);
int_port(Port) when is_list(Port) ->
list_to_integer(Port);
%% This is the case where no port was found and there was no default port
int_port(no_default_port) ->
throw({error, no_default_port}).
+path(<<"">>) ->
+ <<"/">>;
path("") ->
"/";
path(Path) ->
@@ -234,6 +281,14 @@ uri_encode(Char, Reserved) ->
[Char]
end.
+uri_encode_binary(Char, Reserved) ->
+ case sets:is_element(Char, Reserved) of
+ true ->
+ << $%, (integer_to_binary(Char, 16))/binary >>;
+ false ->
+ <<Char>>
+ end.
+
hex2dec(X) when (X>=$0) andalso (X=<$9) -> X-$0;
hex2dec(X) when (X>=$A) andalso (X=<$F) -> X-$A+10;
hex2dec(X) when (X>=$a) andalso (X=<$f) -> X-$a+10.
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index aafa97afee..487d04f7aa 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,10 +35,10 @@
%%% Internal application API
%%%=========================================================================
to_upper(Str) ->
- string:to_upper(Str).
+ string:uppercase(Str).
to_lower(Str) ->
- string:to_lower(Str).
+ string:lowercase(Str).
%% Example: Mon, 09-Dec-2002 13:46:00 GMT
convert_netscapecookie_date([_D,_A,_Y, $,, $ ,
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index e6377b4882..540e68e749 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -99,7 +99,14 @@ start_service(Conf) ->
stop_service({Address, Port}) ->
stop_service({Address, Port, ?DEFAULT_PROFILE});
stop_service({Address, Port, Profile}) ->
- httpd_sup:stop_child(Address, Port, Profile);
+ Name = httpd_util:make_name("httpd_instance_sup", Address, Port, Profile),
+ Pid = whereis(Name),
+ MonitorRef = erlang:monitor(process, Pid),
+ Result = httpd_sup:stop_child(Address, Port, Profile),
+ receive
+ {'DOWN', MonitorRef, _, _, _} ->
+ Result
+ end;
stop_service(Pid) when is_pid(Pid) ->
case service_info(Pid) of
{ok, Info} ->
diff --git a/lib/inets/src/http_server/httpd.hrl b/lib/inets/src/http_server/httpd.hrl
index 29dc45f93a..751264ae0a 100644
--- a/lib/inets/src/http_server/httpd.hrl
+++ b/lib/inets/src/http_server/httpd.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index adccaf3b69..447faec12f 100644
--- a/lib/inets/src/http_server/httpd_acceptor.erl
+++ b/lib/inets/src/http_server/httpd_acceptor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_acceptor_sup.erl b/lib/inets/src/http_server/httpd_acceptor_sup.erl
index 172498df8b..09d81a66d0 100644
--- a/lib/inets/src/http_server/httpd_acceptor_sup.erl
+++ b/lib/inets/src/http_server/httpd_acceptor_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_cgi.erl b/lib/inets/src/http_server/httpd_cgi.erl
index fb5feb5fbe..583c0be985 100644
--- a/lib/inets/src/http_server/httpd_cgi.erl
+++ b/lib/inets/src/http_server/httpd_cgi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index 132e1b5b7a..9e54f2b2c5 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -395,7 +395,8 @@ validate_properties(Properties) ->
%% That is, if property A depends on property B.
%% The only sunch preperty at this time is bind_address that depends
%% on ipfamily.
-validate_properties2(Properties) ->
+validate_properties2(Properties0) ->
+ Properties = fix_ipfamily(Properties0),
case proplists:get_value(bind_address, Properties) of
undefined ->
case proplists:get_value(sock_type, Properties, ip_comm) of
@@ -422,6 +423,15 @@ validate_properties2(Properties) ->
end
end.
+fix_ipfamily(Properties) ->
+ case proplists:get_value(ipfamily, Properties) of
+ undefined ->
+ Properties;
+ IpFamily ->
+ NewProps = proplists:delete(ipfamily, Properties),
+ [{ipfamily, validate_ipfamily(IpFamily)} | NewProps]
+ end.
+
add_inet_defaults(Properties) ->
case proplists:get_value(ipfamily, Properties) of
undefined ->
diff --git a/lib/inets/src/http_server/httpd_connection_sup.erl b/lib/inets/src/http_server/httpd_connection_sup.erl
index 939aa5366b..f7b3bef245 100644
--- a/lib/inets/src/http_server/httpd_connection_sup.erl
+++ b/lib/inets/src/http_server/httpd_connection_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_esi.erl b/lib/inets/src/http_server/httpd_esi.erl
index a925fac217..f5493f6fad 100644
--- a/lib/inets/src/http_server/httpd_esi.erl
+++ b/lib/inets/src/http_server/httpd_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ handle_headers("") ->
{ok, [], 200};
handle_headers(Headers) ->
NewHeaders = string:tokens(Headers, ?CRLF),
- handle_headers(NewHeaders, [], 200).
+ handle_headers(NewHeaders, [], 200, true).
%%%========================================================================
%%% Internal functions
@@ -80,21 +80,17 @@ parse_headers([?CR, ?LF, ?CR, ?LF | Rest], Acc) ->
parse_headers([Char | Rest], Acc) ->
parse_headers(Rest, [Char | Acc]).
-handle_headers([], NewHeaders, StatusCode) ->
+handle_headers([], NewHeaders, StatusCode, _) ->
{ok, NewHeaders, StatusCode};
-handle_headers([Header | Headers], NewHeaders, StatusCode) ->
+handle_headers([Header | Headers], NewHeaders, StatusCode, NoESIStatus) ->
{FieldName, FieldValue} = httpd_response:split_header(Header, []),
case FieldName of
- "location" ->
- case http_request:is_absolut_uri(FieldValue) of
- true ->
- handle_headers(Headers,
- [{FieldName, FieldValue} | NewHeaders],
- 302);
- false ->
- {proceed, FieldValue}
- end;
+ "location" when NoESIStatus == true ->
+ handle_headers(Headers,
+ [{FieldName, FieldValue} | NewHeaders],
+ 302, NoESIStatus);
+
"status" ->
NewStatusCode =
case httpd_util:split(FieldValue," ",2) of
@@ -103,8 +99,9 @@ handle_headers([Header | Headers], NewHeaders, StatusCode) ->
_ ->
200
end,
- handle_headers(Headers, NewHeaders, NewStatusCode);
+ handle_headers(Headers, NewHeaders, NewStatusCode, false);
_ ->
handle_headers(Headers,
- [{FieldName, FieldValue}| NewHeaders], StatusCode)
- end.
+ [{FieldName, FieldValue}| NewHeaders], StatusCode,
+ NoESIStatus)
+ end.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index ad29b5b29a..47a8c48d01 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
%%
-module(httpd_example).
-export([print/1]).
--export([get/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2]).
+-export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2,new_status_and_location/2]).
--export([newformat/3]).
+-export([newformat/3, post_chunked/3]).
%% These are used by the inets test-suite
-export([delay/1, chunk_timeout/3]).
@@ -59,6 +59,11 @@ get(_Env,[]) ->
get(Env,Input) ->
default(Env,Input).
+put(Env,{Input,_Body}) ->
+ default(Env,Input);
+put(Env,Input) ->
+ default(Env,Input).
+
get_bin(_Env,_Input) ->
[list_to_binary(header()),
list_to_binary(top("GET Example")),
@@ -85,6 +90,9 @@ post(Env,Input) ->
yahoo(_Env,_Input) ->
"Location: http://www.yahoo.com\r\n\r\n".
+new_status_and_location(_Env,_Input) ->
+ "status:201 Created\r\n Location: http://www.yahoo.com\r\n\r\n".
+
default(Env,Input) ->
[header(),
top("Default Example"),
@@ -94,7 +102,7 @@ default(Env,Input) ->
io_lib:format("~p",[httpd:parse_query(Input)]),"\n",
footer()].
-peer(Env, Input) ->
+peer(Env, _Input) ->
Header =
case proplists:get_value(peer_cert, Env) of
undefined ->
@@ -126,15 +134,31 @@ footer() ->
"</BODY>
</HTML>\n".
-
-newformat(SessionID, _Env, _Input)->
+post_chunked(_SessionID, _Env, {first, _Body} = _Bodychunk) ->
+ {continue, {state, 1}};
+post_chunked(_SessionID, _Env, {continue, _Body, {state, N}} = _Bodychunk) ->
+ {continue, {state, N+1}};
+post_chunked(SessionID, _Env, {last, _Body, {state, N}} = _Bodychunk) ->
+ mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Received chunked body")),
+ mod_esi:deliver(SessionID, "Received" ++ integer_to_list(N) ++ "chunks"),
+ mod_esi:deliver(SessionID, footer());
+post_chunked(SessionID, _Env, {last, _Body, undefined} = _Bodychunk) ->
+ mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Received chunked body")),
+ mod_esi:deliver(SessionID, "Received 1 chunk"),
+ mod_esi:deliver(SessionID, footer());
+post_chunked(_, _, _Body) ->
+ exit(body_not_chunked).
+
+newformat(SessionID,_,_) ->
mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("new esi format test")),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, footer()).
-
+
%% ------------------------------------------------------
delay(Time) when is_integer(Time) ->
@@ -161,7 +185,7 @@ sleep(T) -> receive after T -> ok end.
%% ------------------------------------------------------
-chunk_timeout(SessionID, _, StrInt) ->
+chunk_timeout(SessionID, _, _StrInt) ->
mod_esi:deliver(SessionID, "Tranfer-Encoding:chunked/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("Test chunk encoding timeout")),
timer:sleep(20000),
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 5ada71ad76..4d419172d0 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_instance_sup.erl b/lib/inets/src/http_server/httpd_instance_sup.erl
index 079cc464ba..b77aa174ca 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-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_internal.hrl b/lib/inets/src/http_server/httpd_internal.hrl
index 79b53668ad..09d720ee85 100644
--- a/lib/inets/src/http_server/httpd_internal.hrl
+++ b/lib/inets/src/http_server/httpd_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_log.erl b/lib/inets/src/http_server/httpd_log.erl
index 0bad759774..56a08cd502 100644
--- a/lib/inets/src/http_server/httpd_log.erl
+++ b/lib/inets/src/http_server/httpd_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index 763ddae524..7cb39937e8 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_misc_sup.erl b/lib/inets/src/http_server/httpd_misc_sup.erl
index 114a3c746f..cac9315c27 100644
--- a/lib/inets/src/http_server/httpd_misc_sup.erl
+++ b/lib/inets/src/http_server/httpd_misc_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 749f58c197..007d272323 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -36,7 +36,7 @@
%% little at a time on a socket.
-export([
parse_method/1, parse_uri/1, parse_version/1, parse_headers/1,
- whole_body/1
+ whole_body/1, body_chunk_first/3, body_chunk/3, add_chunk/1
]).
@@ -76,13 +76,12 @@ body_data(Headers, Body) ->
ContentLength = list_to_integer(Headers#http_request_h.'content-length'),
case size(Body) - ContentLength of
0 ->
- {binary_to_list(Body), <<>>};
+ {Body, <<>>};
_ ->
<<BodyThisReq:ContentLength/binary, Next/binary>> = Body,
- {binary_to_list(BodyThisReq), Next}
+ {BodyThisReq, Next}
end.
-
%%-------------------------------------------------------------------------
%% validate(Method, Uri, Version) -> ok | {error, {bad_request, Reason} |
%% {error, {not_supported, {Method, Uri, Version}}
@@ -292,10 +291,46 @@ parse_headers(<<Octet, Rest/binary>>, Header, Headers, Current,
parse_headers(Rest, [Octet | Header], Headers, Current + 1, Max,
Options, Result).
+body_chunk_first(Body, 0 = Length, _) ->
+ whole_body(Body, Length);
+body_chunk_first(Body, Length, MaxChunk) ->
+ case body_chunk(Body, Length, MaxChunk) of
+ {ok, {last, NewBody}} ->
+ {ok, NewBody};
+ Other ->
+ Other
+ end.
+%% Used to chunk non chunk decoded post/put data
+add_chunk([<<>>, Body, Length, MaxChunk]) ->
+ body_chunk(Body, Length, MaxChunk);
+add_chunk([More, Body, Length, MaxChunk]) ->
+ body_chunk(<<Body/binary, More/binary>>, Length, MaxChunk).
+
+body_chunk(Body, Length, nolimit) ->
+ whole_body(Body, Length);
+body_chunk(<<>> = Body, Length, MaxChunk) ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}};
+
+body_chunk(Body, Length, MaxChunk) when Length > MaxChunk ->
+ case size(Body) >= MaxChunk of
+ true ->
+ <<Chunk:MaxChunk/binary, Rest/binary>> = Body,
+ {ok, {{continue, Chunk}, ?MODULE, add_chunk, [Rest, Length - MaxChunk, MaxChunk]}};
+ false ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
+ end;
+body_chunk(Body, Length, MaxChunk) ->
+ case size(Body) of
+ Length ->
+ {ok, {last, Body}};
+ _ ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
+ end.
+
whole_body(Body, Length) ->
case size(Body) of
N when N < Length, Length > 0 ->
- {?MODULE, whole_body, [Body, Length]};
+ {?MODULE, add_chunk, [Body, Length, nolimit]};
N when N >= Length, Length >= 0 ->
%% When a client uses pipelining trailing data
%% may be part of the next request!
@@ -443,6 +478,3 @@ check_header({"content-length", Value}, Maxsizes) ->
end;
check_header(_, _) ->
ok.
-
-
-
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 01686b2596..d918f10424 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-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,18 +37,20 @@
-include("httpd_internal.hrl").
-define(HANDSHAKE_TIMEOUT, 5000).
+
-record(state, {mod, %% #mod{}
manager, %% pid()
status, %% accept | busy | blocked
mfa, %% {Module, Function, Args}
max_keep_alive_request = infinity, %% integer() | infinity
- response_sent = false, %% true | false
- timeout, %% infinity | integer() > 0
- timer, %% ref() - Request timer
- headers, %% #http_request_h{}
+ response_sent = false :: boolean(),
+ timeout, %% infinity | integer() > 0
+ timer :: 'undefined' | reference(), % Request timer
+ headers, %% #http_request_h{}
body, %% binary()
data, %% The total data received in bits, checked after 10s
- byte_limit %% Bit limit per second before kick out
+ byte_limit, %% Bit limit per second before kick out
+ chunk
}).
%%====================================================================
@@ -123,7 +125,8 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
NrOfRequest = max_keep_alive_request(ConfigDB),
MaxContentLen = max_content_length(ConfigDB),
Customize = customize(ConfigDB),
-
+ MaxChunk = max_client_body_chunk(ConfigDB),
+
{_, Status} = httpd_manager:new_connection(Manager),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
@@ -138,7 +141,8 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
status = Status,
timeout = TimeOut,
max_keep_alive_request = NrOfRequest,
- mfa = MFA},
+ mfa = MFA,
+ chunk = chunk_start(MaxChunk)},
http_transport:setopts(SocketType, Socket,
[binary, {packet, 0}, {active, once}]),
@@ -193,6 +197,7 @@ handle_cast(Msg, #state{mod = ModData} = State) ->
%%--------------------------------------------------------------------
handle_info({Proto, Socket, Data},
#state{mfa = {Module, Function, Args},
+ chunk = {ChunkState, _},
mod = #mod{socket_type = SockType,
socket = Socket} = ModData} = State)
when (((Proto =:= tcp) orelse
@@ -206,7 +211,8 @@ handle_info({Proto, Socket, Data},
_ ->
State#state.data + byte_size(Data)
end,
- case PROCESSED of
+
+ case PROCESSED of
{ok, Result} ->
NewState = case NewDataSize of
undefined ->
@@ -214,7 +220,7 @@ handle_info({Proto, Socket, Data},
_ ->
set_new_data_size(cancel_request_timeout(State), NewDataSize)
end,
- handle_http_msg(Result, NewState);
+ handle_msg(Result, NewState);
{error, {size_error, MaxSize, ErrCode, ErrStr}, Version} ->
NewModData = ModData#mod{http_version = Version},
httpd_response:send_status(NewModData, ErrCode, ErrStr),
@@ -223,7 +229,10 @@ handle_info({Proto, Socket, Data},
error_log(Reason, NewModData),
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
-
+
+ {http_chunk = Module, Function, Args} when ChunkState =/= undefined ->
+ NewState = handle_chunk(Module, Function, Args, State),
+ {noreply, NewState};
NewMFA ->
http_transport:setopts(SockType, Socket, [{active, once}]),
case NewDataSize of
@@ -348,6 +357,34 @@ await_socket_ownership_transfer(AcceptTimeout) ->
exit(accept_socket_timeout)
end.
+
+%%% Internal chunking of client body
+handle_msg({{continue, Chunk}, Module, Function, Args}, #state{chunk = {_, CbState}} = State) ->
+ handle_internal_chunk(State#state{chunk = {continue, CbState},
+ body = Chunk}, Module, Function, Args);
+handle_msg({continue, Module, Function, Args}, #state{mod = ModData} = State) ->
+ http_transport:setopts(ModData#mod.socket_type,
+ ModData#mod.socket,
+ [{active, once}]),
+ {noreply, State#state{mfa = {Module, Function, Args}}};
+handle_msg({last, Body}, #state{headers = Headers, chunk = {_, CbState}} = State) ->
+ NewHeaders = Headers#http_request_h{'content-length' = integer_to_list(size(Body))},
+ handle_response(State#state{chunk = {last, CbState},
+ headers = NewHeaders,
+ body = Body});
+%%% Last data chunked by client
+handle_msg({ChunkedHeaders, Body}, #state{headers = Headers , chunk = {ChunkState, CbState}} = State) when ChunkState =/= undefined ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{chunk = {last, CbState},
+ headers = NewHeaders,
+ body = Body});
+handle_msg({ChunkedHeaders, Body}, #state{headers = Headers , chunk = {undefined, _}} = State) ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{headers = NewHeaders,
+ body = Body});
+handle_msg(Result, State) ->
+ handle_http_msg(Result, State).
+
handle_http_msg({_, _, Version, {_, _}, _},
#state{status = busy, mod = ModData} = State) ->
handle_manager_busy(State#state{mod =
@@ -404,10 +441,6 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}}
end;
-handle_http_msg({ChunkedHeaders, Body},
- State = #state{headers = Headers}) ->
- NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
- handle_response(State#state{headers = NewHeaders, body = Body});
handle_http_msg(Body, State) ->
handle_response(State#state{body = Body}).
@@ -442,22 +475,25 @@ handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) ->
end.
-handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
+handle_body(#state{headers = Headers, body = Body,
+ chunk = {ChunkState, CbState}, mod = #mod{config_db = ConfigDB} = ModData} = State,
MaxHeaderSize, MaxBodySize) ->
+ MaxChunk = max_client_body_chunk(ConfigDB),
case Headers#http_request_h.'transfer-encoding' of
"chunked" ->
try http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of
- {Module, Function, Args} ->
+ {Module, Function, Args} ->
http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
{noreply, State#state{mfa =
- {Module, Function, Args}}};
- {ok, {ChunkedHeaders, NewBody}} ->
- NewHeaders =
- http_chunk:handle_headers(Headers, ChunkedHeaders),
- handle_response(State#state{headers = NewHeaders,
- body = NewBody})
+ {Module, Function, Args},
+ chunk = chunk_start(MaxChunk)}};
+ {ok, {ChunkedHeaders, NewBody}} ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{headers = NewHeaders,
+ body = NewBody,
+ chunk = chunk_finish(ChunkState, CbState, MaxChunk)})
catch
throw:Error ->
httpd_response:send_status(ModData, 400,
@@ -475,21 +511,36 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
_ ->
- Length = list_to_integer(Headers#http_request_h.'content-length'),
+ Length = list_to_integer(Headers#http_request_h.'content-length'),
+ MaxChunk = max_client_body_chunk(ConfigDB),
case ((Length =< MaxBodySize) or (MaxBodySize == nolimit)) of
true ->
- case httpd_request:whole_body(Body, Length) of
- {Module, Function, Args} ->
- http_transport:setopts(ModData#mod.socket_type,
+ case httpd_request:body_chunk_first(Body, Length, MaxChunk) of
+ %% This is the case that the we need more data to complete
+ %% the body but chunking to the mod_esi user is not enabled.
+ {Module, add_chunk = Function, Args} ->
+ http_transport:setopts(ModData#mod.socket_type,
+ ModData#mod.socket,
+ [{active, once}]),
+ {noreply, State#state{mfa =
+ {Module, Function, Args}}};
+ %% Chunking to mod_esi user is enabled
+ {ok, {continue, Module, Function, Args}} ->
+ http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
{noreply, State#state{mfa =
{Module, Function, Args}}};
-
- {ok, NewBody} ->
- handle_response(
- State#state{headers = Headers,
- body = NewBody})
+ {ok, {{continue, Chunk}, Module, Function, Args}} ->
+ handle_internal_chunk(State#state{chunk = chunk_start(MaxChunk),
+ body = Chunk}, Module, Function, Args);
+ %% Whole body delivered, if chunking mechanism is enabled the whole
+ %% body fits in one chunk.
+ {ok, NewBody} ->
+ handle_response(State#state{chunk = chunk_finish(ChunkState,
+ CbState, MaxChunk),
+ headers = Headers,
+ body = NewBody})
end;
false ->
httpd_response:send_status(ModData, 413, "Body too long"),
@@ -549,15 +600,61 @@ expect(Headers, _, ConfigDB) ->
end
end.
+handle_chunk(http_chunk = Module, decode_data = Function,
+ [ChunkSize, TotalChunk, {MaxBodySize, BodySoFar, _AccLength, MaxHeaderSize}],
+ #state{chunk = {_, CbState},
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State) ->
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body =
+ {continue, BodySoFar, CbState}}),
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, [ChunkSize, TotalChunk, {MaxBodySize, <<>>, 0, MaxHeaderSize}]}};
+
+handle_chunk(http_chunk = Module, decode_size = Function,
+ [Data, HexList, _AccSize, {MaxBodySize, BodySoFar, _AccLength, MaxHeaderSize}],
+ #state{chunk = {_, CbState},
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State) ->
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body = {continue, BodySoFar, CbState}}),
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, [Data, HexList, 0, {MaxBodySize, <<>>, 0, MaxHeaderSize}]}};
+handle_chunk(Module, Function, Args, #state{mod = #mod{socket_type = SockType,
+ socket = Socket}} = State) ->
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{mfa = {Module, Function, Args}}.
+
+handle_internal_chunk(#state{chunk = {ChunkState, CbState}, body = Chunk,
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State, Module, Function, Args)->
+ Bodychunk = body_chunk(ChunkState, CbState, Chunk),
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body = Bodychunk}),
+ case Args of
+ [<<>> | _] ->
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ {noreply, State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, Args}}};
+ _ ->
+ handle_info({dummy, Socket, <<>>}, State#state{chunk = {continue, NewCbState},
+ mfa = {Module, Function, Args}})
+ end.
+
+handle_response(#state{body = Body,
+ headers = Headers,
+ mod = ModData,
+ chunk = {last, CbState},
+ max_keep_alive_request = Max} = State) when Max > 0 ->
+ {NewBody, Data} = httpd_request:body_data(Headers, Body),
+ ok = httpd_response:generate_and_send_response(
+ ModData#mod{entity_body = {last, NewBody, CbState}}),
+ handle_next_request(State#state{response_sent = true}, Data);
handle_response(#state{body = Body,
mod = ModData,
headers = Headers,
max_keep_alive_request = Max} = State) when Max > 0 ->
{NewBody, Data} = httpd_request:body_data(Headers, Body),
+ %% Backwards compatible, may cause memory explosion
ok = httpd_response:generate_and_send_response(
- ModData#mod{entity_body = NewBody}),
+ ModData#mod{entity_body = binary_to_list(NewBody)}),
handle_next_request(State#state{response_sent = true}, Data);
-
handle_response(#state{body = Body,
headers = Headers,
mod = ModData} = State) ->
@@ -577,6 +674,7 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
MaxURISize = max_uri_size(ModData#mod.config_db),
MaxContentLen = max_content_length(ModData#mod.config_db),
Customize = customize(ModData#mod.config_db),
+ MaxChunk = max_client_body_chunk(ModData#mod.config_db),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
{max_version, ?HTTP_MAX_VERSION_STRING},
@@ -589,6 +687,7 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
max_keep_alive_request = decrease(Max),
headers = undefined,
body = undefined,
+ chunk = chunk_start(MaxChunk),
response_sent = false},
NewState = activate_request_timeout(TmpState),
@@ -646,6 +745,9 @@ error_log(ReasonString, #mod{config_db = ConfigDB}) ->
max_header_size(ConfigDB) ->
httpd_util:lookup(ConfigDB, max_header_size, ?HTTP_MAX_HEADER_SIZE).
+max_client_body_chunk(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_client_body_chunk, nolimit).
+
max_uri_size(ConfigDB) ->
httpd_util:lookup(ConfigDB, max_uri_size, ?HTTP_MAX_URI_SIZE).
@@ -660,3 +762,17 @@ max_content_length(ConfigDB) ->
customize(ConfigDB) ->
httpd_util:lookup(ConfigDB, customize, httpd_custom).
+
+chunk_start(nolimit) ->
+ {undefined, undefined};
+chunk_start(_) ->
+ {first, undefined}.
+chunk_finish(_, _, nolimit) ->
+ {undefined, undefined};
+chunk_finish(_, CbState, _) ->
+ {last, CbState}.
+
+body_chunk(first, _, Chunk) ->
+ {first, Chunk};
+body_chunk(ChunkState, CbState, Chunk) ->
+ {ChunkState, Chunk, CbState}.
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index c0b5f09faf..6b9053fda6 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(httpd_response).
-export([generate_and_send_response/1, send_status/3, send_header/3,
send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3,
- split_header/2, is_disable_chunked_send/1, cache_headers/2]).
+ split_header/2, is_disable_chunked_send/1, cache_headers/2, handle_continuation/1]).
-export([map_status_code/2]).
-include_lib("inets/src/inets_app/inets_internal.hrl").
@@ -31,6 +31,9 @@
-define(VMODULE,"RESPONSE").
+handle_continuation(Mod) ->
+ generate_and_send_response(Mod).
+
%% If peername does not exist the client already discarded the
%% request so we do not need to send a reply.
generate_and_send_response(#mod{init_data =
@@ -39,6 +42,8 @@ generate_and_send_response(#mod{init_data =
generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
Modules = httpd_util:lookup(ConfigDB, modules, ?DEFAULT_MODS),
case traverse_modules(ModData, Modules) of
+ {continue, _} = Continue ->
+ Continue;
done ->
ok;
{proceed, Data} ->
@@ -69,17 +74,15 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
traverse_modules(ModData,[]) ->
{proceed,ModData#mod.data};
traverse_modules(ModData,[Module|Rest]) ->
- ?hdrd("traverse modules", [{callback_module, Module}]),
try apply(Module, do, [ModData]) of
+ {continue, _} = Continue ->
+ Continue;
done ->
- ?hdrt("traverse modules - done", []),
- done;
+ done;
{break, NewData} ->
- ?hdrt("traverse modules - break", [{new_data, NewData}]),
- {proceed, NewData};
+ {proceed, NewData};
{proceed, NewData} ->
- ?hdrt("traverse modules - proceed", [{new_data, NewData}]),
- traverse_modules(ModData#mod{data = NewData}, Rest)
+ traverse_modules(ModData#mod{data = NewData}, Rest)
catch
T:E ->
String =
@@ -104,15 +107,10 @@ send_status(#mod{socket_type = SocketType,
socket = Socket,
config_db = ConfigDB} = ModData, StatusCode, PhraseArgs) ->
- ?hdrd("send status", [{status_code, StatusCode},
- {phrase_args, PhraseArgs}]),
-
ReasonPhrase = httpd_util:reason_phrase(StatusCode),
Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
Body = get_body(ReasonPhrase, Message),
- ?hdrt("send status - header", [{reason_phrase, ReasonPhrase},
- {message, Message}]),
send_header(ModData, StatusCode,
[{content_type, "text/html"},
{content_length, integer_to_list(length(Body))}]),
@@ -390,8 +388,7 @@ send_response_old(#mod{socket_type = Type,
send_header(ModData, StatusCode, [{content_length,
content_length(NewResponse)}]),
httpd_socket:deliver(Type, Sock, NewResponse);
-
- {error, _Reason} ->
+ _ ->
send_status(ModData, 500, "Internal Server Error")
end.
diff --git a/lib/inets/src/http_server/httpd_script_env.erl b/lib/inets/src/http_server/httpd_script_env.erl
index 1c5d828b46..d7c92c59ef 100644
--- a/lib/inets/src/http_server/httpd_script_env.erl
+++ b/lib/inets/src/http_server/httpd_script_env.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,9 +74,13 @@ which_peercert(#mod{socket_type = {Type, _}, socket = Socket}) when Type == essl
which_peercert(_) -> %% Not an ssl connection
undefined.
+
which_resolve(#mod{init_data = #init_data{resolve = Resolve}}) ->
Resolve.
+which_name(#mod{config_db = ConfigDB}) ->
+ httpd_util:lookup(ConfigDB, server_name).
+
which_method(#mod{method = Method}) ->
Method.
@@ -85,7 +89,8 @@ which_request_uri(#mod{request_uri = RUri}) ->
create_basic_elements(esi, ModData) ->
[{server_software, which_server(ModData)},
- {server_name, which_resolve(ModData)},
+ {server_name, which_name(ModData)},
+ {host_name, which_resolve(ModData)},
{gateway_interface, ?GATEWAY_INTERFACE},
{server_protocol, ?SERVER_PROTOCOL},
{server_port, which_port(ModData)},
@@ -96,7 +101,8 @@ create_basic_elements(esi, ModData) ->
create_basic_elements(cgi, ModData) ->
[{"SERVER_SOFTWARE", which_server(ModData)},
- {"SERVER_NAME", which_resolve(ModData)},
+ {"SERVER_NAME", which_name(ModData)},
+ {"HOST_NAME", which_resolve(ModData)},
{"GATEWAY_INTERFACE", ?GATEWAY_INTERFACE},
{"SERVER_PROTOCOL", ?SERVER_PROTOCOL},
{"SERVER_PORT", integer_to_list(which_port(ModData))},
@@ -160,9 +166,9 @@ create_script_elements(cgi, path_info, PathInfo, ModData) ->
[{"PATH_INFO", PathInfo},
{"PATH_TRANSLATED", PathTranslated}];
create_script_elements(esi, entity_body, Body, _) ->
- [{content_length, httpd_util:flatlength(Body)}];
+ [{content_length, integer_to_list(httpd_util:flatlength(Body))}];
create_script_elements(cgi, entity_body, Body, _) ->
- [{"CONTENT_LENGTH", httpd_util:flatlength(Body)}];
+ [{"CONTENT_LENGTH", integer_to_list(httpd_util:flatlength(Body))}];
create_script_elements(_, _, _, _) ->
[].
diff --git a/lib/inets/src/http_server/httpd_socket.erl b/lib/inets/src/http_server/httpd_socket.erl
index b7b232a686..aa67c13621 100644
--- a/lib/inets/src/http_server/httpd_socket.erl
+++ b/lib/inets/src/http_server/httpd_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index bf40cedd5c..d1216e01b0 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 6dd6db6a0c..4a2eff4770 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -333,7 +333,9 @@ rfc1123_date(LocalTime) ->
{{YYYY,MM,DD},{Hour,Min,Sec}} =
case calendar:local_time_to_universal_time_dst(LocalTime) of
[Gmt] -> Gmt;
- [_,Gmt] -> Gmt
+ [_,Gmt] -> Gmt;
+ % Should not happen, but handle the empty list to prevent an error.
+ [] -> LocalTime
end,
DayNumber = calendar:day_of_the_week({YYYY,MM,DD}),
lists:flatten(
diff --git a/lib/inets/src/http_server/mod_actions.erl b/lib/inets/src/http_server/mod_actions.erl
index 154fde294e..b5449f20ee 100644
--- a/lib/inets/src/http_server/mod_actions.erl
+++ b/lib/inets/src/http_server/mod_actions.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 727f6e0ce3..0333076546 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth.erl b/lib/inets/src/http_server/mod_auth.erl
index b03629cabe..fba94df176 100644
--- a/lib/inets/src/http_server/mod_auth.erl
+++ b/lib/inets/src/http_server/mod_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth.hrl b/lib/inets/src/http_server/mod_auth.hrl
index 88554a64ed..dd7794c78c 100644
--- a/lib/inets/src/http_server/mod_auth.hrl
+++ b/lib/inets/src/http_server/mod_auth.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth_dets.erl b/lib/inets/src/http_server/mod_auth_dets.erl
index 95a2cdd669..9f95b2ca2d 100644
--- a/lib/inets/src/http_server/mod_auth_dets.erl
+++ b/lib/inets/src/http_server/mod_auth_dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth_mnesia.erl b/lib/inets/src/http_server/mod_auth_mnesia.erl
index 994f25a462..62acc554d4 100644
--- a/lib/inets/src/http_server/mod_auth_mnesia.erl
+++ b/lib/inets/src/http_server/mod_auth_mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth_plain.erl b/lib/inets/src/http_server/mod_auth_plain.erl
index 1a3120e03c..f2b0dfd71f 100644
--- a/lib/inets/src/http_server/mod_auth_plain.erl
+++ b/lib/inets/src/http_server/mod_auth_plain.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl
index 7d1e1a3431..90d9ee34b1 100644
--- a/lib/inets/src/http_server/mod_auth_server.erl
+++ b/lib/inets/src/http_server/mod_auth_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -128,7 +128,7 @@ list_group_members(Addr, Port, Dir, Group, Password) ->
list_group_members(Addr, Port, ?DEFAULT_PROFILE, Dir, Group, Password).
list_group_members(Addr, Port, Profile, Dir, Group, Password) ->
Name = make_name(Addr, Port, Profile),
- Req = {list_group_members, Addr, Port, Dir, Group, Password},
+ Req = {list_group_members, Addr, Port, Profile, Dir, Group, Password},
call(Name, Req).
delete_group(Addr, Port, Dir, GroupName, Password) ->
diff --git a/lib/inets/src/http_server/mod_browser.erl b/lib/inets/src/http_server/mod_browser.erl
index e3c41793ae..1e8f860746 100644
--- a/lib/inets/src/http_server/mod_browser.erl
+++ b/lib/inets/src/http_server/mod_browser.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_cgi.erl b/lib/inets/src/http_server/mod_cgi.erl
index ec8b9be32e..1454332895 100644
--- a/lib/inets/src/http_server/mod_cgi.erl
+++ b/lib/inets/src/http_server/mod_cgi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_dir.erl b/lib/inets/src/http_server/mod_dir.erl
index 2d8f27af3c..ba93d0b271 100644
--- a/lib/inets/src/http_server/mod_dir.erl
+++ b/lib/inets/src/http_server/mod_dir.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_disk_log.erl b/lib/inets/src/http_server/mod_disk_log.erl
index 5e395a2118..2023546f01 100644
--- a/lib/inets/src/http_server/mod_disk_log.erl
+++ b/lib/inets/src/http_server/mod_disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -363,17 +363,21 @@ create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList) ->
%%----------------------------------------------------------------------
open(Filename, MaxBytes, MaxFiles, internal) ->
- Opts = [{format, internal}, {repair, truncate}],
- open1(Filename, MaxBytes, MaxFiles, Opts);
+ Opt0 = {format, internal},
+ Opts1 = [Opt0, {repair, true}],
+ Opts2 = [Opt0, {repair, truncate}],
+ open1(Filename, MaxBytes, MaxFiles, Opts1, Opts2);
open(Filename, MaxBytes, MaxFiles, _) ->
Opts = [{format, external}],
- open1(Filename, MaxBytes, MaxFiles, Opts).
+ open1(Filename, MaxBytes, MaxFiles, Opts, Opts).
-open1(Filename, MaxBytes, MaxFiles, Opts0) ->
- Opts1 = [{name, Filename}, {file, Filename}, {type, wrap}] ++ Opts0,
- case open2(Opts1, {MaxBytes, MaxFiles}) of
+open1(Filename, MaxBytes, MaxFiles, Opts1, Opts2) ->
+ Opts0 = [{name, Filename}, {file, Filename}, {type, wrap}],
+ case open2(Opts0 ++ Opts1, Opts0 ++ Opts2, {MaxBytes, MaxFiles}) of
{ok, LogDB} ->
{ok, LogDB};
+ {repaired, LogDB, {recovered, _}, {badbytes, _}} ->
+ {ok, LogDB};
{error, Reason} ->
{error,
?NICE("Can't create " ++ Filename ++
@@ -382,11 +386,16 @@ open1(Filename, MaxBytes, MaxFiles, Opts0) ->
{error, ?NICE("Can't create "++Filename)}
end.
-open2(Opts, Size) ->
- case disk_log:open(Opts) of
+open2(Opts1, Opts2, Size) ->
+ case disk_log:open(Opts1) of
{error, {badarg, size}} ->
%% File did not exist, add the size option and try again
- disk_log:open([{size, Size} | Opts]);
+ disk_log:open([{size, Size} | Opts1]);
+ {error, {Reason, _}} when
+ Reason == not_a_log_file;
+ Reason == invalid_index_file ->
+ %% File was corrupt, add the truncate option and try again
+ disk_log:open([{size, Size} | Opts2]);
Else ->
Else
end.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 2978ac9095..3206d957d9 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-define(VMODULE,"ESI").
-define(DEFAULT_ERL_TIMEOUT,15000).
@@ -69,7 +68,6 @@ deliver(_SessionID, _Data) ->
%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
%%-------------------------------------------------------------------------
do(ModData) ->
- ?hdrt("do", []),
case proplists:get_value(status, ModData#mod.data) of
{_StatusCode, _PhraseArgs, _Reason} ->
{proceed, ModData#mod.data};
@@ -190,7 +188,6 @@ store({erl_script_nocache, Value}, _) ->
%%% Internal functions
%%%========================================================================
generate_response(ModData) ->
- ?hdrt("generate response", []),
case scheme(ModData#mod.request_uri, ModData#mod.config_db) of
{eval, ESIBody, Modules} ->
eval(ModData, ESIBody, Modules);
@@ -241,8 +238,7 @@ alias_match_str(Alias, eval_script_alias) ->
%%------------------------ Erl mechanism --------------------------------
erl(#mod{method = Method} = ModData, ESIBody, Modules)
- when (Method =:= "GET") orelse (Method =:= "HEAD") ->
- ?hdrt("erl", [{method, Method}]),
+ when (Method =:= "GET") orelse (Method =:= "HEAD") orelse (Method =:= "DELETE") ->
case httpd_util:split(ESIBody,":|%3A|/",2) of
{ok, [ModuleName, FuncAndInput]} ->
case httpd_util:split(FuncAndInput,"[\?/]",2) of
@@ -264,44 +260,46 @@ erl(#mod{method = Method} = ModData, ESIBody, Modules)
{proceed, [{status,{400, none, BadRequest}} | ModData#mod.data]}
end;
-erl(#mod{request_uri = ReqUri,
- method = "PUT",
- http_version = Version,
- data = Data}, _ESIBody, _Modules) ->
- ?hdrt("erl", [{method, put}]),
- {proceed, [{status,{501,{"PUT", ReqUri, Version},
- ?NICE("Erl mechanism doesn't support method PUT")}}|
- Data]};
+erl(#mod{method = "PUT", entity_body = Body} = ModData,
+ ESIBody, Modules) ->
+ case httpd_util:split(ESIBody,":|%3A|/",2) of
+ {ok, [ModuleName, FuncAndInput]} ->
+ case httpd_util:split(FuncAndInput,"[\?/]",2) of
+ {ok, [FunctionName, Input]} ->
+ generate_webpage(ModData, ESIBody, Modules,
+ list_to_atom(ModuleName),
+ FunctionName, {Input,Body},
+ script_elements(FuncAndInput, Input));
+ {ok, [FunctionName]} ->
+ generate_webpage(ModData, ESIBody, Modules,
+ list_to_atom(ModuleName),
+ FunctionName, {undefined,Body},
+ script_elements(FuncAndInput, ""));
+ {ok, BadRequest} ->
+ {proceed,[{status,{400,none, BadRequest}} |
+ ModData#mod.data]}
+ end;
+ {ok, BadRequest} ->
+ {proceed, [{status,{400, none, BadRequest}} | ModData#mod.data]}
+ end;
-erl(#mod{request_uri = ReqUri,
- method = "DELETE",
- http_version = Version,
- data = Data}, _ESIBody, _Modules) ->
- ?hdrt("erl", [{method, delete}]),
- {proceed,[{status,{501,{"DELETE", ReqUri, Version},
- ?NICE("Erl mechanism doesn't support method DELETE")}}|
- Data]};
+erl(#mod{method = "POST", entity_body = Body} = ModData, ESIBody, Modules) ->
+ case httpd_util:split(ESIBody,":|%3A|/",2) of
+ {ok,[ModuleName, Function]} ->
+ generate_webpage(ModData, ESIBody, Modules,
+ list_to_atom(ModuleName),
+ Function, Body, []);
+ {ok, BadRequest} ->
+ {proceed,[{status, {400, none, BadRequest}} | ModData#mod.data]}
+ end;
erl(#mod{request_uri = ReqUri,
method = "PATCH",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("erl", [{method, patch}]),
{proceed, [{status,{501,{"PATCH", ReqUri, Version},
?NICE("Erl mechanism doesn't support method PATCH")}}|
- Data]};
-
-erl(#mod{method = "POST",
- entity_body = Body} = ModData, ESIBody, Modules) ->
- ?hdrt("erl", [{method, post}]),
- case httpd_util:split(ESIBody,":|%3A|/",2) of
- {ok,[ModuleName, Function]} ->
- generate_webpage(ModData, ESIBody, Modules,
- list_to_atom(ModuleName),
- Function, Body, [{entity_body, Body}]);
- {ok, BadRequest} ->
- {proceed,[{status, {400, none, BadRequest}} | ModData#mod.data]}
- end.
+ Data]}.
generate_webpage(ModData, ESIBody, [all], Module, FunctionName,
Input, ScriptElements) ->
@@ -309,7 +307,6 @@ generate_webpage(ModData, ESIBody, [all], Module, FunctionName,
FunctionName, Input, ScriptElements);
generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
Input, ScriptElements) ->
- ?hdrt("generate webpage", []),
Function = list_to_atom(FunctionName),
case lists:member(Module, Modules) of
true ->
@@ -331,7 +328,6 @@ generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
%% Old API that waits for the dymnamic webpage to be totally generated
%% before anythig is sent back to the client.
erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
- ?hdrt("erl_scheme_webpage_whole", [{module, Mod}, {function, Func}]),
case (catch Mod:Func(Env, Input)) of
{'EXIT',{undef, _}} ->
{proceed, [{status, {404, ModData#mod.request_uri, "Not found"}}
@@ -343,33 +339,27 @@ erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
{Headers, Body} =
httpd_esi:parse_headers(lists:flatten(Response)),
Length = httpd_util:flatlength(Body),
- case httpd_esi:handle_headers(Headers) of
- {proceed, AbsPath} ->
- {proceed, [{real_name, httpd_util:split_path(AbsPath)}
- | ModData#mod.data]};
- {ok, NewHeaders, StatusCode} ->
- send_headers(ModData, StatusCode,
- [{"content-length",
- integer_to_list(Length)}| NewHeaders]),
- case ModData#mod.method of
- "HEAD" ->
- {proceed, [{response, {already_sent, 200, 0}} |
- ModData#mod.data]};
- _ ->
- httpd_response:send_body(ModData,
- StatusCode, Body),
- {proceed, [{response, {already_sent, 200,
- Length}} |
- ModData#mod.data]}
- end
- end
+ {ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
+ send_headers(ModData, StatusCode,
+ [{"content-length",
+ integer_to_list(Length)}| NewHeaders]),
+ case ModData#mod.method of
+ "HEAD" ->
+ {proceed, [{response, {already_sent, 200, 0}} |
+ ModData#mod.data]};
+ _ ->
+ httpd_response:send_body(ModData,
+ StatusCode, Body),
+ {proceed, [{response, {already_sent, 200,
+ Length}} |
+ ModData#mod.data]}
+ end
end.
%% New API that allows the dynamic wepage to be sent back to the client
%% in small chunks at the time during generation.
erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
process_flag(trap_exit, true),
- ?hdrt("erl_scheme_webpage_chunk", [{module, Mod}, {function, Func}]),
Self = self(),
%% Spawn worker that generates the webpage.
%% It would be nicer to use erlang:function_exported/3 but if the
@@ -380,7 +370,9 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
{'EXIT', {undef,_}} ->
%% Will force fallback on the old API
exit(erl_scheme_webpage_chunk_undefined);
- _ ->
+ {continue, _} = Continue ->
+ exit(Continue);
+ _ ->
ok
end
end),
@@ -394,38 +386,30 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid) ->
deliver_webpage_chunk(ModData, Pid, Timeout).
deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
- ?hdrt("deliver_webpage_chunk", [{timeout, Timeout}]),
case receive_headers(Timeout) of
{error, Reason} ->
%% Happens when webpage generator callback/3 is undefined
- ?hdrv("deliver_webpage_chunk - failed receiving headers",
- [{reason, Reason}]),
{error, Reason};
+ {continue, _} = Continue ->
+ Continue;
{Headers, Body} ->
- case httpd_esi:handle_headers(Headers) of
- {proceed, AbsPath} ->
- {proceed, [{real_name, httpd_util:split_path(AbsPath)}
- | ModData#mod.data]};
- {ok, NewHeaders, StatusCode} ->
- IsDisableChunkedSend =
- httpd_response:is_disable_chunked_send(Db),
- case (ModData#mod.http_version =/= "HTTP/1.1") or
- (IsDisableChunkedSend) of
- true ->
- send_headers(ModData, StatusCode,
- [{"connection", "close"} |
- NewHeaders]);
- false ->
- send_headers(ModData, StatusCode,
- [{"transfer-encoding",
- "chunked"} | NewHeaders])
- end,
- handle_body(Pid, ModData, Body, Timeout, length(Body),
- IsDisableChunkedSend)
- end;
- timeout ->
- ?hdrv("deliver_webpage_chunk - timeout", []),
- send_headers(ModData, 504, [{"connection", "close"}]),
+ {ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
+ IsDisableChunkedSend = httpd_response:is_disable_chunked_send(Db),
+ case (ModData#mod.http_version =/= "HTTP/1.1") or
+ (IsDisableChunkedSend) of
+ true ->
+ send_headers(ModData, StatusCode,
+ [{"connection", "close"} |
+ NewHeaders]);
+ false ->
+ send_headers(ModData, StatusCode,
+ [{"transfer-encoding",
+ "chunked"} | NewHeaders])
+ end,
+ handle_body(Pid, ModData, Body, Timeout, length(Body),
+ IsDisableChunkedSend);
+ timeout ->
+ send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
end.
@@ -433,16 +417,14 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
receive_headers(Timeout) ->
receive
{esi_data, Chunk} ->
- ?hdrt("receive_headers - received esi data (esi)", []),
httpd_esi:parse_headers(lists:flatten(Chunk));
{ok, Chunk} ->
- ?hdrt("receive_headers - received esi data (ok)", []),
httpd_esi:parse_headers(lists:flatten(Chunk));
{'EXIT', Pid, erl_scheme_webpage_chunk_undefined} when is_pid(Pid) ->
- ?hdrd("receive_headers - exit:chunk-undef", []),
{error, erl_scheme_webpage_chunk_undefined};
- {'EXIT', Pid, Reason} when is_pid(Pid) ->
- ?hdrv("receive_headers - exit", [{reason, Reason}]),
+ {'EXIT', Pid, {continue, _} = Continue} when is_pid(Pid) ->
+ Continue;
+ {'EXIT', Pid, Reason} when is_pid(Pid) ->
exit({mod_esi_linked_process_died, Pid, Reason})
after Timeout ->
timeout
@@ -457,7 +439,6 @@ handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
{proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]};
handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
- ?hdrt("handle_body - send chunk", [{timeout, Timeout}, {size, Size}]),
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
{esi_data, Data} when is_binary(Data) ->
@@ -537,7 +518,6 @@ eval(#mod{request_uri = ReqUri,
method = "PUT",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, put}]),
{proceed,[{status,{501,{"PUT", ReqUri, Version},
?NICE("Eval mechanism doesn't support method PUT")}}|
Data]};
@@ -546,7 +526,6 @@ eval(#mod{request_uri = ReqUri,
method = "DELETE",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, delete}]),
{proceed,[{status,{501,{"DELETE", ReqUri, Version},
?NICE("Eval mechanism doesn't support method DELETE")}}|
Data]};
@@ -555,14 +534,12 @@ eval(#mod{request_uri = ReqUri,
method = "POST",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, post}]),
{proceed,[{status,{501,{"POST", ReqUri, Version},
?NICE("Eval mechanism doesn't support method POST")}}|
Data]};
eval(#mod{method = Method} = ModData, ESIBody, Modules)
when (Method =:= "GET") orelse (Method =:= "HEAD") ->
- ?hdrt("eval", [{method, Method}]),
case is_authorized(ESIBody, Modules) of
true ->
case generate_webpage(ESIBody) of
@@ -572,15 +549,10 @@ eval(#mod{method = Method} = ModData, ESIBody, Modules)
{ok, Response} ->
{Headers, _} =
httpd_esi:parse_headers(lists:flatten(Response)),
- case httpd_esi:handle_headers(Headers) of
- {ok, _, StatusCode} ->
- {proceed,[{response, {StatusCode, Response}} |
- ModData#mod.data]};
- {proceed, AbsPath} ->
- {proceed, [{real_name, AbsPath} |
- ModData#mod.data]}
- end
- end;
+ {ok, _, StatusCode} =httpd_esi:handle_headers(Headers),
+ {proceed,[{response, {StatusCode, Response}} |
+ ModData#mod.data]}
+ end;
false ->
{proceed,[{status,
{403, ModData#mod.request_uri,
diff --git a/lib/inets/src/http_server/mod_get.erl b/lib/inets/src/http_server/mod_get.erl
index e8b3896f89..58600f5e3e 100644
--- a/lib/inets/src/http_server/mod_get.erl
+++ b/lib/inets/src/http_server/mod_get.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_head.erl b/lib/inets/src/http_server/mod_head.erl
index 1b68c1c66b..25c11360eb 100644
--- a/lib/inets/src/http_server/mod_head.erl
+++ b/lib/inets/src/http_server/mod_head.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_htaccess.erl b/lib/inets/src/http_server/mod_htaccess.erl
index f229c96f2d..7b742bba24 100644
--- a/lib/inets/src/http_server/mod_htaccess.erl
+++ b/lib/inets/src/http_server/mod_htaccess.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -412,8 +412,8 @@ getAuthenticatingDataFromHeader(Info)->
case httpd_util:split(UnCodedString,":",2) of
{ok,[User,PassWord]}->
{user,User,PassWord};
- {error,Error}->
- {error,Error}
+ Other ->
+ {error, Other}
end
end;
BadCredentials ->
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
index 4161f7059c..ec570504be 100644
--- a/lib/inets/src/http_server/mod_log.erl
+++ b/lib/inets/src/http_server/mod_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -105,8 +105,8 @@ do(Info) ->
Code = proplists:get_value(code,Head,unknown),
transfer_log(Info, "-", AuthUser, Date, Code, Size),
{proceed, Info#mod.data};
- {_StatusCode, Response} ->
- transfer_log(Info,"-",AuthUser,Date,200,
+ {StatusCode, Response} ->
+ transfer_log(Info, "-", AuthUser, Date, StatusCode,
httpd_util:flatlength(Response)),
{proceed,Info#mod.data};
undefined ->
diff --git a/lib/inets/src/http_server/mod_range.erl b/lib/inets/src/http_server/mod_range.erl
index 66d66c2809..1c6c6d927d 100644
--- a/lib/inets/src/http_server/mod_range.erl
+++ b/lib/inets/src/http_server/mod_range.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl
index 9b410952f0..07129940a5 100644
--- a/lib/inets/src/http_server/mod_responsecontrol.erl
+++ b/lib/inets/src/http_server/mod_responsecontrol.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_security.erl b/lib/inets/src/http_server/mod_security.erl
index 1f936d598a..e7fc043217 100644
--- a/lib/inets/src/http_server/mod_security.erl
+++ b/lib/inets/src/http_server/mod_security.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl
index f9281b0fdc..4f52357af3 100644
--- a/lib/inets/src/http_server/mod_security_server.erl
+++ b/lib/inets/src/http_server/mod_security_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_trace.erl b/lib/inets/src/http_server/mod_trace.erl
index e1cb428264..f007426ae3 100644
--- a/lib/inets/src/http_server/mod_trace.erl
+++ b/lib/inets/src/http_server/mod_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 7f51676dc5..eb0098dbee 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2015. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -48,9 +48,7 @@ MODULES = \
inets_app \
inets_sup \
inets_trace \
- inets_lib \
- inets_time_compat \
- inets_regexp
+ inets_lib
INTERNAL_HRL_FILES = inets_internal.hrl
EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index c09139872f..eb4be932ac 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-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,8 +28,6 @@
inets_service,
inets_trace,
inets_lib,
- inets_time_compat,
- inets_regexp,
%% FTP
ftp,
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index f568efd488..fdf4cc6e07 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,13 +18,13 @@
%% %CopyrightEnd%
{"%VSN%",
[
- {<<"6.2.4">>, [{load_module, httpd_request_handler,
+ {<<"6.4.3">>, [{load_module, httpd_esi,
soft_purge, soft_purge, []}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
- {<<"6.2.4">>, [{load_module, httpd_request_handler,
+ {<<"6.4.3">>, [{load_module, httpd_esi,
soft_purge, soft_purge, []}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl
index 2a40f73889..2d380012d7 100644
--- a/lib/inets/src/inets_app/inets.erl
+++ b/lib/inets/src/inets_app/inets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk
index 2c85173c68..1228514661 100644
--- a/lib/inets/src/inets_app/inets.mk
+++ b/lib/inets/src/inets_app/inets.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+# Copyright Ericsson AB 2010-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets_app.erl b/lib/inets/src/inets_app/inets_app.erl
index 3e4718070c..da4e9ead25 100644
--- a/lib/inets/src/inets_app/inets_app.erl
+++ b/lib/inets/src/inets_app/inets_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets_internal.hrl b/lib/inets/src/inets_app/inets_internal.hrl
index cc794d27c0..079b415b56 100644
--- a/lib/inets/src/inets_app/inets_internal.hrl
+++ b/lib/inets/src/inets_app/inets_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets_lib.erl b/lib/inets/src/inets_app/inets_lib.erl
index 6e16f5ef6e..3fae376a9f 100644
--- a/lib/inets/src/inets_app/inets_lib.erl
+++ b/lib/inets/src/inets_app/inets_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
%% Help function, elapsed milliseconds since T0
millisec_passed({_,_,_} = T0 ) ->
%% OTP 17 and earlier
- timer:now_diff(inets_time_compat:timestamp(), T0) div 1000;
+ timer:now_diff(erlang:timestamp(), T0) div 1000;
millisec_passed(T0) ->
%% OTP 18
diff --git a/lib/inets/src/inets_app/inets_regexp.erl b/lib/inets/src/inets_app/inets_regexp.erl
deleted file mode 100644
index fc1608bc5a..0000000000
--- a/lib/inets/src/inets_app/inets_regexp.erl
+++ /dev/null
@@ -1,414 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(inets_regexp).
-
--export([parse/1, match/2, first_match/2, split/2, sub/3, gsub/3]).
-
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-
-%% parse(RegExp) -> {ok, RE} | {error, E}.
-%% Parse the regexp described in the string RegExp.
-
-parse(S) ->
- case (catch reg(S)) of
- {R, []} ->
- {ok, R};
- {_R, [C|_]} ->
- {error, {illegal, [C]}};
- {error, E} ->
- {error, E}
- end.
-
-
-%% Find the longest match of RegExp in String.
-
-match(S, RegExp) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok,RE} -> match(S, RE);
- {error,E} -> {error,E}
- end;
-match(S, RE) ->
- case match(RE, S, 1, 0, -1) of
- {Start,Len} when Len >= 0 ->
- {match, Start, Len};
- {_Start,_Len} ->
- nomatch
- end.
-
-%% Find the first match of RegExp in String.
-
-first_match(S, RegExp) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok, RE} ->
- first_match(S, RE);
- {error, E} ->
- {error, E}
- end;
-first_match(S, RE) ->
- case first_match(RE, S, 1) of
- {Start,Len} when Len >= 0 ->
- {match, Start,Len};
- nomatch ->
- nomatch
- end.
-
-first_match(RE, S, St) when S =/= [] ->
- case re_apply(S, St, RE) of
- {match, P, _Rest} ->
- {St, P-St};
- nomatch ->
- first_match(RE, tl(S), St+1)
- end;
-first_match(_RE, [], _St) ->
- nomatch.
-
-
-match(RE, S, St, Pos, L) ->
- case first_match(RE, S, St) of
- {St1, L1} ->
- Nst = St1 + 1,
- if L1 > L ->
- match(RE, lists:nthtail(Nst-St, S), Nst, St1, L1);
- true ->
- match(RE, lists:nthtail(Nst-St, S), Nst, Pos, L)
- end;
- nomatch ->
- {Pos, L}
- end.
-
-
-%% Split a string into substrings where the RegExp describes the
-%% field seperator. The RegExp " " is specially treated.
-
-split(String, " ") -> %This is really special
- {ok, RE} = parse("[ \t]+"),
- case split_apply(String, RE, true) of
- [[]|Ss] ->
- {ok,Ss};
- Ss ->
- {ok,Ss}
- end;
-split(String, RegExp) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok, RE} ->
- {ok, split_apply(String, RE, false)};
- {error, E} ->
- {error,E}
- end;
-split(String, RE) ->
- {ok, split_apply(String, RE, false)}.
-
-
-%% Substitute the first match of the regular expression RegExp
-%% with the string Replace in String. Accept pre-parsed regular
-%% expressions.
-
-sub(String, RegExp, Rep) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok, RE} ->
- sub(String, RE, Rep);
- {error, E} ->
- {error, E}
- end;
-sub(String, RE, Rep) ->
- Ss = sub_match(String, RE, 1),
- {ok, sub_repl(Ss, Rep, String, 1), length(Ss)}.
-
-
-%% Substitute every match of the regular expression RegExp with
-%% the string New in String. Accept pre-parsed regular expressions.
-
-gsub(String, RegExp, Rep) when is_list(RegExp) ->
- case parse(RegExp) of
- {ok, RE} ->
- gsub(String, RE, Rep);
- {error, E} ->
- {error, E}
- end;
-gsub(String, RE, Rep) ->
- Ss = matches(String, RE, 1),
- {ok, sub_repl(Ss, Rep, String, 1), length(Ss)}.
-
-
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
-
-%% This is the regular expression grammar used. It is equivalent to the
-%% one used in AWK, except that we allow ^ $ to be used anywhere and fail
-%% in the matching.
-%%
-%% reg -> reg1 : '$1'.
-%% reg1 -> reg1 "|" reg2 : {'or','$1','$2'}.
-%% reg1 -> reg2 : '$1'.
-%% reg2 -> reg2 reg3 : {concat,'$1','$2'}.
-%% reg2 -> reg3 : '$1'.
-%% reg3 -> reg3 "*" : {kclosure,'$1'}.
-%% reg3 -> reg3 "+" : {pclosure,'$1'}.
-%% reg3 -> reg3 "?" : {optional,'$1'}.
-%% reg3 -> reg4 : '$1'.
-%% reg4 -> "(" reg ")" : '$2'.
-%% reg4 -> "\\" char : '$2'.
-%% reg4 -> "^" : bos.
-%% reg4 -> "$" : eos.
-%% reg4 -> "." : char.
-%% reg4 -> "[" class "]" : {char_class,char_class('$2')}
-%% reg4 -> "[" "^" class "]" : {comp_class,char_class('$3')}
-%% reg4 -> "\"" chars "\"" : char_string('$2')
-%% reg4 -> char : '$1'.
-%% reg4 -> empty : epsilon.
-%% The grammar of the current regular expressions. The actual parser
-%% is a recursive descent implementation of the grammar.
-
-reg(S) -> reg1(S).
-
-%% reg1 -> reg2 reg1'
-%% reg1' -> "|" reg2
-%% reg1' -> empty
-
-reg1(S0) ->
- {L,S1} = reg2(S0),
- reg1p(S1, L).
-
-reg1p([$||S0], L) ->
- {R,S1} = reg2(S0),
- reg1p(S1, {'or',L,R});
-reg1p(S, L) -> {L,S}.
-
-%% reg2 -> reg3 reg2'
-%% reg2' -> reg3
-%% reg2' -> empty
-
-reg2(S0) ->
- {L,S1} = reg3(S0),
- reg2p(S1, L).
-
-reg2p([C|S0], L) when (C =/= $|) andalso (C =/= $)) ->
- {R,S1} = reg3([C|S0]),
- reg2p(S1, {concat,L,R});
-reg2p(S, L) -> {L,S}.
-
-%% reg3 -> reg4 reg3'
-%% reg3' -> "*" reg3'
-%% reg3' -> "+" reg3'
-%% reg3' -> "?" reg3'
-%% reg3' -> empty
-
-reg3(S0) ->
- {L,S1} = reg4(S0),
- reg3p(S1, L).
-
-reg3p([$*|S], L) -> reg3p(S, {kclosure,L});
-reg3p([$+|S], L) -> reg3p(S, {pclosure,L});
-reg3p([$?|S], L) -> reg3p(S, {optional,L});
-reg3p(S, L) -> {L,S}.
-
-reg4([$(|S0]) ->
- case reg(S0) of
- {R,[$)|S1]} -> {R,S1};
- {_R,_S} -> throw({error,{unterminated,"("}})
- end;
-reg4([$\\,O1,O2,O3|S])
- when ((O1 >= $0) andalso
- (O1 =< $7) andalso
- (O2 >= $0) andalso
- (O2 =< $7) andalso
- (O3 >= $0) andalso
- (O3 =< $7)) ->
- {(O1*8 + O2)*8 + O3 - 73*$0,S};
-reg4([$\\,C|S]) ->
- {escape_char(C),S};
-reg4([$\\]) ->
- throw({error, {unterminated,"\\"}});
-reg4([$^|S]) ->
- {bos,S};
-reg4([$$|S]) ->
- {eos,S};
-reg4([$.|S]) ->
- {{comp_class,"\n"},S};
-reg4("[^" ++ S0) ->
- case char_class(S0) of
- {Cc,[$]|S1]} -> {{comp_class,Cc},S1};
- {_Cc,_S} -> throw({error,{unterminated,"["}})
- end;
-reg4([$[|S0]) ->
- case char_class(S0) of
- {Cc,[$]|S1]} -> {{char_class,Cc},S1};
- {_Cc,_S1} -> throw({error,{unterminated,"["}})
- end;
-reg4([C|S])
- when (C =/= $*) andalso (C =/= $+) andalso (C =/= $?) andalso (C =/= $]) ->
- {C, S};
-reg4([C|_S]) ->
- throw({error,{illegal,[C]}});
-reg4([]) ->
- {epsilon,[]}.
-
-escape_char($n) -> $\n; %\n = LF
-escape_char($r) -> $\r; %\r = CR
-escape_char($t) -> $\t; %\t = TAB
-escape_char($v) -> $\v; %\v = VT
-escape_char($b) -> $\b; %\b = BS
-escape_char($f) -> $\f; %\f = FF
-escape_char($e) -> $\e; %\e = ESC
-escape_char($s) -> $\s; %\s = SPACE
-escape_char($d) -> $\d; %\d = DEL
-escape_char(C) -> C.
-
-char_class([$]|S]) -> char_class(S, [$]]);
-char_class(S) -> char_class(S, []).
-
-char($\\, [O1,O2,O3|S]) when
- O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- {(O1*8 + O2)*8 + O3 - 73*$0,S};
-char($\\, [C|S]) -> {escape_char(C),S};
-char(C, S) -> {C,S}.
-
-char_class([C1|S0], Cc) when C1 =/= $] ->
- case char(C1, S0) of
- {Cf,[$-,C2|S1]} when C2 =/= $] ->
- case char(C2, S1) of
- {Cl,S2} when Cf < Cl -> char_class(S2, [{Cf,Cl}|Cc]);
- {Cl,_S2} -> throw({error,{char_class,[Cf,$-,Cl]}})
- end;
- {C,S1} -> char_class(S1, [C|Cc])
- end;
-char_class(S, Cc) -> {Cc,S}.
-
-
-%% re_apply(String, StartPos, RegExp) -> re_app_res().
-%%
-%% Apply the (parse of the) regular expression RegExp to String. If
-%% there is a match return the position of the remaining string and
-%% the string if else return 'nomatch'. BestMatch specifies if we want
-%% the longest match, or just a match.
-%%
-%% StartPos should be the real start position as it is used to decide
-%% if we ae at the beginning of the string.
-%%
-%% Pass two functions to re_apply_or so it can decide, on the basis
-%% of BestMatch, whether to just any take any match or try both to
-%% find the longest. This is slower but saves duplicatng code.
-
-re_apply(S, St, RE) -> re_apply(RE, [], S, St).
-
-re_apply(epsilon, More, S, P) -> %This always matches
- re_apply_more(More, S, P);
-re_apply({'or',RE1,RE2}, More, S, P) ->
- re_apply_or(re_apply(RE1, More, S, P),
- re_apply(RE2, More, S, P));
-re_apply({concat,RE1,RE2}, More, S0, P) ->
- re_apply(RE1, [RE2|More], S0, P);
-re_apply({kclosure,CE}, More, S, P) ->
- %% Be careful with the recursion, explicitly do one call before
- %% looping.
- re_apply_or(re_apply_more(More, S, P),
- re_apply(CE, [{kclosure,CE}|More], S, P));
-re_apply({pclosure,CE}, More, S, P) ->
- re_apply(CE, [{kclosure,CE}|More], S, P);
-re_apply({optional,CE}, More, S, P) ->
- re_apply_or(re_apply_more(More, S, P),
- re_apply(CE, More, S, P));
-re_apply(bos, More, S, 1) -> re_apply_more(More, S, 1);
-re_apply(eos, More, [$\n|S], P) -> re_apply_more(More, S, P);
-re_apply(eos, More, [], P) -> re_apply_more(More, [], P);
-re_apply({char_class,Cc}, More, [C|S], P) ->
- case in_char_class(C, Cc) of
- true -> re_apply_more(More, S, P+1);
- false -> nomatch
- end;
-re_apply({comp_class,Cc}, More, [C|S], P) ->
- case in_char_class(C, Cc) of
- true -> nomatch;
- false -> re_apply_more(More, S, P+1)
- end;
-re_apply(C, More, [C|S], P) when is_integer(C) ->
- re_apply_more(More, S, P+1);
-re_apply(_RE, _More, _S, _P) -> nomatch.
-
-%% re_apply_more([RegExp], String, Length) -> re_app_res().
-
-re_apply_more([RE|More], S, P) -> re_apply(RE, More, S, P);
-re_apply_more([], S, P) -> {match,P,S}.
-
-%% in_char_class(Char, Class) -> bool().
-
-in_char_class(C, [{C1,C2}|_Cc]) when C >= C1, C =< C2 -> true;
-in_char_class(C, [C|_Cc]) -> true;
-in_char_class(C, [_|Cc]) -> in_char_class(C, Cc);
-in_char_class(_C, []) -> false.
-
-%% re_apply_or(Match1, Match2) -> re_app_res().
-%% If we want the best match then choose the longest match, else just
-%% choose one by trying sequentially.
-
-re_apply_or({match,P1,S1}, {match,P2,_S2}) when P1 >= P2 -> {match,P1,S1};
-re_apply_or({match,_P1,_S1}, {match,P2,S2}) -> {match,P2,S2};
-re_apply_or(nomatch, R2) -> R2;
-re_apply_or(R1, nomatch) -> R1.
-
-
-matches(S, RE, St) ->
- case first_match(RE, S, St) of
- {St1,0} ->
- [{St1,0}|matches(string:substr(S, St1+2-St), RE, St1+1)];
- {St1,L1} ->
- [{St1,L1}|matches(string:substr(S, St1+L1+1-St), RE, St1+L1)];
- nomatch ->
- []
- end.
-
-sub_match(S, RE, St) ->
- case first_match(RE, S, St) of
- {St1,L1} -> [{St1,L1}];
- nomatch -> []
- end.
-
-sub_repl([{St,L}|Ss], Rep, S, Pos) ->
- Rs = sub_repl(Ss, Rep, S, St+L),
- string:substr(S, Pos, St-Pos) ++
- sub_repl(Rep, string:substr(S, St, L), Rs);
-sub_repl([], _Rep, S, Pos) ->
- string:substr(S, Pos).
-
-sub_repl([$&|Rep], M, Rest) -> M ++ sub_repl(Rep, M, Rest);
-sub_repl("\\&" ++ Rep, M, Rest) -> [$&|sub_repl(Rep, M, Rest)];
-sub_repl([C|Rep], M, Rest) -> [C|sub_repl(Rep, M, Rest)];
-sub_repl([], _M, Rest) -> Rest.
-
-split_apply(S, RE, Trim) -> split_apply(S, 1, RE, Trim, []).
-
-split_apply([], _P, _RE, true, []) ->
- [];
-split_apply([], _P, _RE, _T, Sub) ->
- [lists:reverse(Sub)];
-split_apply(S, P, RE, T, Sub) ->
- case re_apply(S, P, RE) of
- {match,P,_Rest} ->
- split_apply(tl(S), P+1, RE, T, [hd(S)|Sub]);
- {match,P1,Rest} ->
- [lists:reverse(Sub)|split_apply(Rest, P1, RE, T, [])];
- nomatch ->
- split_apply(tl(S), P+1, RE, T, [hd(S)|Sub])
- end.
diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl
index 706915de92..3441d2a2e4 100644
--- a/lib/inets/src/inets_app/inets_service.erl
+++ b/lib/inets/src/inets_app/inets_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets_sup.erl b/lib/inets/src/inets_app/inets_sup.erl
index a48a8db190..d8ae7eff26 100644
--- a/lib/inets/src/inets_app/inets_sup.erl
+++ b/lib/inets/src/inets_app/inets_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/inets_app/inets_time_compat.erl b/lib/inets/src/inets_app/inets_time_compat.erl
deleted file mode 100644
index 475f0685dc..0000000000
--- a/lib/inets/src/inets_app/inets_time_compat.erl
+++ /dev/null
@@ -1,72 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%% This module is created to be able to execute on ERTS versions both
-%% earlier and later than 7.0.
-
--module(inets_time_compat).
-
-%% We don't want warnings about the use of erlang:now/0 in
-%% this module.
--compile(nowarn_deprecated_function).
-
--export([monotonic_time/0,
- timestamp/0,
- unique_integer/0,
- unique_integer/1]).
-
-monotonic_time() ->
- try
- erlang:monotonic_time()
- catch
- error:undef ->
- %% Use Erlang system time as monotonic time
- erlang_system_time_fallback()
- end.
-
-timestamp() ->
- try
- erlang:timestamp()
- catch
- error:undef ->
- erlang:now()
- end.
-
-unique_integer() ->
- try
- erlang:unique_integer()
- catch
- error:undef ->
- erlang_system_time_fallback()
- end.
-
-unique_integer(Modifiers) ->
- try
- erlang:unique_integer(Modifiers)
- catch
- error:badarg ->
- erlang:error(badarg, [Modifiers]);
- error:undef ->
- erlang_system_time_fallback()
- end.
-
-erlang_system_time_fallback() ->
- {MS, S, US} = erlang:now(),
- (MS*1000000+S)*1000000+US.
diff --git a/lib/inets/src/tftp/Makefile b/lib/inets/src/tftp/Makefile
index d5d94e1b78..4eaa959cce 100644
--- a/lib/inets/src/tftp/Makefile
+++ b/lib/inets/src/tftp/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl
index 45d7852863..c8804ea55f 100644
--- a/lib/inets/src/tftp/tftp.erl
+++ b/lib/inets/src/tftp/tftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp.hrl b/lib/inets/src/tftp/tftp.hrl
index 2cea18a7ea..25543e0b9e 100644
--- a/lib/inets/src/tftp/tftp.hrl
+++ b/lib/inets/src/tftp/tftp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp_binary.erl b/lib/inets/src/tftp/tftp_binary.erl
index 6981d741c6..09adcfc41f 100644
--- a/lib/inets/src/tftp/tftp_binary.erl
+++ b/lib/inets/src/tftp/tftp_binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl
index 493a29a68f..fb2c9749e5 100644
--- a/lib/inets/src/tftp/tftp_engine.erl
+++ b/lib/inets/src/tftp/tftp_engine.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,8 @@
-record(file_info, {peer_req, pid}).
-record(sys_misc, {module, function, arguments}).
-record(error, {where, code, text, filename}).
--record(prepared, {status :: prep_status(), result, block_no, next_data, prev_data}).
+-record(prepared, {status :: prep_status() | 'undefined',
+ result, block_no, next_data, prev_data}).
-record(transfer_res, {status, decoded_msg, prepared}).
-define(ERROR(Where, Code, Text, Filename),
#error{where = Where, code = Code, text = Text, filename = Filename}).
diff --git a/lib/inets/src/tftp/tftp_file.erl b/lib/inets/src/tftp/tftp_file.erl
index 39382d6fd0..7664324808 100644
--- a/lib/inets/src/tftp/tftp_file.erl
+++ b/lib/inets/src/tftp/tftp_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp_lib.erl b/lib/inets/src/tftp/tftp_lib.erl
index 01dea97d07..454754f0a3 100644
--- a/lib/inets/src/tftp/tftp_lib.erl
+++ b/lib/inets/src/tftp/tftp_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/tftp/tftp_logger.erl b/lib/inets/src/tftp/tftp_logger.erl
index 5e5d1d56c7..a869958484 100644
--- a/lib/inets/src/tftp/tftp_logger.erl
+++ b/lib/inets/src/tftp/tftp_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ info_msg(Format, Data) ->
%%-------------------------------------------------------------------
add_timestamp(Format, Data) ->
- Time = inets_time_compat:timestamp(),
+ Time = erlang:timestamp(),
{{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Time),
%% {"~p-~s-~sT~s:~s:~sZ,~6.6.0w tftp: " ++ Format ++ "\n",
%% [Y, t(Mo), t(D), t(H), t(Mi), t(S), MicroSecs | Data]}.
diff --git a/lib/inets/src/tftp/tftp_sup.erl b/lib/inets/src/tftp/tftp_sup.erl
index 98b92cc87c..40b67c499c 100644
--- a/lib/inets/src/tftp/tftp_sup.erl
+++ b/lib/inets/src/tftp/tftp_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ unique_name(Options) ->
{value, {_, Port}} when is_integer(Port), Port > 0 ->
{tftpd, Port};
_ ->
- {tftpd, inets_time_compat:unique_integer([positive])}
+ {tftpd, erlang:unique_integer([positive])}
end.
default_kill_after() ->
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 607ec7c182..ffc512050a 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2014. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,7 +42,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
INCLUDES = -I. \
- -I$(ERL_TOP)/lib/test_server/include/ \
-I$(ERL_TOP)/lib/inets/src/inets_app \
-I$(ERL_TOP)/lib/inets/src/http_lib \
-I$(ERL_TOP)/lib/inets/src/http_client \
@@ -152,7 +151,6 @@ MODULES = \
inets_test_lib \
erl_make_certs \
ftp_SUITE \
- ftp_suite_lib \
ftp_format_SUITE \
http_format_SUITE \
httpc_SUITE \
@@ -170,8 +168,6 @@ MODULES = \
httpd_test_lib \
inets_sup_SUITE \
inets_SUITE \
- inets_app_test \
- inets_appup_test \
tftp_test_lib \
tftp_SUITE \
uri_SUITE \
@@ -238,7 +234,6 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
# running the target "targets".
# ----------------------------------------------------
ERL_COMPILE_FLAGS += \
- -pa ../../../internal_tools/test_server/ebin \
$(INCLUDES) \
$(FTP_FLAGS) \
$(INETS_FLAGS)
diff --git a/lib/inets/test/erl_make_certs.erl b/lib/inets/test/erl_make_certs.erl
index f7666864ff..2db95825bc 100644
--- a/lib/inets/test/erl_make_certs.erl
+++ b/lib/inets/test/erl_make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/ftp_SUITE.erl b/lib/inets/test/ftp_SUITE.erl
index 12c8185187..3dfec01ba2 100644
--- a/lib/inets/test/ftp_SUITE.erl
+++ b/lib/inets/test/ftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,18 +42,25 @@
-define(BAD_USER, "baduser").
-define(BAD_DIR, "baddirectory").
-go() -> ct:run_test([{suite,"ftp_SUITE"}, {logdir,"LOG"}]).
-gos() -> ct:run_test([{suite,"ftp_SUITE"}, {group,ftps_passive}, {logdir,"LOG"}]).
+-record(progress, {
+ current = 0,
+ total
+ }).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,20}}].
+
all() ->
[
{group, ftp_passive},
{group, ftp_active},
{group, ftps_passive},
- {group, ftps_active}
+ {group, ftps_active},
+ error_ehost,
+ clean_shutdown
].
groups() ->
@@ -86,11 +93,20 @@ ftp_tests()->
append_chunk,
recv,
recv_3,
- recv_bin,
+ recv_bin,
+ recv_bin_twice,
recv_chunk,
+ recv_chunk_twice,
+ recv_chunk_three_times,
type,
quote,
- ip_v6_disabled
+ error_elogin,
+ progress_report_send,
+ progress_report_recv,
+ not_owner,
+ unexpected_call,
+ unexpected_cast,
+ unexpected_bang
].
%%--------------------------------------------------------------------
@@ -101,6 +117,7 @@ ftp_tests()->
%%% ftpservers list of servers to check if they are available
%%% The element is:
%%% {Name, % string(). The os command name
+%%% Path, % string(). The os PATH syntax, e.g "/bin:/usr/bin"
%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
%%% % The command to start the daemon with.
%%% ChkUp, % fun(start_result()) -> string(). Os command to check
@@ -116,12 +133,13 @@ ftp_tests()->
-define(default_ftp_servers,
[{"vsftpd",
- fun(__CONF__) ->
- DataDir = ?config(data_dir,__CONF__),
+ "/sbin:/usr/sbin:/usr/local/sbin",
+ fun(__CONF__, AbsName) ->
+ DataDir = proplists:get_value(data_dir,__CONF__),
ConfFile = filename:join(DataDir, "vsftpd.conf"),
- PrivDir = ?config(priv_dir,__CONF__),
+ PrivDir = proplists:get_value(priv_dir,__CONF__),
AnonRoot = PrivDir,
- Cmd = ["vsftpd "++filename:join(DataDir,"vsftpd.conf"),
+ Cmd = [AbsName ++" "++filename:join(DataDir,"vsftpd.conf"),
" -oftpd_banner=erlang_otp_testing",
" -oanon_root=\"",AnonRoot,"\"",
" -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
@@ -145,7 +163,7 @@ ftp_tests()->
fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
end,
fun(__CONF__) ->
- AnonRoot = ?config(priv_dir,__CONF__),
+ AnonRoot = proplists:get_value(priv_dir,__CONF__),
[{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
{id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
end,
@@ -161,9 +179,9 @@ init_per_suite(Config) ->
false ->
{skip, "No ftp server found"};
{ok,Data} ->
- TstDir = filename:join(?config(priv_dir,Config), "test"),
+ TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"),
file:make_dir(TstDir),
- make_cert_files(dsa, rsa, "server-", ?config(data_dir,Config)),
+ make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)),
start_ftpd([{test_dir,TstDir},
{ftpd_data,Data}
| Config])
@@ -176,47 +194,67 @@ end_per_suite(Config) ->
ok.
%%--------------------------------------------------------------------
-init_per_group(_Group, Config) -> Config.
-
-end_per_group(_Group, Config) -> Config.
+init_per_group(Group, Config) when Group == ftps_active,
+ Group == ftps_passive ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ Config
+ catch
+ _:_ ->
+ {skip, "Crypto did not start"}
+ end;
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, Config) ->
+ Config.
%%--------------------------------------------------------------------
-init_per_testcase(Case, Config0) ->
- Group = proplists:get_value(name,?config(tc_group_properties,Config0)),
- try ?MODULE:Case(doc) of
- Msg -> ct:comment(Msg)
- catch
- _:_-> ok
- end,
+init_per_testcase(Case, Config0) ->
+ Group = proplists:get_value(name, proplists:get_value(tc_group_properties,Config0)),
TLS = [{tls,[{reuse_sessions,true}]}],
ACTIVE = [{mode,active}],
PASSIVE = [{mode,passive}],
- ExtraOpts = [verbose],
+ CaseOpts = case Case of
+ progress_report_send -> [{progress, {?MODULE,progress,#progress{}}}];
+ progress_report_recv -> [{progress, {?MODULE,progress,#progress{}}}];
+ _ -> []
+ end,
+ ExtraOpts = [verbose | CaseOpts],
Config =
case Group of
- ftp_active -> ftp__open(Config0, ACTIVE ++ExtraOpts);
- ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ExtraOpts);
- ftp_passive -> ftp__open(Config0, PASSIVE ++ExtraOpts);
- ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ExtraOpts)
+ ftp_active -> ftp__open(Config0, ACTIVE ++ ExtraOpts);
+ ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ ExtraOpts);
+ ftp_passive -> ftp__open(Config0, PASSIVE ++ ExtraOpts);
+ ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ ExtraOpts);
+ undefined -> Config0
end,
case Case of
- user -> Config;
- bad_user -> Config;
+ user -> Config;
+ bad_user -> Config;
+ error_elogin -> Config;
+ error_ehost -> Config;
+ clean_shutdown -> Config;
_ ->
- Pid = ?config(ftp,Config),
+ Pid = proplists:get_value(ftp,Config),
ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
- ok = ftp:cd(Pid, ?config(priv_dir,Config)),
+ ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)),
Config
end.
end_per_testcase(user, _Config) -> ok;
end_per_testcase(bad_user, _Config) -> ok;
+end_per_testcase(error_elogin, _Config) -> ok;
+end_per_testcase(error_ehost, _Config) -> ok;
+end_per_testcase(clean_shutdown, _Config) -> ok;
end_per_testcase(_Case, Config) ->
- case ?config(tc_status,Config) of
+ case proplists:get_value(tc_status,Config) of
ok -> ok;
_ ->
- try ftp:latest_ctrl_response(?config(ftp,Config))
+ try ftp:latest_ctrl_response(proplists:get_value(ftp,Config))
of
{ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
catch
@@ -228,51 +266,57 @@ end_per_testcase(_Case, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-user(doc) -> ["Open an ftp connection to a host, and logon as anonymous ftp, then logoff"];
+user() -> [
+ {doc, "Open an ftp connection to a host, and logon as anonymous ftp,"
+ " then logoff"}].
user(Config) ->
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon
ok = ftp:close(Pid), % logoff
{error,eclosed} = ftp:pwd(Pid), % check logoff result
ok.
%%-------------------------------------------------------------------------
-bad_user(doc) -> ["Open an ftp connection to a host, and logon with bad user."];
+bad_user() ->
+ [{doc, "Open an ftp connection to a host, and logon with bad user."}].
bad_user(Config) ->
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS("")),
ok.
%%-------------------------------------------------------------------------
-pwd(doc) -> ["Test ftp:pwd/1 & ftp:lpwd/1"];
+pwd() ->
+ [{doc, "Test ftp:pwd/1 & ftp:lpwd/1"}].
pwd(Config0) ->
Config = set_state([reset], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{ok, PWD} = ftp:pwd(Pid),
{ok, PathLpwd} = ftp:lpwd(Pid),
PWD = id2ftp_result("", Config),
PathLpwd = id2ftp_result("", Config).
%%-------------------------------------------------------------------------
-cd(doc) -> ["Open an ftp connection, log on as anonymous ftp, and cd to a"
- "directory and to a non-existent directory."];
+cd() ->
+ ["Open an ftp connection, log on as anonymous ftp, and cd to a"
+ "directory and to a non-existent directory."].
cd(Config0) ->
Dir = "test",
Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:cd(Pid, id2ftp(Dir,Config)),
{ok, PWD} = ftp:pwd(Pid),
ExpectedPWD = id2ftp_result(Dir, Config),
PWD = ExpectedPWD,
- {error, epath} = ftp:cd(Pid, ?BAD_DIR).
+ {error, epath} = ftp:cd(Pid, ?BAD_DIR),
+ ok.
%%-------------------------------------------------------------------------
-lcd(doc) ->
- ["Test api function ftp:lcd/2"];
+lcd() ->
+ [{doc, "Test api function ftp:lcd/2"}].
lcd(Config0) ->
Dir = "test",
Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:lcd(Pid, id2ftp(Dir,Config)),
{ok, PWD} = ftp:lpwd(Pid),
ExpectedPWD = id2ftp_result(Dir, Config),
@@ -280,19 +324,20 @@ lcd(Config0) ->
{error, epath} = ftp:lcd(Pid, ?BAD_DIR).
%%-------------------------------------------------------------------------
-ls(doc) -> ["Open an ftp connection; ls the current directory, and the "
- "\"test\" directory. We assume that ls never fails, since "
- "it's output is meant to be read by humans. "];
+ls() ->
+ [{doc, "Open an ftp connection; ls the current directory, and the "
+ "\"test\" directory. We assume that ls never fails, since "
+ "it's output is meant to be read by humans. "}].
ls(Config0) ->
Config = set_state([reset,{mkdir,"test"}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{ok, _R1} = ftp:ls(Pid),
{ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
%% of files (including wildcards).
- case ?config(wildcard_support, Config) of
+ case proplists:get_value(wildcard_support, Config) of
true ->
{ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
_ ->
@@ -300,20 +345,21 @@ ls(Config0) ->
end.
%%-------------------------------------------------------------------------
-nlist(doc) -> ["Open an ftp connection; nlist the current directory, and the "
+nlist() ->
+ [{doc,"Open an ftp connection; nlist the current directory, and the "
"\"test\" directory. Nlist does not behave consistenly over "
"operating systems. On some it is an error to have an empty "
- "directory."];
+ "directory."}].
nlist(Config0) ->
Config = set_state([reset,{mkdir,"test"}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{ok, _R1} = ftp:nlist(Pid),
{ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
%% of files (including wildcards).
- case ?config(wildcard_support, Config) of
+ case proplists:get_value(wildcard_support, Config) of
true ->
{ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
_ ->
@@ -321,141 +367,176 @@ nlist(Config0) ->
end.
%%-------------------------------------------------------------------------
-rename(doc) -> ["Rename a file."];
+rename() ->
+ [{doc, "Rename a file."}].
rename(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
OldFile = "old.txt",
NewFile = "new.txt",
Config = set_state([reset,{mkfile,OldFile,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:rename(Pid,
id2ftp(OldFile,Config),
id2ftp(NewFile,Config)),
true = (chk_file(NewFile,Contents,Config)
- and chk_no_file([OldFile],Config)).
-
+ and chk_no_file([OldFile],Config)),
+ {error,epath} = ftp:rename(Pid,
+ id2ftp("non_existing_file",Config),
+ id2ftp(NewFile,Config)),
+ ok.
%%-------------------------------------------------------------------------
-send(doc) -> ["Transfer a file with ftp using send/2."];
+send() ->
+ [{doc, "Transfer a file with ftp using send/2."}].
send(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
SrcDir = "data",
File = "file.txt",
Config = set_state([reset,{mkfile,[SrcDir,File],Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
-chk_no_file([File],Config),
-chk_file([SrcDir,File],Contents,Config),
+ chk_no_file([File],Config),
+ chk_file([SrcDir,File],Contents,Config),
ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
ok = ftp:cd(Pid, id2ftp("",Config)),
ok = ftp:send(Pid, File),
+ chk_file(File, Contents, Config),
- chk_file(File, Contents, Config).
+ {error,epath} = ftp:send(Pid, "non_existing_file"),
+ ok.
%%-------------------------------------------------------------------------
-send_3(doc) -> ["Transfer a file with ftp using send/3."];
+send_3() ->
+ [{doc, "Transfer a file with ftp using send/3."}].
send_3(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
Dir = "incoming",
File = "file.txt",
RemoteFile = "remfile.txt",
Config = set_state([reset,{mkfile,File,Contents},{mkdir,Dir}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:cd(Pid, id2ftp(Dir,Config)),
ok = ftp:lcd(Pid, id2ftp("",Config)),
ok = ftp:send(Pid, File, RemoteFile),
+ chk_file([Dir,RemoteFile], Contents, Config),
- chk_file([Dir,RemoteFile], Contents, Config).
+ {error,epath} = ftp:send(Pid, "non_existing_file", RemoteFile),
+ ok.
%%-------------------------------------------------------------------------
-send_bin(doc) -> ["Send a binary."];
+send_bin() ->
+ [{doc, "Send a binary."}].
send_bin(Config0) ->
BinContents = <<"ftp_SUITE test ...">>,
File = "file.txt",
Config = set_state([reset], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{error, enotbinary} = ftp:send_bin(Pid, "some string", id2ftp(File,Config)),
ok = ftp:send_bin(Pid, BinContents, id2ftp(File,Config)),
- chk_file(File, BinContents, Config).
+ chk_file(File, BinContents, Config),
+ {error, efnamena} = ftp:send_bin(Pid, BinContents, "/nothere"),
+ ok.
%%-------------------------------------------------------------------------
-send_chunk(doc) -> ["Send a binary using chunks."];
+send_chunk() ->
+ [{doc, "Send a binary using chunks."}].
send_chunk(Config0) ->
- Contents = <<"ftp_SUITE test ...">>,
+ Contents1 = <<"1: ftp_SUITE test ...">>,
+ Contents2 = <<"2: ftp_SUITE test ...">>,
File = "file.txt",
Config = set_state([reset,{mkdir,"incoming"}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
+ {error, echunk} = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
{error, echunk} = ftp:cd(Pid, "incoming"),
{error, enotbinary} = ftp:send_chunk(Pid, "some string"),
- ok = ftp:send_chunk(Pid, Contents),
- ok = ftp:send_chunk(Pid, Contents),
+ ok = ftp:send_chunk(Pid, Contents1),
+ ok = ftp:send_chunk(Pid, Contents2),
ok = ftp:send_chunk_end(Pid),
- chk_file(File, <<Contents/binary,Contents/binary>>, Config).
+ chk_file(File, <<Contents1/binary,Contents2/binary>>, Config),
+
+ {error, echunk} = ftp:send_chunk(Pid, Contents1),
+ {error, echunk} = ftp:send_chunk_end(Pid),
+ {error, efnamena} = ftp:send_chunk_start(Pid, "/"),
+ ok.
%%-------------------------------------------------------------------------
-delete(doc) -> ["Delete a file."];
+delete() ->
+ [{doc, "Delete a file."}].
delete(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
File = "file.txt",
Config = set_state([reset,{mkfile,File,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:delete(Pid, id2ftp(File,Config)),
- chk_no_file([File], Config).
+ chk_no_file([File], Config),
+ {error,epath} = ftp:delete(Pid, id2ftp(File,Config)),
+ ok.
%%-------------------------------------------------------------------------
-mkdir(doc) -> ["Make a remote directory."];
+mkdir() ->
+ [{doc, "Make a remote directory."}].
mkdir(Config0) ->
NewDir = "new_dir",
Config = set_state([reset], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
- chk_dir([NewDir], Config).
+ chk_dir([NewDir], Config),
+ {error,epath} = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
+ ok.
%%-------------------------------------------------------------------------
-rmdir(doc) -> ["Remove a directory."];
+rmdir() ->
+ [{doc, "Remove a directory."}].
rmdir(Config0) ->
Dir = "dir",
Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:rmdir(Pid, id2ftp(Dir,Config)),
- chk_no_dir([Dir], Config).
+ chk_no_dir([Dir], Config),
+ {error,epath} = ftp:rmdir(Pid, id2ftp(Dir,Config)),
+ ok.
%%-------------------------------------------------------------------------
-append(doc) -> ["Append a local file twice to a remote file"];
+append() ->
+ [{doc, "Append a local file twice to a remote file"}].
append(Config0) ->
SrcFile = "f_src.txt",
DstFile = "f_dst.txt",
Contents = <<"ftp_SUITE test ...">>,
Config = set_state([reset,{mkfile,SrcFile,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
- chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
+ chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config),
+ {error,epath} = ftp:append(Pid, id2ftp("non_existing_file",Config), id2ftp(DstFile,Config)),
+ ok.
%%-------------------------------------------------------------------------
-append_bin(doc) -> ["Append a local file twice to a remote file using append_bin"];
+append_bin() ->
+ [{doc, "Append a local file twice to a remote file using append_bin"}].
append_bin(Config0) ->
DstFile = "f_dst.txt",
Contents = <<"ftp_SUITE test ...">>,
Config = set_state([reset], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
%%-------------------------------------------------------------------------
-append_chunk(doc) -> ["Append chunks."];
+append_chunk() ->
+ [{doc, "Append chunks."}].
append_chunk(Config0) ->
File = "f_dst.txt",
Contents = [<<"ER">>,<<"LE">>,<<"RL">>],
Config = set_state([reset], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:append_chunk_start(Pid, id2ftp(File,Config)),
{error, enotbinary} = ftp:append_chunk(Pid, binary_to_list(lists:nth(1,Contents))),
ok = ftp:append_chunk(Pid,lists:nth(1,Contents)),
@@ -465,74 +546,167 @@ append_chunk(Config0) ->
chk_file(File, <<"ERLERL">>, Config).
%%-------------------------------------------------------------------------
-recv(doc) -> ["Receive a file using recv/2"];
+recv() ->
+ [{doc, "Receive a file using recv/2"}].
recv(Config0) ->
- File = "f_dst.txt",
+ File1 = "f_dst1.txt",
+ File2 = "f_dst2.txt",
SrcDir = "a_dir",
- Contents = <<"ftp_SUITE test ...">>,
- Config = set_state([reset, {mkfile,[SrcDir,File],Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Contents1 = <<"1 ftp_SUITE test ...">>,
+ Contents2 = <<"2 ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,[SrcDir,File1],Contents1}, {mkfile,[SrcDir,File2],Contents2}], Config0),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:cd(Pid, id2ftp(SrcDir,Config)),
ok = ftp:lcd(Pid, id2ftp("",Config)),
- ok = ftp:recv(Pid, File),
- chk_file(File, Contents, Config).
+ ok = ftp:recv(Pid, File1),
+ chk_file(File1, Contents1, Config),
+ ok = ftp:recv(Pid, File2),
+ chk_file(File2, Contents2, Config),
+ {error,epath} = ftp:recv(Pid, "non_existing_file"),
+ ok.
%%-------------------------------------------------------------------------
-recv_3(doc) -> ["Receive a file using recv/3"];
+recv_3() ->
+ [{doc,"Receive a file using recv/3"}].
recv_3(Config0) ->
DstFile = "f_src.txt",
SrcFile = "f_dst.txt",
Contents = <<"ftp_SUITE test ...">>,
Config = set_state([reset, {mkfile,SrcFile,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:cd(Pid, id2ftp("",Config)),
ok = ftp:recv(Pid, SrcFile, id2abs(DstFile,Config)),
chk_file(DstFile, Contents, Config).
%%-------------------------------------------------------------------------
-recv_bin(doc) -> ["Receive a file as a binary."];
+recv_bin() ->
+ [{doc, "Receive a file as a binary."}].
recv_bin(Config0) ->
File = "f_dst.txt",
Contents = <<"ftp_SUITE test ...">>,
Config = set_state([reset, {mkfile,File,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{ok,Received} = ftp:recv_bin(Pid, id2ftp(File,Config)),
- find_diff(Received, Contents).
+ find_diff(Received, Contents),
+ {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
+ ok.
%%-------------------------------------------------------------------------
-recv_chunk(doc) -> ["Receive a file using chunk-wise."];
+recv_bin_twice() ->
+ [{doc, "Receive two files as a binaries."}].
+recv_bin_twice(Config0) ->
+ File1 = "f_dst1.txt",
+ File2 = "f_dst2.txt",
+ Contents1 = <<"1 ftp_SUITE test ...">>,
+ Contents2 = <<"2 ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
+ ct:log("First transfer",[]),
+ Pid = proplists:get_value(ftp, Config),
+ {ok,Received1} = ftp:recv_bin(Pid, id2ftp(File1,Config)),
+ find_diff(Received1, Contents1),
+ ct:log("Second transfer",[]),
+ {ok,Received2} = ftp:recv_bin(Pid, id2ftp(File2,Config)),
+ find_diff(Received2, Contents2),
+ ct:log("Transfers ready!",[]),
+ {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
+ ok.
+%%-------------------------------------------------------------------------
+recv_chunk() ->
+ [{doc, "Receive a file using chunk-wise."}].
recv_chunk(Config0) ->
File = "big_file.txt",
Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
Config = set_state([reset, {mkfile,File,Contents}], Config0),
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
{{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)),
{ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>),
find_diff(ReceivedContents, Contents).
-recv_chunk(Pid, Acc) -> recv_chunk(Pid, Acc, 0).
+recv_chunk_twice() ->
+ [{doc, "Receive two files using chunk-wise."}].
+recv_chunk_twice(Config0) ->
+ File1 = "big_file1.txt",
+ File2 = "big_file2.txt",
+ Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Contents2 = crypto:strong_rand_bytes(1200),
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
+ {ok, ReceivedContents1, _Ncunks1} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
+ {ok, ReceivedContents2, _Ncunks2} = recv_chunk(Pid, <<>>),
+ find_diff(ReceivedContents1, Contents1),
+ find_diff(ReceivedContents2, Contents2).
+
+recv_chunk_three_times() ->
+ [{doc, "Receive two files using chunk-wise."},
+ {timetrap,{seconds,120}}].
+recv_chunk_three_times(Config0) ->
+ File1 = "big_file1.txt",
+ File2 = "big_file2.txt",
+ File3 = "big_file3.txt",
+ Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Contents2 = crypto:strong_rand_bytes(1200),
+ Contents3 = list_to_binary( lists:duplicate(1000, lists:seq(255,0,-1)) ),
+
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}, {mkfile,File3,Contents3}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
+ {ok, ReceivedContents1, Nchunks1} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
+ {ok, ReceivedContents2, _Nchunks2} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
+ {ok, ReceivedContents3, _Nchunks3} = recv_chunk(Pid, <<>>, 10000, 0, Nchunks1),
+
+ find_diff(ReceivedContents1, Contents1),
+ find_diff(ReceivedContents2, Contents2),
+ find_diff(ReceivedContents3, Contents3).
+
+
+
+recv_chunk(Pid, Acc) ->
+ recv_chunk(Pid, Acc, 0, 0, undefined).
+
+
+
+%% ExpectNchunks :: integer() | undefined
+recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) when N+1 < ExpectNchunks ->
+ %% for all I in integer(), I < undefined
+ recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks);
+
+recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
+ %% N >= ExpectNchunks-1
+ timer:sleep(DelayMilliSec),
+ recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks).
+
-recv_chunk(Pid, Acc, N) ->
+recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
+ ct:log("Call ftp:recv_chunk",[]),
case ftp:recv_chunk(Pid) of
ok -> {ok, Acc, N};
- {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, N+1);
+ {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, DelayMilliSec, N+1, ExpectNchunks);
Error -> {Error, N}
end.
%%-------------------------------------------------------------------------
-type(doc) -> ["Test that we can change btween ASCCI and binary transfer mode"];
+type() ->
+ [{doc,"Test that we can change btween ASCCI and binary transfer mode"}].
type(Config) ->
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
ok = ftp:type(Pid, ascii),
ok = ftp:type(Pid, binary),
ok = ftp:type(Pid, ascii),
{error, etype} = ftp:type(Pid, foobar).
%%-------------------------------------------------------------------------
-quote(doc) -> [""];
quote(Config) ->
- Pid = ?config(ftp, Config),
+ Pid = proplists:get_value(ftp, Config),
["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
[_| _] = ftp:quote(Pid, "help"),
%% This negativ test causes some ftp servers to hang. This test
@@ -541,48 +715,154 @@ quote(Config) ->
%% = ftp:quote(Pid, "list"),
ok.
+%%-------------------------------------------------------------------------
+progress_report_send() ->
+ [{doc, "Test the option progress for ftp:send/[2,3]"}].
+progress_report_send(Config) when is_list(Config) ->
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
+ send(Config),
+ receive
+ {ReportPid, ok} ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+progress_report_recv() ->
+ [{doc, "Test the option progress for ftp:recv/[2,3]"}].
+progress_report_recv(Config) when is_list(Config) ->
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
+ recv(Config),
+ receive
+ {ReportPid, ok} ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+
+not_owner() ->
+ [{doc, "Test what happens if a process that not owns the connection tries "
+ "to use it"}].
+not_owner(Config) when is_list(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+
+ Parent = self(),
+ OtherPid = spawn_link(
+ fun() ->
+ {error, not_connection_owner} = ftp:pwd(Pid),
+ ftp:close(Pid),
+ Parent ! {self(), ok}
+ end),
+ receive
+ {OtherPid, ok} ->
+ {ok, _} = ftp:pwd(Pid)
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+unexpected_call()->
+ [{doc, "Test that behaviour of the ftp process if the api is abused"}].
+unexpected_call(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+
+ %% Serious programming fault, connetion will be shut down
+ case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
+ {error, {connection_terminated, 'API_violation'}} ->
+ ok;
+ Unexpected1 ->
+ exit({unexpected_result, Unexpected1})
+ end,
+ ct:sleep(500),
+ undefined = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
%%-------------------------------------------------------------------------
-ip_v6_disabled(doc) -> ["Test ipv4 command PORT"];
-ip_v6_disabled(_Config) ->
- %%% FIXME!!!! What is this???
- ok.%% send(Config).
+unexpected_cast()->
+ [{doc, "Test that behaviour of the ftp process if the api is abused"}].
+unexpected_cast(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+ %% Serious programming fault, connetion will be shut down
+ gen_server:cast(Pid, {self(), foobar, 10}),
+ ct:sleep(500),
+ undefined = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
%%-------------------------------------------------------------------------
-%% big_one(doc) ->
-%% ["Create a local file and transfer it to the remote host into the "
-%% "the \"incoming\" directory, remove "
-%% "the local file. Then open a new connection; cd to \"incoming\", "
-%% "lcd to the private directory; receive the file; delete the "
-%% "remote file; close connection; check that received file is in "
-%% "the correct directory; cleanup." ];
-%% big_one(Config) ->
-%% Pid = ?config(ftp, Config),
-%% do_recv(Pid, Config).
-%% do_recv(Pid, Config) ->
-%% PrivDir = ?config(priv_dir, Config),
-%% File = ?config(file, Config),
-%% Newfile = ?config(new_file, Config),
-%% AbsFile = filename:absname(File, PrivDir),
-%% Contents = "ftp_SUITE:recv test ...",
-%% ok = file:write_file(AbsFile, list_to_binary(Contents)),
-%% ok = ftp:cd(Pid, "incoming"),
-%% ftp:delete(Pid, File), % reset
-%% ftp:lcd(Pid, PrivDir),
-%% ok = ftp:send(Pid, File),
-%% ok = file:delete(AbsFile), % cleanup
-%% test_server:sleep(100),
-%% ok = ftp:lcd(Pid, PrivDir),
-%% ok = ftp:recv(Pid, File),
-%% {ok, Files} = file:list_dir(PrivDir),
-%% true = lists:member(File, Files),
-%% ok = file:delete(AbsFile), % cleanup
-%% ok = ftp:recv(Pid, File, Newfile),
-%% ok = ftp:delete(Pid, File), % cleanup
-%% ok.
+unexpected_bang()->
+ [{doc, "Test that connection ignores unexpected bang"}].
+unexpected_bang(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+ %% Could be an innocent misstake the connection lives.
+ Pid ! foobar,
+ ct:sleep(500),
+ {status, _} = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
+
+%%-------------------------------------------------------------------------
+clean_shutdown() ->
+ [{doc, "Test that owning process that exits with reason "
+ "'shutdown' does not cause an error message. OTP 6035"}].
+
+clean_shutdown(Config) ->
+ Parent = self(),
+ HelperPid = spawn(
+ fun() ->
+ ftp__open(Config, [verbose]),
+ Parent ! ok,
+ receive
+ nothing -> ok
+ end
+ end),
+ receive
+ ok ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ LogFile = filename:join([PrivDir,"ticket_6035.log"]),
+ error_logger:logfile({open, LogFile}),
+ exit(HelperPid, shutdown),
+ timer:sleep(2000),
+ error_logger:logfile(close),
+ case is_error_report_6035(LogFile) of
+ true -> ok;
+ false -> {fail, "Bad logfile"}
+ end
+ end.
+%%%----------------------------------------------------------------
+%%% Error codes not tested elsewhere
+
+error_elogin(Config0) ->
+ Dir = "test",
+ OldFile = "old.txt",
+ NewFile = "new.txt",
+ SrcDir = "data",
+ File = "file.txt",
+ Config = set_state([reset,
+ {mkdir,Dir},
+ {mkfile,OldFile,<<"Contents..">>},
+ {mkfile,[SrcDir,File],<<"Contents..">>}], Config0),
+
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
+ {error,elogin} = ftp:send(Pid, File),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ {error,elogin} = ftp:pwd(Pid),
+ {error,elogin} = ftp:cd(Pid, id2ftp(Dir,Config)),
+ {error,elogin} = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
+ ok.
+
+error_ehost(_Config) ->
+ {error, ehost} = ftp:open("nohost.nodomain"),
+ ok.
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
@@ -676,71 +956,81 @@ chk_no_dir(PathList, Config) ->
ct:fail("Unexpected error for ~p: ~p",[Path,Error])
end.
-
-%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
-%% find a suitable ftpd
-%%
find_executable(Config) ->
- FTPservers = case ?config(ftpservers,Config) of
- undefined -> ?default_ftp_servers;
- L -> L
- end,
- case lists:dropwhile(fun not_available/1, FTPservers) of
- [] -> false;
- [FTPD_data|_] -> {ok, FTPD_data}
+ search_executable(proplists:get_value(ftpservers, Config, ?default_ftp_servers)).
+
+
+search_executable([{Name,Paths,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}|Srvrs]) ->
+ case os_find(Name,Paths) of
+ false ->
+ ct:log("~p not found",[Name]),
+ search_executable(Srvrs);
+ AbsName ->
+ ct:comment("Found ~p",[AbsName]),
+ {ok, {AbsName,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}}
+ end;
+search_executable([]) ->
+ false.
+
+
+os_find(Name, Paths) ->
+ case os:find_executable(Name, Paths) of
+ false -> os:find_executable(Name);
+ AbsName -> AbsName
end.
-not_available({Name,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}) ->
- os:find_executable(Name) == false.
-
-%%--------------------------------------------------------------------
-%% start/stop of ftpd
-%%
-start_ftpd(Config) ->
- {Name,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} = ?config(ftpd_data, Config),
- case StartCmd(Config) of
+%%%----------------------------------------------------------------
+start_ftpd(Config0) ->
+ {AbsName,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} =
+ proplists:get_value(ftpd_data, Config0),
+ case StartCmd(Config0, AbsName) of
{ok,StartResult} ->
- [{ftpd_host,Host},
- {ftpd_port,Port},
- {ftpd_start_result,StartResult} | ConfigRewrite(Config)];
+ Config = [{ftpd_host,Host},
+ {ftpd_port,Port},
+ {ftpd_start_result,StartResult} | ConfigRewrite(Config0)],
+ try
+ ftp__close(ftp__open(Config,[verbose]))
+ of
+ Config1 when is_list(Config1) ->
+ ct:log("Usuable ftp server ~p started on ~p:~p",[AbsName,Host,Port]),
+ Config
+ catch
+ Class:Exception ->
+ ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
+ [AbsName,Host,Port,Class,Exception]),
+ {skip, [AbsName," started but unusuable"]}
+ end;
{error,Msg} ->
- {skip, [Name," not started: ",Msg]}
+ {skip, [AbsName," not started: ",Msg]}
end.
stop_ftpd(Config) ->
- {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
- StopCommand(?config(ftpd_start_result,Config)).
+ {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ StopCommand(proplists:get_value(ftpd_start_result,Config)).
ps_ftpd(Config) ->
- {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
- ct:log( ChkUp(?config(ftpd_start_result,Config)) ).
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ ct:log( ChkUp(proplists:get_value(ftpd_start_result,Config)) ).
ftpd_running(Config) ->
- {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
- ChkUp(?config(ftpd_start_result,Config)).
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ ChkUp(proplists:get_value(ftpd_start_result,Config)).
-%%--------------------------------------------------------------------
-%% start/stop of ftpc
-%%
ftp__open(Config, Options) ->
- Host = ?config(ftpd_host,Config),
- Port = ?config(ftpd_port,Config),
+ Host = proplists:get_value(ftpd_host,Config),
+ Port = proplists:get_value(ftpd_port,Config),
ct:log("Host=~p, Port=~p",[Host,Port]),
{ok,Pid} = ftp:open(Host, [{port,Port} | Options]),
[{ftp,Pid}|Config].
ftp__close(Config) ->
- ok = ftp:close(?config(ftp,Config)),
+ ok = ftp:close(proplists:get_value(ftp,Config)),
Config.
-%%--------------------------------------------------------------------
-%%
split(Cs) -> string:tokens(Cs, "\r\n").
-%%--------------------------------------------------------------------
-%%
find_diff(Bin1, Bin2) ->
case find_diff(Bin1, Bin2, 1) of
{error, {diff,Pos,RC,LC}} ->
@@ -753,15 +1043,14 @@ find_diff(Bin1, Bin2) ->
find_diff(A, A, _) -> true;
find_diff(<<H,T1/binary>>, <<H,T2/binary>>, Pos) -> find_diff(T1, T2, Pos+1);
find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}.
-%%--------------------------------------------------------------------
-%%
+
set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops);
set_state(reset, Config) ->
rm('*', id2abs("",Config)),
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
file:set_cwd(PrivDir),
- ftp:lcd(?config(ftp,Config),PrivDir),
+ ftp:lcd(proplists:get_value(ftp,Config),PrivDir),
set_state({mkdir,""},Config);
set_state({mkdir,Id}, Config) ->
Abs = id2abs(Id, Config),
@@ -787,7 +1076,6 @@ mk_path(F, Pfx) ->
AbsName
end.
-
rm('*', Pfx) ->
{ok,Fs} = file:list_dir(Pfx),
lists:foreach(fun(F) -> rm(F, Pfx) end, Fs);
@@ -805,17 +1093,88 @@ rm(F, Pfx) ->
ok
end.
-%%--------------------------------------------------------------------
-%%
-
-id2abs(Id, Conf) -> filename:join(?config(priv_dir,Conf),ids(Id)).
-id2ftp(Id, Conf) -> (?config(id2ftp,Conf))(ids(Id)).
-id2ftp_result(Id, Conf) -> (?config(id2ftp_result,Conf))(ids(Id)).
+id2abs(Id, Conf) -> filename:join(proplists:get_value(priv_dir,Conf),ids(Id)).
+id2ftp(Id, Conf) -> (proplists:get_value(id2ftp,Conf))(ids(Id)).
+id2ftp_result(Id, Conf) -> (proplists:get_value(id2ftp_result,Conf))(ids(Id)).
ids([[_|_]|_]=Ids) -> filename:join(Ids);
ids(Id) -> Id.
-is_expected_absName(Id, File, Conf) -> File = (?config(id2abs,Conf))(Id).
-is_expected_ftpInName(Id, File, Conf) -> File = (?config(id2ftp,Conf))(Id).
-is_expected_ftpOutName(Id, File, Conf) -> File = (?config(id2ftp_result,Conf))(Id).
+is_expected_absName(Id, File, Conf) -> File = (proplists:get_value(id2abs,Conf))(Id).
+is_expected_ftpInName(Id, File, Conf) -> File = (proplists:get_value(id2ftp,Conf))(Id).
+is_expected_ftpOutName(Id, File, Conf) -> File = (proplists:get_value(id2ftp_result,Conf))(Id).
+
+
+%%%----------------------------------------------------------------
+%%% Help functions for the option '{progress,Progress}'
+%%%
+
+%%%----------------
+%%% Callback:
+
+progress(#progress{} = P, _File, {file_size, Total} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! start,
+ P#progress{total = Total};
+
+progress(#progress{current = Current} = P, _File, {transfer_size, 0} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! finish,
+ case P#progress.total of
+ unknown -> P;
+ Current -> P;
+ Total -> ct:fail({error, {progress, {total,Total}, {current,Current}}}),
+ P
+ end;
+
+progress(#progress{current = Current} = P, _File, {transfer_size, Size} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! update,
+ P#progress{current = Current + Size};
+
+progress(P, _File, M) ->
+ ct:pal("Progress **** Strange: ~p",[M]),
+ P.
+
+
+%%%----------------
+%%% Help process that counts the files transferred:
+
+progress_report_receiver_init(Parent, N) ->
+ register(progress_report_receiver, self()),
+ progress_report_receiver_expect_N_files(Parent, N).
+
+progress_report_receiver_expect_N_files(_Parent, 0) ->
+ ct:pal("progress_report got all files!", []);
+progress_report_receiver_expect_N_files(Parent, N) ->
+ ct:pal("progress_report expects ~p more files",[N]),
+ receive
+ start -> ok
+ end,
+ progress_report_receiver_loop(Parent, N-1).
+
+
+progress_report_receiver_loop(Parent, N) ->
+ ct:pal("progress_report expect update | finish. N = ~p",[N]),
+ receive
+ update ->
+ ct:pal("progress_report got update",[]),
+ progress_report_receiver_loop(Parent, N);
+ finish ->
+ ct:pal("progress_report got finish, send ~p to ~p",[{self(),ok}, Parent]),
+ Parent ! {self(), ok},
+ progress_report_receiver_expect_N_files(Parent, N)
+ end.
+
+%%%----------------------------------------------------------------
+%%% Help functions for bug OTP-6035
+
+is_error_report_6035(LogFile) ->
+ case file:read_file(LogFile) of
+ {ok, Bin} ->
+ nomatch =/= binary:match(Bin, <<"=ERROR REPORT====">>);
+ _ ->
+ false
+ end.
+
diff --git a/lib/inets/test/ftp_format_SUITE.erl b/lib/inets/test/ftp_format_SUITE.erl
index 9b71d2944b..95d594a44b 100644
--- a/lib/inets/test/ftp_format_SUITE.erl
+++ b/lib/inets/test/ftp_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,18 +24,13 @@
-include_lib("common_test/include/ct.hrl").
-include("ftp_internal.hrl").
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
-%% Test cases must be exported.
--export([ ftp_150/1,
- ftp_200/1, ftp_220/1, ftp_226/1, ftp_257/1, ftp_331/1, ftp_425/1,
- ftp_other_status_codes/1, ftp_multiple_lines/1,
- ftp_multipel_ctrl_messages/1, format_error/1]).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,5}}
+ ].
all() ->
[{group, ftp_response}, format_error].
@@ -43,8 +38,8 @@ all() ->
groups() ->
[{ftp_response, [],
[ftp_150, ftp_200, ftp_220, ftp_226, ftp_257, ftp_331,
- ftp_425, ftp_other_status_codes, ftp_multiple_lines,
- ftp_multipel_ctrl_messages]}].
+ ftp_425, ftp_other_status_codes, ftp_multiple_lines_status_in_msg,
+ ftp_multiple_lines, ftp_multipel_ctrl_messages]}].
init_per_suite(Config) ->
Config.
@@ -60,23 +55,16 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_, Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- [{watchdog, Dog} | NewConfig].
-
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+end_per_testcase(_, _) ->
ok.
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
-ftp_150(doc) ->
- ["Especially check that respons can be devided in a random place."];
-ftp_150(suite) ->
- [];
+ftp_150() ->
+ [{doc, "Especially check that respons can be devided in a random place."}].
ftp_150(Config) when is_list(Config) ->
FtpResponse = ["150 ASCII data conn", "ection for /bin/ls ",
"(134.138.177", ".89,50434) (0 bytes).\r\n"],
@@ -84,14 +72,11 @@ ftp_150(Config) when is_list(Config) ->
"150 ASCII data connection for /bin/ls "
"(134.138.177.89,50434) (0 bytes).\r\n" = Msg =
parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_prel, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_200(doc) ->
- ["Especially check that respons can be devided after the first status "
- "code character and in the end delimiter."];
-ftp_200(suite) ->
- [];
+ {pos_prel, _} = ftp_response:interpret(Msg).
+
+ftp_200() ->
+ [{doc, "Especially check that respons can be devided after the first status "
+ "code character and in the end delimiter."}].
ftp_200(Config) when is_list(Config) ->
FtpResponse = ["2", "00 PORT command successful.", [?CR], [?LF]],
@@ -100,11 +85,9 @@ ftp_200(Config) when is_list(Config) ->
{pos_compl, _} = ftp_response:interpret(Msg),
ok.
-ftp_220(doc) ->
- ["Especially check that respons can be devided after the "
- "first with space "];
-ftp_220(suite) ->
- [];
+ftp_220() ->
+ [{doc, "Especially check that respons can be devided after the "
+ "first with space "}].
ftp_220(Config) when is_list(Config) ->
FtpResponse = ["220 ","fingon FTP server (SunOS 5.8) ready.\r\n"],
@@ -113,11 +96,9 @@ ftp_220(Config) when is_list(Config) ->
{pos_compl, _} = ftp_response:interpret(Msg),
ok.
-ftp_226(doc) ->
- ["Especially check that respons can be devided after second status code"
- " character and in the end delimiter."];
-ftp_226(suite) ->
- [];
+ftp_226() ->
+ [{doc, "Especially check that respons can be devided after second status code"
+ " character and in the end delimiter."}].
ftp_226(Config) when is_list(Config) ->
FtpResponse = ["22" "6 Transfer complete.\r", [?LF]],
@@ -126,10 +107,8 @@ ftp_226(Config) when is_list(Config) ->
{pos_compl, _} = ftp_response:interpret(Msg),
ok.
-ftp_257(doc) ->
- ["Especially check that quoted chars do not cause a problem."];
-ftp_257(suite) ->
- [];
+ftp_257() ->
+ [{doc, "Especially check that quoted chars do not cause a problem."}].
ftp_257(Config) when is_list(Config) ->
FtpResponse = ["257 \"/\" is current directory.\r\n"],
@@ -138,11 +117,9 @@ ftp_257(Config) when is_list(Config) ->
{pos_compl, _} = ftp_response:interpret(Msg),
ok.
-ftp_331(doc) ->
- ["Especially check that respons can be devided after the third status "
- " status code character."];
-ftp_331(suite) ->
- [];
+ftp_331() ->
+ [{doc, "Especially check that respons can be devided after the third status "
+ " status code character."}].
ftp_331(Config) when is_list(Config) ->
%% Brake before white space after code
FtpResponse =
@@ -153,10 +130,8 @@ ftp_331(Config) when is_list(Config) ->
{pos_interm, _} = ftp_response:interpret(Msg),
ok.
-ftp_425(doc) ->
- ["Especially check a message that was received in only one part."];
-ftp_425(suite) ->
- [];
+ftp_425() ->
+ [{doc, "Especially check a message that was received in only one part."}].
ftp_425(Config) when is_list(Config) ->
FtpResponse =
["425 Can't build data connection: Connection refused.\r\n"],
@@ -166,10 +141,17 @@ ftp_425(Config) when is_list(Config) ->
{trans_neg_compl, _} = ftp_response:interpret(Msg),
ok.
-ftp_multiple_lines(doc) ->
- ["Especially check multiple lines devided in significant places"];
-ftp_multiple_lines(suite) ->
- [];
+ftp_multiple_lines_status_in_msg() ->
+ [{doc, "check that multiple lines gets parsed correct, even if we have "
+ " the status code within the msg being sent"}].
+ftp_multiple_lines_status_in_msg(Config) when is_list(Config) ->
+ ML = "230-User usr-230 is logged in\r\n" ++
+ "230 OK. Current directory is /\r\n",
+ {ok, ML, <<>>} = ftp_response:parse_lines(list_to_binary(ML), [], start),
+ ok.
+
+ftp_multiple_lines() ->
+ [{doc, "Especially check multiple lines devided in significant places"}].
ftp_multiple_lines(Config) when is_list(Config) ->
FtpResponse = ["21", "4","-The",
" following commands are recognized:\r\n"
@@ -247,13 +229,11 @@ ftp_multiple_lines(Config) when is_list(Config) ->
FtpResponse2),
ok.
-ftp_other_status_codes(doc) ->
- ["Check that other valid status codes, than the ones above, are handled"
+ftp_other_status_codes() ->
+ [{doc, "Check that other valid status codes, than the ones above, are handled"
"by ftp_response:interpret/1. Note there are som ftp status codes"
"that will not be received with the current ftp instruction support,"
- "they are not included here."];
-ftp_other_status_codes(suite) ->
- [];
+ "they are not included here."}].
ftp_other_status_codes(Config) when is_list(Config) ->
%% 1XX
@@ -282,18 +262,16 @@ ftp_other_status_codes(Config) when is_list(Config) ->
{perm_neg_compl, _ } = ftp_response:interpret("501 Foobar\r\n"),
{perm_neg_compl, _ } = ftp_response:interpret("503 Foobar\r\n"),
{perm_neg_compl, _ } = ftp_response:interpret("504 Foobar\r\n"),
- {perm_neg_compl, _ } = ftp_response:interpret("530 Foobar\r\n"),
+ {elogin, _ } = ftp_response:interpret("530 Foobar\r\n"),
{perm_neg_compl, _ } = ftp_response:interpret("532 Foobar\r\n"),
{epath, _ } = ftp_response:interpret("550 Foobar\r\n"),
{epnospc, _ } = ftp_response:interpret("552 Foobar\r\n"),
{efnamena, _ } = ftp_response:interpret("553 Foobar\r\n"),
ok.
-ftp_multipel_ctrl_messages(doc) ->
- ["The ftp server may send more than one control message as a reply,"
- "check that they are handled one at the time."];
-ftp_multipel_ctrl_messages(suite) ->
- [];
+ftp_multipel_ctrl_messages() ->
+ [{doc, "The ftp server may send more than one control message as a reply,"
+ "check that they are handled one at the time."}].
ftp_multipel_ctrl_messages(Config) when is_list(Config) ->
FtpResponse = ["200 PORT command successful.\r\n200 Foobar\r\n"],
@@ -306,10 +284,6 @@ ftp_multipel_ctrl_messages(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-format_error(doc) ->
- [""];
-format_error(suite) ->
- [];
format_error(Config) when is_list(Config) ->
"Synchronisation error during chunk sending." =
ftp:formaterror(echunk),
@@ -346,7 +320,7 @@ parse(Module, Function, [AccLines, StatusCode], [Data | Rest]) ->
{continue, {NewData, NewAccLines, NewStatusCode}} ->
case Rest of
[] ->
- test_server:fail({wrong_input, Data, Rest});
+ ct:fail({wrong_input, Data, Rest});
[_ | _] ->
parse(Module, Function, [NewAccLines, NewStatusCode],
[binary_to_list(NewData) ++ hd(Rest) | tl(Rest)])
diff --git a/lib/inets/test/ftp_property_test_SUITE.erl b/lib/inets/test/ftp_property_test_SUITE.erl
index 984fb58f16..b314882296 100644
--- a/lib/inets/test/ftp_property_test_SUITE.erl
+++ b/lib/inets/test/ftp_property_test_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
deleted file mode 100644
index 6d30f3aa62..0000000000
--- a/lib/inets/test/ftp_suite_lib.erl
+++ /dev/null
@@ -1,1696 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_suite_lib).
-
-
--include_lib("test_server/include/test_server.hrl").
--include_lib("test_server/include/test_server_line.hrl").
--include("inets_test_lib.hrl").
-
-%% Test server specific exports
-% -export([init_per_testcase/2, end_per_testcase/2]).
-
--compile(export_all).
-
-
--record(progress, {
- current = 0,
- total
- }).
-
-
-
--define(FTP_USER, "anonymous").
--define(FTP_PASS, passwd()).
--define(FTP_PORT, 21).
-
--define(BAD_HOST, "badhostname").
--define(BAD_USER, "baduser").
--define(BAD_DIR, "baddirectory").
-
--ifdef(ftp_debug_client).
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{debug, debug},
- {timeout, timer:seconds(15)} | Flags])).
--else.
--ifdef(ftp_trace_client).
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{debug, trace},
- {timeout, timer:seconds(15)} | Flags])).
--else.
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{verbose, true},
- {timeout, timer:seconds(15)} | Flags])).
--endif.
--endif.
-
-%% -- Tickets --
-
-tickets(doc) ->
- "Test cases for reported bugs";
-tickets(suite) ->
- [ticket_6035].
-
-%% --
-
-ftpd_init(FtpdTag, Config) ->
- %% Get the host name(s) of FTP server
- Hosts =
- case ct:get_config(ftpd_hosts) of
- undefined ->
- ftpd_hosts(data_dir(Config));
- H ->
- H
- end,
- p("ftpd_init -> "
- "~n Hosts: ~p"
- "~n Config: ~p"
- "~n FtpdTag: ~p", [Hosts, Config, FtpdTag]),
- %% Get the first host that actually have a running FTP server
- case lists:keysearch(FtpdTag, 1, Hosts) of
- {value, {_, TagHosts}} when is_list(TagHosts) ->
- inets:start(),
- case (catch get_ftpd_host(TagHosts)) of
- {ok, Host} ->
- inets:stop(),
- [{ftp_remote_host, Host}|Config];
- _ ->
- inets:stop(),
- Reason = lists:flatten(
- io_lib:format("Could not find a valid "
- "FTP server for ~p (~p)",
- [FtpdTag, TagHosts])),
- {skip, Reason}
- end;
- _ ->
- Reason = lists:flatten(
- io_lib:format("No host(s) running FTPD server "
- "for ~p", [FtpdTag])),
- {skip, Reason}
- end.
-
-ftpd_fin(Config) ->
- lists:keydelete(ftp_remote_host, 1, Config).
-
-get_ftpd_host([]) ->
- {error, no_host};
-get_ftpd_host([Host|Hosts]) ->
- p("get_ftpd_host -> entry with"
- "~n Host: ~p"
- "~n", [Host]),
- case (catch ftp:open(Host, [{port, ?FTP_PORT}, {timeout, 20000}])) of
- {ok, Pid} ->
- (catch ftp:close(Pid)),
- {ok, Host};
- _ ->
- get_ftpd_host(Hosts)
- end.
-
-
-%%--------------------------------------------------------------------
-
-dirty_select_ftpd_host(Config) ->
- Hosts =
- case ct:get_config(ftpd_hosts) of
- undefined ->
- ftpd_hosts(data_dir(Config));
- H ->
- H
- end,
- dirty_select_ftpd_host2(Hosts).
-
-dirty_select_ftpd_host2([]) ->
- throw({error, not_found});
-dirty_select_ftpd_host2([{PlatformTag, Hosts} | PlatformHosts]) ->
- case dirty_select_ftpd_host3(Hosts) of
- none ->
- dirty_select_ftpd_host2(PlatformHosts);
- {ok, Host} ->
- {PlatformTag, Host}
- end.
-
-dirty_select_ftpd_host3([]) ->
- none;
-dirty_select_ftpd_host3([Host|Hosts]) when is_list(Host) ->
- case dirty_select_ftpd_host4(Host) of
- true ->
- {ok, Host};
- false ->
- dirty_select_ftpd_host3(Hosts)
- end;
-dirty_select_ftpd_host3([_|Hosts]) ->
- dirty_select_ftpd_host3(Hosts).
-
-%% This is a very simple and dirty test that there is a
-%% (FTP) deamon on the other end.
-dirty_select_ftpd_host4(Host) ->
- Port = 21,
- IpFam = inet,
- Opts = [IpFam, binary, {packet, 0}, {active, false}],
- Timeout = ?SECS(5),
- case gen_tcp:connect(Host, Port, Opts, Timeout) of
- {ok, Sock} ->
- gen_tcp:close(Sock),
- true;
- _Error ->
- false
- end.
-
-
-%%--------------------------------------------------------------------
-
-test_filenames() ->
- {ok, Host} = inet:gethostname(),
- File = Host ++ "_ftp_test.txt",
- NewFile = "new_" ++ File,
- {File, NewFile}.
-
-%%--------------------------------------------------------------------
-%% 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)
- when (Case =:= open) orelse
- (Case =:= open_port) ->
- put(ftp_testcase, Case),
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
- inets:start(),
- NewConfig = data_dir(Config),
- watch_dog(NewConfig);
-
-init_per_testcase(Case, Config) ->
- put(ftp_testcase, Case),
- do_init_per_testcase(Case, Config).
-
-do_init_per_testcase(Case, Config)
- when (Case =:= passive_user) ->
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
- inets:start(),
- NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
- case (catch ?ftp_open(Host, [{mode, passive}])) of
- {ok, Pid} ->
- [{ftp, Pid} | data_dir(NewConfig)];
- {skip, _} = SKIP ->
- SKIP
- end;
-
-do_init_per_testcase(Case, Config)
- when (Case =:= active_user) ->
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
- inets:start(),
- NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
- case (catch ?ftp_open(Host, [{mode, active}])) of
- {ok, Pid} ->
- [{ftp, Pid} | data_dir(NewConfig)];
- {skip, _} = SKIP ->
- SKIP
- end;
-
-do_init_per_testcase(Case, Config)
- when (Case =:= progress_report_send) orelse
- (Case =:= progress_report_recv) ->
- inets:start(),
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
- NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
- Opts = [{port, ?FTP_PORT},
- {verbose, true},
- {progress, {?MODULE, progress, #progress{}}}],
- case ftp:open(Host, Opts) of
- {ok, Pid} ->
- ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS),
- [{ftp, Pid} | data_dir(NewConfig)];
- {skip, _} = SKIP ->
- SKIP
- end;
-
-do_init_per_testcase(Case, Config) ->
- io:format(user,"~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
- inets:start(),
- NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
- Opts1 =
- if
- ((Case =:= passive_ip_v6_disabled) orelse
- (Case =:= active_ip_v6_disabled)) ->
- [{ipfamily, inet}];
- true ->
- []
- end,
- Opts2 =
- case string:tokens(atom_to_list(Case), [$_]) of
- ["active" | _] ->
- [{mode, active} | Opts1];
- _ ->
- [{mode, passive} | Opts1]
- end,
- case (catch ?ftp_open(Host, Opts2)) of
- {ok, Pid} ->
- ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS),
- [{ftp, Pid} | data_dir(NewConfig)];
- {skip, _} = SKIP ->
- SKIP
- end.
-
-
-%%--------------------------------------------------------------------
-%% 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(_, Config) ->
- NewConfig = close_connection(Config),
- Dog = ?config(watchdog, NewConfig),
- inets:stop(),
- test_server:timetrap_cancel(Dog),
- ok.
-
-
-%%-------------------------------------------------------------------------
-%% Suites similar for all hosts.
-%%-------------------------------------------------------------------------
-
-passive(suite) ->
- [
- passive_user,
- passive_pwd,
- passive_cd,
- passive_lcd,
- passive_ls,
- passive_nlist,
- passive_rename,
- passive_delete,
- passive_mkdir,
- passive_send,
- passive_send_bin,
- passive_send_chunk,
- passive_append,
- passive_append_bin,
- passive_append_chunk,
- passive_recv,
- passive_recv_bin,
- passive_recv_chunk,
- passive_type,
- passive_quote,
- passive_ip_v6_disabled
- ].
-
-active(suite) ->
- [
- active_user,
- active_pwd,
- active_cd,
- active_lcd,
- active_ls,
- active_nlist,
- active_rename,
- active_delete,
- active_mkdir,
- active_send,
- active_send_bin,
- active_send_chunk,
- active_append,
- active_append_bin,
- active_append_chunk,
- active_recv,
- active_recv_bin,
- active_recv_chunk,
- active_type,
- active_quote,
- active_ip_v6_disabled
- ].
-
-
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-
-open(doc) ->
- ["Open an ftp connection to a host and close the connection."
- "Also check that !-messages does not disturbe the connection"];
-open(suite) ->
- [];
-open(Config) when is_list(Config) ->
- Host = ftp_host(Config),
- (catch tc_open(Host)).
-
-
-tc_open(Host) ->
- p("tc_open -> entry with"
- "~n Host: ~p", [Host]),
- {ok, Pid} = ?ftp_open(Host, []),
- ok = ftp:close(Pid),
- p("tc_open -> try (ok) open 1"),
- {ok, Pid1} =
- ftp:open({option_list, [{host,Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
- {timeout, 30000}]}),
- ok = ftp:close(Pid1),
-
- p("tc_open -> try (fail) open 2"),
- {error, ehost} =
- ftp:open({option_list, [{port, ?FTP_PORT}, {flags, [verbose]}]}),
- {ok, Pid2} = ftp:open(Host),
- ok = ftp:close(Pid2),
-
- p("tc_open -> try (ok) open 3"),
- {ok, NewHost} = inet:getaddr(Host, inet),
- {ok, Pid3} = ftp:open(NewHost),
- ftp:user(Pid3, ?FTP_USER, ?FTP_PASS),
- Pid3 ! foobar,
- test_server:sleep(5000),
- {message_queue_len, 0} = process_info(self(), message_queue_len),
- ["200" ++ _] = ftp:quote(Pid3, "NOOP"),
- ok = ftp:close(Pid3),
-
- %% Bad input that has default values are ignored and the defult
- %% is used.
- p("tc_open -> try (ok) open 4"),
- {ok, Pid4} =
- ftp:open({option_list, [{host, Host},
- {port, badarg},
- {flags, [verbose]},
- {timeout, 30000}]}),
- test_server:sleep(100),
- ok = ftp:close(Pid4),
-
- p("tc_open -> try (ok) open 5"),
- {ok, Pid5} =
- ftp:open({option_list, [{host, Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
- {timeout, -42}]}),
- test_server:sleep(100),
- ok = ftp:close(Pid5),
-
- p("tc_open -> try (ok) open 6"),
- {ok, Pid6} =
- ftp:open({option_list, [{host, Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
- {mode, cool}]}),
- test_server:sleep(100),
- ok = ftp:close(Pid6),
-
- p("tc_open -> try (ok) open 7"),
- {ok, Pid7} =
- ftp:open(Host, [{port, ?FTP_PORT}, {verbose, true}, {timeout, 30000}]),
- ok = ftp:close(Pid7),
-
- p("tc_open -> try (ok) open 8"),
- {ok, Pid8} =
- ftp:open(Host, ?FTP_PORT),
- ok = ftp:close(Pid8),
-
- p("tc_open -> try (ok) open 9"),
- {ok, Pid9} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
- {dtimeout, -99}]),
- ok = ftp:close(Pid9),
-
- p("tc_open -> try (ok) open 10"),
- {ok, Pid10} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
- {dtimeout, "foobar"}]),
- ok = ftp:close(Pid10),
-
- p("tc_open -> try (ok) open 11"),
- {ok, Pid11} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
- {dtimeout, 1}]),
- ok = ftp:close(Pid11),
-
- p("tc_open -> done"),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-open_port(doc) ->
- ["Open an ftp connection to a host with given port number "
- "and close the connection."]; % See also OTP-3892
-open_port(suite) ->
- [];
-open_port(Config) when is_list(Config) ->
- Host = ftp_host(Config),
- {ok, Pid} = ftp:open(Host, [{port, ?FTP_PORT}]),
- ok = ftp:close(Pid),
- {error, ehost} = ftp:open(?BAD_HOST, []),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-passive_user(doc) ->
- ["Open an ftp connection to a host, and logon as anonymous ftp."];
-passive_user(suite) ->
- [];
-passive_user(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- p("Pid: ~p",[Pid]),
- do_user(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_pwd(doc) ->
- ["Test ftp:pwd/1 & ftp:lpwd/1"];
-passive_pwd(suite) ->
- [];
-passive_pwd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_pwd(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_cd(doc) ->
- ["Open an ftp connection, log on as anonymous ftp, and cd to the"
- "directory \"/pub\" and the to the non-existent directory."];
-passive_cd(suite) ->
- [];
-passive_cd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_cd(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_lcd(doc) ->
- ["Test api function ftp:lcd/2"];
-passive_lcd(suite) ->
- [];
-passive_lcd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- PrivDir = ?config(priv_dir, Config),
- do_lcd(Pid, PrivDir).
-
-
-%%-------------------------------------------------------------------------
-
-passive_ls(doc) ->
- ["Open an ftp connection; ls the current directory, and the "
- "\"incoming\" directory. We assume that ls never fails, since "
- "it's output is meant to be read by humans. "];
-passive_ls(suite) ->
- [];
-passive_ls(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_ls(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_nlist(doc) ->
- ["Open an ftp connection; nlist the current directory, and the "
- "\"incoming\" directory. Nlist does not behave consistenly over "
- "operating systems. On some it is an error to have an empty "
- "directory."];
-passive_nlist(suite) ->
- [];
-passive_nlist(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- WildcardSupport = ?config(wildcard_support, Config),
- do_nlist(Pid, WildcardSupport).
-
-
-%%-------------------------------------------------------------------------
-
-passive_rename(doc) ->
- ["Transfer a file to the server, and rename it; then remove it."];
-passive_rename(suite) ->
- [];
-passive_rename(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_rename(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_delete(doc) ->
- ["Transfer a file to the server, and then delete it"];
-passive_delete(suite) ->
- [];
-passive_delete(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_delete(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_mkdir(doc) ->
- ["Make a remote directory, cd to it, go to parent directory, and "
- "remove the directory."];
-passive_mkdir(suite) ->
- [];
-passive_mkdir(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_mkdir(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_send(doc) ->
- ["Create a local file in priv_dir; open an ftp connection to a host; "
- "logon as anonymous ftp; cd to the directory \"incoming\"; lcd to "
- "priv_dir; send the file; get a directory listing and check that "
- "the file is on the list;, delete the remote file; get another listing "
- "and check that the file is not on the list; close the session; "
- "delete the local file."];
-passive_send(suite) ->
- [];
-passive_send(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_append(doc) ->
- ["Create a local file in priv_dir; open an ftp connection to a host; "
- "logon as anonymous ftp; cd to the directory \"incoming\"; lcd to "
- "priv_dir; append the file to a file at the remote side that not exits"
- "this will create the file at the remote side. Then it append the file "
- "again. When this is done it recive the remote file and control that"
- "the content is doubled in it.After that it will remove the files"];
-passive_append(suite) ->
- [];
-passive_append(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_send_bin(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "send a binary; remove file; close the connection."];
-passive_send_bin(suite) ->
- [];
-passive_send_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send_bin(Pid, Config).
-
-%%-------------------------------------------------------------------------
-
-passive_append_bin(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "append a binary twice; get the file and compare the content"
- "remove file; close the connection."];
-passive_append_bin(suite) ->
- [];
-passive_append_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append_bin(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_send_chunk(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "send chunks; remove file; close the connection."];
-passive_send_chunk(suite) ->
- [];
-passive_send_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_append_chunk(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "append chunks;control content remove file; close the connection."];
-passive_append_chunk(suite) ->
- [];
-passive_append_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_recv(doc) ->
- ["Create a local file and transfer it to the remote host into the "
- "the \"incoming\" directory, remove "
- "the local file. Then open a new connection; cd to \"incoming\", "
- "lcd to the private directory; receive the file; delete the "
- "remote file; close connection; check that received file is in "
- "the correct directory; cleanup." ];
-passive_recv(suite) ->
- [];
-passive_recv(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_recv_bin(doc) ->
- ["Send a binary to the remote host; and retreive "
- "the file; then remove the file."];
-passive_recv_bin(suite) ->
- [];
-passive_recv_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv_bin(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_recv_chunk(doc) ->
- ["Send a binary to the remote host; Connect again, and retreive "
- "the file; then remove the file."];
-passive_recv_chunk(suite) ->
- [];
-passive_recv_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-passive_type(doc) ->
- ["Test that we can change btween ASCCI and binary transfer mode"];
-passive_type(suite) ->
- [];
-passive_type(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_type(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_quote(doc) ->
- [""];
-passive_quote(suite) ->
- [];
-passive_quote(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_quote(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-passive_ip_v6_disabled(doc) ->
- ["Test ipv4 command PASV"];
-passive_ip_v6_disabled(suite) ->
- [];
-passive_ip_v6_disabled(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_user(doc) ->
- ["Open an ftp connection to a host, and logon as anonymous ftp."];
-active_user(suite) ->
- [];
-active_user(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_user(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_pwd(doc) ->
- ["Test ftp:pwd/1 & ftp:lpwd/1"];
-active_pwd(suite) ->
- [];
-active_pwd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_pwd(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_cd(doc) ->
- ["Open an ftp connection, log on as anonymous ftp, and cd to the"
- "directory \"/pub\" and to a non-existent directory."];
-active_cd(suite) ->
- [];
-active_cd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_cd(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_lcd(doc) ->
- ["Test api function ftp:lcd/2"];
-active_lcd(suite) ->
- [];
-active_lcd(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- PrivDir = ?config(priv_dir, Config),
- do_lcd(Pid, PrivDir).
-
-
-%%-------------------------------------------------------------------------
-
-active_ls(doc) ->
- ["Open an ftp connection; ls the current directory, and the "
- "\"incoming\" directory. We assume that ls never fails, since "
- "it's output is meant to be read by humans. "];
-active_ls(suite) ->
- [];
-active_ls(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_ls(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_nlist(doc) ->
- ["Open an ftp connection; nlist the current directory, and the "
- "\"incoming\" directory. Nlist does not behave consistenly over "
- "operating systems. On some it is an error to have an empty "
- "directory."];
-active_nlist(suite) ->
- [];
-active_nlist(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- WildcardSupport = ?config(wildcard_support, Config),
- do_nlist(Pid, WildcardSupport).
-
-
-%%-------------------------------------------------------------------------
-
-active_rename(doc) ->
- ["Transfer a file to the server, and rename it; then remove it."];
-active_rename(suite) ->
- [];
-active_rename(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_rename(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_delete(doc) ->
- ["Transfer a file to the server, and then delete it"];
-active_delete(suite) ->
- [];
-active_delete(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_delete(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_mkdir(doc) ->
- ["Make a remote directory, cd to it, go to parent directory, and "
- "remove the directory."];
-active_mkdir(suite) ->
- [];
-active_mkdir(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_mkdir(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_send(doc) ->
- ["Create a local file in priv_dir; open an ftp connection to a host; "
- "logon as anonymous ftp; cd to the directory \"incoming\"; lcd to "
- "priv_dir; send the file; get a directory listing and check that "
- "the file is on the list;, delete the remote file; get another listing "
- "and check that the file is not on the list; close the session; "
- "delete the local file."];
-active_send(suite) ->
- [];
-active_send(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_append(doc) ->
- ["Create a local file in priv_dir; open an ftp connection to a host; "
- "logon as anonymous ftp; cd to the directory \"incoming\"; lcd to "
- "priv_dir; append the file to a file at the remote side that not exits"
- "this will create the file at the remote side. Then it append the file "
- "again. When this is done it recive the remote file and control that"
- "the content is doubled in it.After that it will remove the files"];
-active_append(suite) ->
- [];
-active_append(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_send_bin(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "send a binary; remove file; close the connection."];
-active_send_bin(suite) ->
- [];
-active_send_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send_bin(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_append_bin(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "append a binary twice; get the file and compare the content"
- "remove file; close the connection."];
-active_append_bin(suite) ->
- [];
-active_append_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append_bin(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_send_chunk(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "send chunks; remove file; close the connection."];
-active_send_chunk(suite) ->
- [];
-active_send_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_append_chunk(doc) ->
- ["Open a connection to a host; cd to the directory \"incoming\"; "
- "append chunks;control content remove file; close the connection."];
-active_append_chunk(suite) ->
- [];
-active_append_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_append_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_recv(doc) ->
- ["Create a local file and transfer it to the remote host into the "
- "the \"incoming\" directory, remove "
- "the local file. Then open a new connection; cd to \"incoming\", "
- "lcd to the private directory; receive the file; delete the "
- "remote file; close connection; check that received file is in "
- "the correct directory; cleanup." ];
-active_recv(suite) ->
- [];
-active_recv(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_recv_bin(doc) ->
- ["Send a binary to the remote host; and retreive "
- "the file; then remove the file."];
-active_recv_bin(suite) ->
- [];
-active_recv_bin(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv_bin(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_recv_chunk(doc) ->
- ["Send a binary to the remote host; Connect again, and retreive "
- "the file; then remove the file."];
-active_recv_chunk(suite) ->
- [];
-active_recv_chunk(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_recv_chunk(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-active_type(doc) ->
- ["Test that we can change btween ASCCI and binary transfer mode"];
-active_type(suite) ->
- [];
-active_type(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_type(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_quote(doc) ->
- [""];
-active_quote(suite) ->
- [];
-active_quote(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_quote(Pid).
-
-
-%%-------------------------------------------------------------------------
-
-active_ip_v6_disabled(doc) ->
- ["Test ipv4 command PORT"];
-active_ip_v6_disabled(suite) ->
- [];
-active_ip_v6_disabled(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- do_send(Pid, Config).
-
-
-%%-------------------------------------------------------------------------
-
-api_missuse(doc)->
- ["Test that behaviour of the ftp process if the api is abused"];
-api_missuse(suite) -> [];
-api_missuse(Config) when is_list(Config) ->
- p("api_missuse -> entry"),
- Flag = process_flag(trap_exit, true),
- Pid = ?config(ftp, Config),
- Host = ftp_host(Config),
-
- %% Serious programming fault, connetion will be shut down
- p("api_missuse -> verify bad call termination (~p)", [Pid]),
- case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
- {error, {connection_terminated, 'API_violation'}} ->
- ok;
- Unexpected1 ->
- exit({unexpected_result, Unexpected1})
- end,
- test_server:sleep(500),
- undefined = process_info(Pid, status),
-
- p("api_missuse -> start new client"),
- {ok, Pid2} = ?ftp_open(Host, []),
- %% Serious programming fault, connetion will be shut down
- p("api_missuse -> verify bad cast termination"),
- gen_server:cast(Pid2, {self(), foobar, 10}),
- test_server:sleep(500),
- undefined = process_info(Pid2, status),
-
- p("api_missuse -> start new client"),
- {ok, Pid3} = ?ftp_open(Host, []),
- %% Could be an innocent misstake the connection lives.
- p("api_missuse -> verify bad bang"),
- Pid3 ! foobar,
- test_server:sleep(500),
- {status, _} = process_info(Pid3, status),
- process_flag(trap_exit, Flag),
- p("api_missuse -> done"),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-not_owner(doc) ->
- ["Test what happens if a process that not owns the connection tries "
- "to use it"];
-not_owner(suite) ->
- [];
-not_owner(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- OtherPid = spawn_link(?MODULE, not_owner, [Pid, self()]),
-
- receive
- {OtherPid, ok} ->
- {ok, _} = ftp:pwd(Pid)
- end,
- ok.
-
-not_owner(FtpPid, Pid) ->
- {error, not_connection_owner} = ftp:pwd(FtpPid),
- ftp:close(FtpPid),
- test_server:sleep(100),
- Pid ! {self(), ok}.
-
-
-%%-------------------------------------------------------------------------
-
-
-progress_report(doc) ->
- ["Solaris 8 sparc test the option progress."];
-progress_report(suite) ->
- [progress_report_send, progress_report_recv].
-
-
-%% --
-
-progress_report_send(doc) ->
- ["Test the option progress for ftp:send/[2,3]"];
-progress_report_send(suite) ->
- [];
-progress_report_send(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
- do_send(Pid, Config),
- receive
- {ReportPid, ok} ->
- ok
- end.
-
-
-%% --
-
-progress_report_recv(doc) ->
- ["Test the option progress for ftp:recv/[2,3]"];
-progress_report_recv(suite) ->
- [];
-progress_report_recv(Config) when is_list(Config) ->
- Pid = ?config(ftp, Config),
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
- do_recv(Pid, Config),
- receive
- {ReportPid, ok} ->
- ok
- end,
- ok.
-
-progress(#progress{} = Progress , _File, {file_size, Total}) ->
- progress_report_receiver ! start,
- Progress#progress{total = Total};
-progress(#progress{total = Total, current = Current}
- = Progress, _File, {transfer_size, 0}) ->
- progress_report_receiver ! finish,
- case Total of
- unknown ->
- ok;
- Current ->
- ok;
- _ ->
- test_server:fail({error, {progress, {total, Total},
- {current, Current}}})
- end,
- Progress;
-progress(#progress{current = Current} = Progress, _File,
- {transfer_size, Size}) ->
- progress_report_receiver ! update,
- Progress#progress{current = Current + Size}.
-
-progress_report_receiver_init(Pid, N) ->
- register(progress_report_receiver, self()),
- receive
- start ->
- ok
- end,
- progress_report_receiver_loop(Pid, N-1).
-
-progress_report_receiver_loop(Pid, N) ->
- receive
- update ->
- progress_report_receiver_loop(Pid, N);
- finish when N =:= 0 ->
- Pid ! {self(), ok};
- finish ->
- Pid ! {self(), ok},
- receive
- start ->
- ok
- end,
- progress_report_receiver_loop(Pid, N-1)
- end.
-
-
-%%-------------------------------------------------------------------------
-%% Ticket test cases
-%%-------------------------------------------------------------------------
-
-ticket_6035(doc) -> ["Test that owning process that exits with reason "
- "'shutdown' does not cause an error message."];
-ticket_6035(suite) -> [];
-ticket_6035(Config) ->
- p("ticket_6035 -> entry with"
- "~n Config: ~p", [Config]),
- PrivDir = ?config(priv_dir, Config),
- LogFile = filename:join([PrivDir,"ticket_6035.log"]),
- try
- begin
- p("ticket_6035 -> select ftpd host"),
- Host = dirty_select_ftpd_host(Config),
- p("ticket_6035 -> ftpd host selected (~p) => now spawn ftp owner", [Host]),
- Pid = spawn(?MODULE, open_wait_6035, [Host, self()]),
- p("ticket_6035 -> waiter spawned: ~p => now open error logfile (~p)",
- [Pid, LogFile]),
- error_logger:logfile({open, LogFile}),
- p("ticket_6035 -> error logfile open => now kill waiter process"),
- true = kill_ftp_proc_6035(Pid, LogFile),
- p("ticket_6035 -> waiter process killed => now close error logfile"),
- error_logger:logfile(close),
- p("ticket_6035 -> done", []),
- ok
- end
- catch
- throw:{error, not_found} ->
- {skip, "No available FTP servers"}
- end.
-
-kill_ftp_proc_6035(Pid, LogFile) ->
- p("kill_ftp_proc_6035 -> entry"),
- receive
- open ->
- p("kill_ftp_proc_6035 -> received open => now issue shutdown"),
- exit(Pid, shutdown),
- kill_ftp_proc_6035(Pid, LogFile);
- {open_failed, Reason} ->
- p("kill_ftp_proc_6035 -> received open_failed"
- "~n Reason: ~p", [Reason]),
- exit({skip, {failed_openening_server_connection, Reason}})
- after
- 5000 ->
- p("kill_ftp_proc_6035 -> timeout"),
- is_error_report_6035(LogFile)
- end.
-
-open_wait_6035({Tag, FtpServer}, From) ->
- p("open_wait_6035 -> try connect to [~p] ~s for ~p", [Tag, FtpServer, From]),
- case ftp:open(FtpServer, [{timeout, timer:seconds(15)}]) of
- {ok, Pid} ->
- p("open_wait_6035 -> connected (~p), now login", [Pid]),
- LoginResult = ftp:user(Pid,"anonymous","kldjf"),
- p("open_wait_6035 -> login result: ~p", [LoginResult]),
- From ! open,
- receive
- dummy ->
- p("open_wait_6035 -> received dummy"),
- ok
- after
- 10000 ->
- p("open_wait_6035 -> timeout"),
- ok
- end,
- p("open_wait_6035 -> done(ok)"),
- ok;
- {error, Reason} ->
- p("open_wait_6035 -> open failed"
- "~n Reason: ~p", [Reason]),
- From ! {open_failed, {Reason, FtpServer}},
- p("open_wait_6035 -> done(error)"),
- ok
- end.
-
-is_error_report_6035(LogFile) ->
- p("is_error_report_6035 -> entry"),
- Res =
- case file:read_file(LogFile) of
- {ok, Bin} ->
- Txt = binary_to_list(Bin),
- p("is_error_report_6035 -> logfile read: ~n~p", [Txt]),
- read_log_6035(Txt);
- _ ->
- false
- end,
- p("is_error_report_6035 -> logfile read result: "
- "~n ~p", [Res]),
- %% file:delete(LogFile),
- Res.
-
-read_log_6035("=ERROR REPORT===="++_Rest) ->
- p("read_log_6035 -> ERROR REPORT detected"),
- true;
-read_log_6035([H|T]) ->
- p("read_log_6035 -> OTHER: "
- "~p", [H]),
- read_log_6035(T);
-read_log_6035([]) ->
- p("read_log_6035 -> done"),
- false.
-
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-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.
-
-do_pwd(Pid) ->
- {ok, "/"} = ftp:pwd(Pid),
- {ok, Path} = ftp:lpwd(Pid),
- {ok, Path} = file:get_cwd(),
- ok.
-
-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) ->
- ok = ftp:lcd(Pid, Dir),
- {error, epath} = ftp:lcd(Pid, ?BAD_DIR),
- ok.
-
-
-do_ls(Pid) ->
- {ok, _} = ftp:ls(Pid),
- {ok, _} = ftp:ls(Pid, "incoming"),
- %% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
- %% of files (including wildcards).
- {ok, _} = ftp: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
- %% of files (including wildcards).
- case WildcardSupport of
- true ->
- {ok, _} = ftp:nlist(Pid, "incom*"),
- ok;
- _ ->
- ok
- end.
-
-do_rename(Pid, Config) ->
- PrivDir = ?config(priv_dir, Config),
- LFile = ?config(file, Config),
- NewLFile = ?config(new_file, Config),
- AbsLFile = filename:absname(LFile, PrivDir),
- Contents = "ftp_SUITE test ...",
- ok = file:write_file(AbsLFile, list_to_binary(Contents)),
- ok = ftp:cd(Pid, "incoming"),
- ok = ftp:lcd(Pid, PrivDir),
- ftp:delete(Pid, LFile), % reset
- 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
- ok.
-
-do_delete(Pid, Config) ->
- PrivDir = ?config(priv_dir, Config),
- LFile = ?config(file, Config),
- AbsLFile = filename:absname(LFile, PrivDir),
- Contents = "ftp_SUITE test ...",
- ok = file:write_file(AbsLFile, list_to_binary(Contents)),
- 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.
-
-do_mkdir(Pid) ->
- NewDir = "earl_" ++
- integer_to_list(inets_time_compat:unique_integer([positive])),
-
- 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),
- ok = ftp:rmdir(Pid, NewDir),
- ok.
-
-do_send(Pid, Config) ->
- PrivDir = ?config(priv_dir, Config),
- LFile = ?config(file, Config),
- RFile = LFile ++ ".remote",
- AbsLFile = filename:absname(LFile, PrivDir),
- Contents = "ftp_SUITE test ...",
- 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),
- true = lists:member(RFile, RFiles),
- ok = ftp:delete(Pid, RFile),
- case ftp:nlist(Pid) of
- {error, epath} ->
- ok; % No files
- {ok, RFilesString1} ->
- RFiles1 = split(RFilesString1),
- false = lists:member(RFile, RFiles1)
- end,
- ok = file:delete(AbsLFile).
-
-do_append(Pid, Config) ->
- PrivDir = ?config(priv_dir, Config),
- LFile = ?config(file, Config),
- RFile = ?config(new_file, Config),
- AbsLFile = filename:absname(LFile, PrivDir),
- Contents = "ftp_SUITE test:appending\r\n",
-
- ok = file:write_file(AbsLFile, list_to_binary(Contents)),
- ok = ftp:cd(Pid, "incoming"),
- ok = ftp:lcd(Pid, PrivDir),
-
- %% remove files from earlier failed test case
- 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),
-
- %% Control the contents of the file
- {ok, Bin1} = ftp:recv_bin(Pid, RFile),
- ok = ftp:delete(Pid, RFile),
- ok = file:delete(AbsLFile),
- ok = check_content(binary_to_list(Bin1), Contents, double),
-
- {ok, Bin2} = ftp:recv_bin(Pid, LFile),
- ok = ftp:delete(Pid, LFile),
- ok = check_content(binary_to_list(Bin2), Contents, singel),
- ok.
-
-do_send_bin(Pid, Config) ->
- File = ?config(file, Config),
- Contents = "ftp_SUITE test ...",
- 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),
- true = lists:member(File, RFiles),
- ok = ftp:delete(Pid, File),
- ok.
-
-do_append_bin(Pid, Config) ->
- File = ?config(file, Config),
- Contents = "ftp_SUITE test ...",
- 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
- {ok, Bin2} = ftp:recv_bin(Pid, File),
- ok = ftp:delete(Pid,File),
- ok = check_content(binary_to_list(Bin2),binary_to_list(Bin), double).
-
-do_send_chunk(Pid, Config) ->
- File = ?config(file, 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),
- ok = ftp:send_chunk(Pid, Bin),
- ok = ftp:send_chunk(Pid, Bin),
- ok = ftp:send_chunk_end(Pid),
- {ok, RFilesString} = ftp:nlist(Pid),
- RFiles = split(RFilesString),
- true = lists:member(File, RFiles),
- ok = ftp:delete(Pid, File),
- ok.
-
-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))),
- ok = ftp:append_chunk(Pid,list_to_binary(lists:nth(2,Contents))),
- ok = ftp:append_chunk(Pid,list_to_binary(lists:nth(3,Contents))),
- ok = ftp:append_chunk_end(Pid),
- %%Control the contents of the file
- {ok, Bin2} = ftp:recv_bin(Pid, File),
- ok = check_content(binary_to_list(Bin2),"ERL", double),
- ok = ftp:delete(Pid, File),
- ok.
-
-do_recv(Pid, Config) ->
- PrivDir = ?config(priv_dir, Config),
- File = ?config(file, Config),
- Newfile = ?config(new_file, Config),
- AbsFile = filename:absname(File, PrivDir),
- Contents = "ftp_SUITE:recv test ...",
- ok = file:write_file(AbsFile, list_to_binary(Contents)),
- ok = ftp:cd(Pid, "incoming"),
- ftp:delete(Pid, File), % reset
- ftp:lcd(Pid, PrivDir),
- ok = ftp:send(Pid, File),
- 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),
- ok = file:delete(AbsFile), % cleanup
- ok = ftp:recv(Pid, File, Newfile),
- ok = ftp:delete(Pid, File), % cleanup
- ok.
-
-do_recv_bin(Pid, Config) ->
- File = ?config(file, Config),
- Contents1 = "ftp_SUITE test ...",
- Bin1 = list_to_binary(Contents1),
- 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),
- Contents1 = Contents2,
- ok.
-
-do_recv_chunk(Pid, Config) ->
- File = ?config(file, Config),
- Data = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"
- "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"
- "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
-
- Contents1 = lists:flatten(lists:duplicate(10, Data)),
- Bin1 = list_to_binary(Contents1),
- ok = ftp:cd(Pid, "incoming"),
- ok = ftp:type(Pid, binary),
- 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
- ok = find_diff(Contents2, Contents1, 1),
- ok.
-
-do_type(Pid) ->
- ok = ftp:type(Pid, ascii),
- ok = ftp:type(Pid, binary),
- ok = ftp:type(Pid, ascii),
- {error, etype} = ftp:type(Pid, foobar),
- ok.
-
-do_quote(Pid) ->
- ["257 \"/\""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
- [_| _] = ftp:quote(Pid, "help"),
- %% This negativ test causes some ftp servers to hang. This test
- %% is not important for the client, so we skip it for now.
- %%["425 Can't build data connection: Connection refused."]
- %% = ftp:quote(Pid, "list"),
- ok.
-
- watch_dog(Config) ->
- Dog = test_server:timetrap(inets_test_lib:minutes(1)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- [{watchdog, Dog} | NewConfig].
-
- close_connection(Config) ->
- case ?config(ftp, Config) of
- Pid when is_pid(Pid) ->
- ok = ftp:close(Pid),
- lists:delete({ftp, Pid}, Config);
- _ ->
- Config
- end.
-
-ftp_host(Config) ->
- case ?config(ftp_remote_host, Config) of
- undefined ->
- exit({skip, "No host specified"});
- Host ->
- Host
- end.
-
-check_content(RContent, LContent, Amount) ->
- LContent2 = case Amount of
- double ->
- LContent ++ LContent;
- singel ->
- LContent
- end,
- case string:equal(RContent, LContent2) of
- true ->
- ok;
- false ->
- %% Find where the diff is
- Where = find_diff(RContent, LContent2, 1),
- Where
- end.
-
-find_diff(A, A, _) ->
- ok;
-find_diff([H|T1], [H|T2], Pos) ->
- find_diff(T1, T2, Pos+1);
-find_diff(RC, LC, Pos) ->
- {error, {diff, Pos, RC, LC}}.
-
-recv_chunk(Pid, Acc) ->
- case ftp:recv_chunk(Pid) of
- ok ->
- {ok, binary_to_list(Acc)};
- {ok, Bin} ->
- recv_chunk(Pid, <<Acc/binary, Bin/binary>>);
- Error ->
- Error
- end.
-
-split(Cs) ->
- split(Cs, [], []).
-
-split([$\r, $\n| Cs], I, Is) ->
- split(Cs, [], [lists:reverse(I)| Is]);
-split([C| Cs], I, Is) ->
- split(Cs, [C| I], Is);
-split([], I, Is) ->
- lists:reverse([lists:reverse(I)| Is]).
-
-do_ftp_open(Host, Opts) ->
- p("do_ftp_open -> entry with"
- "~n Host: ~p"
- "~n Opts: ~p", [Host, Opts]),
- case ftp:open(Host, Opts) of
- {ok, _} = OK ->
- OK;
- {error, Reason} ->
- Str =
- lists:flatten(
- io_lib:format("Unable to reach test FTP server ~p (~p)",
- [Host, Reason])),
- throw({skip, Str})
- end.
-
-
-passwd() ->
- Host =
- case inet:gethostname() of
- {ok, H} ->
- H;
- _ ->
- "localhost"
- end,
- "ftp_SUITE@" ++ Host.
-
-ftpd_hosts(Config) ->
- DataDir = ?config(data_dir, Config),
- FileName = filename:join([DataDir, "../ftp_SUITE_data/", ftpd_hosts]),
- p("FileName: ~p", [FileName]),
- case file:consult(FileName) of
- {ok, [Hosts]} when is_list(Hosts) ->
- Hosts;
- _ ->
- []
- end.
-
-wrapper(Prefix,doc,Func) ->
- Prefix++Func(doc);
-wrapper(_,X,Func) ->
- Func(X).
-
-data_dir(Config) ->
- case ?config(data_dir, Config) of
- List when (length(List) > 0) ->
- PathList = filename:split(List),
- {NewPathList,_} = lists:split((length(PathList)-1), PathList),
- DataDir = filename:join(NewPathList ++ [ftp_SUITE_data]),
- NewConfig =
- lists:keyreplace(data_dir,1,Config, {data_dir,DataDir}),
- NewConfig;
- _ -> Config
- end.
-
-
-
-p(F) ->
- p(F, []).
-
-p(F, A) ->
- case get(ftp_testcase) of
- undefined ->
- io:format("~w [~w] " ++ F ++ "~n", [?MODULE, self() | A]);
- TC when is_atom(TC) ->
- io:format("~w [~w] ~w:" ++ F ++ "~n", [?MODULE, self(), TC | A])
- end.
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index e977bd1b9b..647eff4f7c 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,13 +55,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_, Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- [{watchdog, Dog} | NewConfig].
+ Config.
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_, _) ->
ok.
%%-------------------------------------------------------------------------
@@ -539,8 +535,11 @@ esi_parse_headers(Config) when is_list(Config) ->
{"location","http://foo.bar.se"}], 302} =
httpd_esi:handle_headers(Headers2),
- {proceed,"/foo/bar.html"} =
- httpd_esi:handle_headers("location:/foo/bar.html\r\n").
+ {ok,[{"location","/foo/bar.html"}], 302} =
+ httpd_esi:handle_headers("location:/foo/bar.html\r\n"),
+
+ {ok,[{"location","http://foo/bar.html"}],201} =
+ httpd_esi:handle_headers("status:201 Created\r\nlocation:http://foo/bar.html\r\n").
%%--------------------------------------------------------------------
cgi_parse_headers() ->
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 93b96e101f..cc166d522e 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,9 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
- [{ct_hooks,[ts_install_cth]}].
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds, 30}}
+ ].
all() ->
[
@@ -67,6 +69,7 @@ real_requests()->
head,
get,
post,
+ delete,
post_stream,
patch,
async,
@@ -86,7 +89,8 @@ real_requests()->
stream_through_mfa,
streaming_error,
inet_opts,
- invalid_headers
+ invalid_headers,
+ invalid_body
].
only_simulated() ->
@@ -105,11 +109,13 @@ only_simulated() ->
tolerate_missing_CR,
userinfo,
bad_response,
+ timeout_redirect,
internal_server_error,
invalid_http,
invalid_chunk_size,
headers_dummy,
headers_with_obs_fold,
+ headers_conflict_chunked_with_length,
empty_response_header,
remote_socket_close,
remote_socket_close_async,
@@ -123,7 +129,10 @@ only_simulated() ->
redirect_see_other,
redirect_temporary_redirect,
port_in_host_header,
- relaxed
+ redirect_port_in_host_header,
+ relaxed,
+ multipart_chunks,
+ stream_fun_server_close
].
misc() ->
@@ -136,8 +145,8 @@ misc() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
inets_test_lib:start_apps([inets]),
ServerRoot = filename:join(PrivDir, "server_root"),
DocRoot = filename:join(ServerRoot, "htdocs"),
@@ -146,7 +155,7 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
inets_test_lib:stop_apps([inets]),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
inets_test_lib:del_dirs(PrivDir),
ok.
@@ -157,20 +166,16 @@ init_per_group(misc = Group, Config) ->
ok = httpc:set_options([{ipfamily, Inet}]),
Config;
+
init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
- start_apps(Group),
- StartSsl = try ssl:start()
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ start_apps(Group),
+ do_init_per_group(Group, Config0)
catch
- Error:Reason ->
- {skip, lists:flatten(io_lib:format("Failed to start apps for https Error=~p Reason=~p", [Error, Reason]))}
- end,
- case StartSsl of
- {error, {already_started, _}} ->
- do_init_per_group(Group, Config0);
- ok ->
- do_init_per_group(Group, Config0);
- _ ->
- StartSsl
+ _:_ ->
+ {skip, "Crypto did not start"}
end;
init_per_group(Group, Config0) ->
@@ -198,7 +203,15 @@ init_per_testcase(persistent_connection, Config) ->
{max_keep_alive_length, 3}], persistent_connection),
Config;
-
+init_per_testcase(wait_for_whole_response, Config) ->
+ ct:timetrap({seconds, 60*3}),
+ Config;
+init_per_testcase(Case, Config) when Case == post;
+ Case == delete;
+ Case == post_delete;
+ Case == post_stream ->
+ ct:timetrap({seconds, 30}),
+ Config;
init_per_testcase(_Case, Config) ->
Config.
@@ -256,6 +269,29 @@ post(Config) when is_list(Config) ->
{ok, {{_,504,_}, [_ | _], []}} =
httpc:request(post, {URL, [{"expect","100-continue"}],
"text/plain", "foobar"}, [], []).
+%%--------------------------------------------------------------------
+delete() ->
+ [{"Test http delete request against local server. We do in this case "
+ "only care about the client side of the the delete. The server "
+ "script will not actually use the delete data."}].
+delete(Config) when is_list(Config) ->
+ CGI = case test_server:os_type() of
+ {win32, _} ->
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ "/cgi-bin/cgi_echo"
+ end,
+
+ URL = url(group_name(Config), CGI, Config),
+ Body = lists:duplicate(100, "1"),
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(delete, {URL, [{"expect","100-continue"}],
+ "text/plain", Body}, [], []),
+
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(delete, {URL, [{"expect","100-continue"}],
+ "text/plain", "foobar"}, [], []).
%%--------------------------------------------------------------------
patch() ->
@@ -332,7 +368,7 @@ pipeline(Config) when is_list(Config) ->
{ok, _} = httpc:request(get, Request, [], [], pipeline),
%% Make sure pipeline session is registerd
- test_server:sleep(4000),
+ ct:sleep(4000),
keep_alive_requests(Request, pipeline).
%%--------------------------------------------------------------------
@@ -342,7 +378,7 @@ persistent_connection(Config) when is_list(Config) ->
{ok, _} = httpc:request(get, Request, [], [], persistent),
%% Make sure pipeline session is registerd
- test_server:sleep(4000),
+ ct:sleep(4000),
keep_alive_requests(Request, persistent).
%%-------------------------------------------------------------------------
@@ -370,7 +406,7 @@ async(Config) when is_list(Config) ->
save_to_file() ->
[{doc, "Test to save the http body to a file"}].
save_to_file(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FilePath = filename:join(PrivDir, "dummy.html"),
URL = url(group_name(Config), "/dummy.html", Config),
Request = {URL, []},
@@ -384,7 +420,7 @@ save_to_file(Config) when is_list(Config) ->
save_to_file_async() ->
[{doc,"Test to save the http body to a file"}].
save_to_file_async(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
FilePath = filename:join(PrivDir, "dummy.html"),
URL = url(group_name(Config), "/dummy.html", Config),
Request = {URL, []},
@@ -465,10 +501,11 @@ redirect_multiple_choises(Config) when is_list(Config) ->
httpc:request(get, {URL300, []}, [{autoredirect, false}], []).
%%-------------------------------------------------------------------------
redirect_moved_permanently() ->
- [{doc, "If the 301 status code is received in response to a request other "
- "than GET or HEAD, the user agent MUST NOT automatically redirect the request "
- "unless it can be confirmed by the user, since this might change "
- "the conditions under which the request was issued."}].
+ [{doc, "The server SHOULD generate a Location header field in the response "
+ "containing a preferred URI reference for the new permanent URI. The user "
+ "agent MAY use the Location field value for automatic redirection. The server's "
+ "response payload usually contains a short hypertext note with a "
+ "hyperlink to the new URI(s)."}].
redirect_moved_permanently(Config) when is_list(Config) ->
URL301 = url(group_name(Config), "/301.html", Config),
@@ -479,15 +516,16 @@ redirect_moved_permanently(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], []}}
= httpc:request(head, {URL301, []}, [], []),
- {ok, {{_,301,_}, [_ | _], [_|_]}}
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
= httpc:request(post, {URL301, [],"text/plain", "foobar"},
[], []).
%%-------------------------------------------------------------------------
redirect_found() ->
- [{doc," If the 302 status code is received in response to a request other "
- "than GET or HEAD, the user agent MUST NOT automatically redirect the "
- "request unless it can be confirmed by the user, since this might change "
- "the conditions under which the request was issued."}].
+ [{doc, "The server SHOULD generate a Location header field in the response "
+ "containing a URI reference for the different URI. The user agent MAY "
+ "use the Location field value for automatic redirection. The server's "
+ "response payload usually contains a short hypertext note with a "
+ "hyperlink to the different URI(s)."}].
redirect_found(Config) when is_list(Config) ->
URL302 = url(group_name(Config), "/302.html", Config),
@@ -498,14 +536,14 @@ redirect_found(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], []}}
= httpc:request(head, {URL302, []}, [], []),
- {ok, {{_,302,_}, [_ | _], [_|_]}}
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
= httpc:request(post, {URL302, [],"text/plain", "foobar"},
[], []).
%%-------------------------------------------------------------------------
redirect_see_other() ->
[{doc, "The different URI SHOULD be given by the Location field in the response. "
"Unless the request method was HEAD, the entity of the response SHOULD contain a short "
- "hypertext note with a hyperlink to the new URI(s). "}].
+ "hypertext note with a hyperlink to the new URI(s)."}].
redirect_see_other(Config) when is_list(Config) ->
URL303 = url(group_name(Config), "/303.html", Config),
@@ -521,10 +559,11 @@ redirect_see_other(Config) when is_list(Config) ->
[], []).
%%-------------------------------------------------------------------------
redirect_temporary_redirect() ->
- [{doc," If the 307 status code is received in response to a request other "
- "than GET or HEAD, the user agent MUST NOT automatically redirect the request "
- "unless it can be confirmed by the user, since this might change "
- "the conditions under which the request was issued."}].
+ [{doc, "The server SHOULD generate a Location header field in the response "
+ "containing a URI reference for the different URI. The user agent MAY "
+ "use the Location field value for automatic redirection. The server's "
+ "response payload usually contains a short hypertext note with a "
+ "hyperlink to the different URI(s)."}].
redirect_temporary_redirect(Config) when is_list(Config) ->
URL307 = url(group_name(Config), "/307.html", Config),
@@ -535,7 +574,7 @@ redirect_temporary_redirect(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], []}}
= httpc:request(head, {URL307, []}, [], []),
- {ok, {{_,307,_}, [_ | _], [_|_]}}
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
= httpc:request(post, {URL307, [],"text/plain", "foobar"},
[], []).
@@ -708,7 +747,7 @@ empty_body() ->
empty_body(Config) when is_list(Config) ->
URL = url(group_name(Config), "/empty.html", Config),
{ok, {{_,200,_}, [_ | _], []}} =
- httpc:request(get, {URL, []}, [{timeout, 500}], []).
+ httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
@@ -748,6 +787,14 @@ bad_response(Config) when is_list(Config) ->
ct:print("Wrong Statusline: ~p~n", [Reason]).
%%-------------------------------------------------------------------------
+timeout_redirect() ->
+ [{doc, "Test that timeout works for redirects, check ERL-420."}].
+timeout_redirect(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/redirect_to_missing_crlf.html", Config),
+ {error, timeout} = httpc:request(get, {URL, []}, [{timeout, 400}], []).
+
+%%-------------------------------------------------------------------------
+
internal_server_error(doc) ->
["Test 50X codes"];
internal_server_error(Config) when is_list(Config) ->
@@ -844,7 +891,7 @@ headers() ->
headers(Config) when is_list(Config) ->
URL = url(group_name(Config), "/dummy.html", Config),
- DocRoot = ?config(doc_root, Config),
+ DocRoot = proplists:get_value(doc_root, Config),
{ok, FileInfo} =
file:read_file_info(filename:join([DocRoot,"dummy.html"])),
@@ -932,7 +979,6 @@ headers_dummy(Config) when is_list(Config) ->
{"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
{"If-Match", "*"},
{"Content-Type", "text/plain"},
- {"Content-Encoding", "chunked"},
{"Content-Length", "6"},
{"Content-Language", "en"},
{"Content-Location", "http://www.foobar.se"},
@@ -958,14 +1004,41 @@ headers_with_obs_fold(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+headers_conflict_chunked_with_length(doc) ->
+ ["Test the code for handling headers with both Transfer-Encoding"
+ "and Content-Length which must receive error in default (not relaxed) mode"
+ "and must receive successful response in relaxed mode"];
+headers_conflict_chunked_with_length(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/headers_conflict_chunked_with_length.html", Config), []},
+ {error, {could_not_parse_as_http, _}} = httpc:request(get, Request, [{relaxed, false}], []),
+ {ok,{{_,200,_},_,_}} = httpc:request(get, Request, [{relaxed, true}], []),
+ ok.
+
+%%-------------------------------------------------------------------------
+
invalid_headers(Config) ->
Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]},
{error, _} = httpc:request(get, Request, [], []).
+%%-------------------------------------------------------------------------
+
+invalid_body(Config) ->
+ URL = url(group_name(Config), "/dummy.html", Config),
+ try
+ httpc:request(post, {URL, [], <<"text/plain">>, "foobar"},
+ [], []),
+ ct:fail(accepted_invalid_input)
+ catch
+ error:function_clause ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
remote_socket_close(Config) when is_list(Config) ->
URL = url(group_name(Config), "/just_close.html", Config),
{error, socket_closed_remotely} = httpc:request(URL).
+
%%-------------------------------------------------------------------------
remote_socket_close_async(Config) when is_list(Config) ->
@@ -1064,8 +1137,21 @@ port_in_host_header(Config) when is_list(Config) ->
Request = {url(group_name(Config), "/ensure_host_header_with_port.html", Config), []},
{ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
inets_test_lib:check_body(Body).
+%%-------------------------------------------------------------------------
+redirect_port_in_host_header(Config) when is_list(Config) ->
+
+ Request = {url(group_name(Config), "/redirect_ensure_host_header_with_port.html", Config), []},
+ {ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
+ inets_test_lib:check_body(Body).
%%-------------------------------------------------------------------------
+multipart_chunks(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/multipart_chunks.html", Config), []},
+ {ok, Ref} = httpc:request(get, Request, [], [{sync, false}, {stream, self}]),
+ ok = receive_stream_n(Ref, 10),
+ httpc:cancel_request(Ref).
+
+%%-------------------------------------------------------------------------
timeout_memory_leak() ->
[{doc, "Check OTP-8739"}].
timeout_memory_leak(Config) when is_list(Config) ->
@@ -1105,6 +1191,22 @@ wait_for_whole_response(Config) when is_list(Config) ->
ReqSeqNumServer ! shutdown.
%%--------------------------------------------------------------------
+stream_fun_server_close() ->
+ [{doc, "Test that an error msg is received when using a receiver fun as stream target"}].
+stream_fun_server_close(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/delay_close.html", Config), []},
+ Self = self(),
+ Fun = fun(X) -> Self ! X end,
+ {ok, RequestId} = httpc:request(get, Request, [], [{sync, false}, {receiver, Fun}]),
+ receive
+ {RequestId, {error, Reason}} ->
+ ct:pal("Close ~p", [Reason]),
+ ok
+ after 13000 ->
+ ct:fail(did_not_receive_close)
+ end.
+
+%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
stream(ReceiverPid, Receiver, Config) ->
@@ -1188,11 +1290,11 @@ not_streamed_test(Request, To) ->
end.
url(http, End, Config) ->
- Port = ?config(port, Config),
+ Port = proplists:get_value(port, Config),
{ok,Host} = inet:gethostname(),
?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
url(https, End, Config) ->
- Port = ?config(port, Config),
+ Port = proplists:get_value(port, Config),
{ok,Host} = inet:gethostname(),
?TLS_URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
url(sim_http, End, Config) ->
@@ -1200,10 +1302,10 @@ url(sim_http, End, Config) ->
url(sim_https, End, Config) ->
url(https, End, Config).
url(http, UserInfo, End, Config) ->
- Port = ?config(port, Config),
+ Port = proplists:get_value(port, Config),
?URL_START ++ UserInfo ++ integer_to_list(Port) ++ End;
url(https, UserInfo, End, Config) ->
- Port = ?config(port, Config),
+ Port = proplists:get_value(port, Config),
?TLS_URL_START ++ UserInfo ++ integer_to_list(Port) ++ End;
url(sim_http, UserInfo, End, Config) ->
url(http, UserInfo, End, Config);
@@ -1211,7 +1313,7 @@ url(sim_https, UserInfo, End, Config) ->
url(https, UserInfo, End, Config).
group_name(Config) ->
- GroupProp = ?config(tc_group_properties, Config),
+ GroupProp = proplists:get_value(tc_group_properties, Config),
proplists:get_value(name, GroupProp).
server_start(sim_http, _) ->
@@ -1233,11 +1335,11 @@ server_start(_, HttpdConfig) ->
proplists:get_value(port, Info).
server_config(http, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
[{port, 0},
{server_name,"httpc_test"},
{server_root, ServerRoot},
- {document_root, ?config(doc_root, Config)},
+ {document_root, proplists:get_value(doc_root, Config)},
{bind_address, any},
{ipfamily, inet_version()},
{mime_type, "text/plain"},
@@ -1259,7 +1361,7 @@ start_apps(_) ->
ok.
ssl_config(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
[{certfile, filename:join(DataDir, "ssl_server_cert.pem")},
{verify, verify_none}
].
@@ -1360,7 +1462,7 @@ dummy_server(Caller, SocketType, Inet, Extra) ->
end.
dummy_server_init(Caller, ip_comm, Inet, _) ->
- BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}],
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {keepalive, true}, {active, false}],
{ok, ListenSocket} = gen_tcp:listen(0, [Inet | BaseOpts]),
{ok, Port} = inet:port(ListenSocket),
Caller ! {port, Port},
@@ -1642,6 +1744,12 @@ handle_uri(_,"/ensure_host_header_with_port.html",_,Headers,_,_) ->
"HTTP/1.1 500 Internal Server Error\r\n" ++
"Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
end;
+handle_uri(_,"/redirect_ensure_host_header_with_port.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/ensure_host_header_with_port.html",
+ "HTTP/1.1 302 Found \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
handle_uri(_,"/300.html",Port,_,Socket,_) ->
NewUri = url_start(Socket) ++
@@ -1773,7 +1881,6 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) ->
%% user to evaluate. This is not a valid response
%% it only tests that the header handling code works.
Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n" ++
"Pragma:1#no-cache\r\n" ++
"Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
"Warning:1#pseudonym foobar\r\n" ++
@@ -1803,6 +1910,15 @@ handle_uri(_,"/obs_folded_headers.html",_,_,_,_) ->
" b\r\n\r\n"
"Hello";
+handle_uri(_,"/headers_conflict_chunked_with_length.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n"
+ "Content-Length:32\r\n"
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+
handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Transfer-Encoding:Chunked\r\n\r\n",
@@ -1844,6 +1960,16 @@ handle_uri(_,"/missing_crlf.html",_,_,_,_) ->
"Content-Length:32\r\n" ++
"<HTML><BODY>foobar</BODY></HTML>";
+handle_uri(_,"/redirect_to_missing_crlf.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/missing_crlf.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 303 See Other \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
handle_uri(_,"/wrong_statusline.html",_,_,_,_) ->
"ok 200 HTTP/1.1\r\n\r\n" ++
"Content-Length:32\r\n\r\n" ++
@@ -1907,9 +2033,9 @@ handle_uri(_,"/once.html",_,_,Socket,_) ->
"Content-Length:32\r\n\r\n",
send(Socket, Head),
send(Socket, "<HTML><BODY>fo"),
- test_server:sleep(1000),
+ ct:sleep(1000),
send(Socket, "ob"),
- test_server:sleep(1000),
+ ct:sleep(1000),
send(Socket, "ar</BODY></HTML>");
handle_uri(_,"/invalid_http.html",_,_,_,_) ->
@@ -1930,6 +2056,19 @@ handle_uri(_,"/missing_CR.html",_,_,_,_) ->
"Content-Length:32\r\n\n" ++
"<HTML><BODY>foobar</BODY></HTML>";
+handle_uri(_,"/multipart_chunks.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:chunked\r\n" ++
+ "Date: " ++ httpd_util:rfc1123_date() ++ "\r\n"
+ "Connection: Keep-Alive\r\n" ++
+ "Content-Type: multipart/x-mixed-replace; boundary=chunk_boundary\r\n" ++
+ "\r\n",
+ send(Socket, Head),
+ send_multipart_chunks(Socket),
+ http_chunk:encode_last();
+handle_uri(_,"/delay_close.html",_,_,Socket,_) ->
+ ct:sleep(10000),
+ close(Socket);
handle_uri("HEAD",_,_,_,_,_) ->
"HTTP/1.1 200 ok\r\n" ++
"Content-Length:0\r\n\r\n";
@@ -2045,7 +2184,7 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
end
end),
MRef = erlang:monitor(process, Pid),
- timer:sleep(10 + random:uniform(1334)),
+ timer:sleep(10 + rand:uniform(1334)),
{Id, Pid, MRef}
end,
lists:seq(1, NumClients)).
@@ -2053,7 +2192,7 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
wait4clients([], _Timeout) ->
ok;
wait4clients(Clients, Timeout) when Timeout > 0 ->
- Time = inets_time_compat:monotonic_time(),
+ Time = erlang:monotonic_time(),
receive
{'DOWN', _MRef, process, Pid, normal} ->
@@ -2134,7 +2273,7 @@ slowly_send_response(CSock, Answer) ->
[length(Answer), Answer])),
lists:foreach(
fun(Char) ->
- timer:sleep(random:uniform(500)),
+ timer:sleep(rand:uniform(500)),
gen_tcp:send(CSock, <<Char>>)
end,
Response).
@@ -2153,10 +2292,9 @@ parse_connection_type(Request) ->
end.
set_random_seed() ->
- Unique = inets_time_compat:unique_integer(),
-
+ Unique = erlang:unique_integer(),
A = erlang:phash2([make_ref(), self(), Unique]),
- random:seed(A, A, A).
+ rand:seed(exsplus, {A, A, A}).
otp_8739(doc) ->
@@ -2227,3 +2365,21 @@ otp_8739_dummy_server_main(_Parent, ListenSocket) ->
Error ->
exit(Error)
end.
+
+send_multipart_chunks(Socket) ->
+ send(Socket, http_chunk:encode("--chunk_boundary\r\n")),
+ send(Socket, http_chunk:encode("Content-Type: text/plain\r\nContent-Length: 4\r\n\r\n")),
+ send(Socket, http_chunk:encode("test\r\n")),
+ ct:sleep(500),
+ send_multipart_chunks(Socket).
+
+receive_stream_n(_, 0) ->
+ ok;
+receive_stream_n(Ref, N) ->
+ receive
+ {http, {Ref, stream_start, _}} ->
+ receive_stream_n(Ref, N);
+ {http, {Ref,stream, Data}} ->
+ ct:pal("Data: ~p", [Data]),
+ receive_stream_n(Ref, N-1)
+ end.
diff --git a/lib/inets/test/httpc_cookie_SUITE.erl b/lib/inets/test/httpc_cookie_SUITE.erl
index 9a62bdb43f..8140967bca 100644
--- a/lib/inets/test/httpc_cookie_SUITE.erl
+++ b/lib/inets/test/httpc_cookie_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,17 +20,11 @@
%%
-module(httpc_cookie_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]).
-
-%% Test cases must be exported.
--export([session_cookies_only/1, netscape_cookies/1,
- cookie_cancel/1, cookie_expires/1, persistent_cookie/1,
- domain_cookie/1, secure_cookie/1, update_cookie/1,
- update_cookie_session/1, cookie_attributes/1]).
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
-define(URL, "http://myhost.cookie.test.org").
-define(URL_DOMAIN, "http://myhost2.cookie.test.org").
@@ -38,86 +32,10 @@
%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, 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.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(session_cookies_only = Case, Config0) ->
- tsp("init_per_testcase(~p) -> entry with"
- "~n Config0: ~p", [Case, Config0]),
- Config = init_workdir(Case, Config0),
- application:start(inets),
- httpc:set_options([{cookies, verify}]),
- watch_dog(Config);
-
-init_per_testcase(Case, Config0) ->
- tsp("init_per_testcase(~p) -> entry with"
- "~n Config0: ~p", [Case, Config0]),
- Config = init_workdir(Case, Config0),
- CaseDir = ?config(case_top_dir, Config),
- application:load(inets),
- application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
- application:start(inets),
- httpc:set_options([{cookies, verify}]),
- watch_dog(Config).
-
-watch_dog(Config) ->
- Dog = test_server:timetrap(inets_test_lib:minutes(10)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- [{watchdog, Dog} | NewConfig].
-
-init_workdir(Case, Config) ->
- PrivDir = ?config(priv_dir, Config),
- SuiteTopDir = filename:join(PrivDir, ?MODULE),
- case file:make_dir(SuiteTopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- tsf({failed_creating_subsuite_top_dir, Error})
- end,
-
- CaseTopDir = filename:join(SuiteTopDir, Case),
- ?line ok = file:make_dir(CaseTopDir),
- [{suite_top_dir, SuiteTopDir},
- {case_top_dir, CaseTopDir} | Config].
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, 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) ->
- tsp("end_per_testcase(~p) -> entry with"
- "~n Config: ~p", [Case, Config]),
- application:stop(inets),
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,15}}
+ ].
all() ->
[
@@ -148,17 +66,55 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(session_cookies_only = Case, Config0) ->
+ Config = init_workdir(Case, Config0),
+ application:start(inets),
+ httpc:set_options([{cookies, verify}]),
+ Config;
+init_per_testcase(cookie_expires = Case, Config0) ->
+ Config = init_workdir(Case, Config0),
+ CaseDir = proplists:get_value(case_top_dir, Config),
+ application:start(inets),
+ application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
+ application:start(inets),
+ httpc:set_options([{cookies, verify}]),
+ Config;
+init_per_testcase(Case, Config0) ->
+ Config = init_workdir(Case, Config0),
+ CaseDir = proplists:get_value(case_top_dir, Config),
+ application:load(inets),
+ application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
+ application:start(inets),
+ httpc:set_options([{cookies, verify}]),
+ Config.
+
+init_workdir(Case, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SuiteTopDir = filename:join(PrivDir, ?MODULE),
+ case file:make_dir(SuiteTopDir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ Error ->
+ ct:fail({failed_creating_subsuite_top_dir, Error})
+ end,
+
+ CaseTopDir = filename:join(SuiteTopDir, Case),
+ ok = file:make_dir(CaseTopDir),
+ [{suite_top_dir, SuiteTopDir},
+ {case_top_dir, CaseTopDir} | Config].
+
+end_per_testcase(_, _) ->
+ application:stop(inets).
+
%% Test cases starts here.
%%--------------------------------------------------------------------
-session_cookies_only(doc) ->
- ["Test that all cookies are handled as session cookies if there"
- "does not exist a directory to save presitent cookies in."];
-session_cookies_only(suite) ->
- [];
+session_cookies_only() ->
+ [{doc, "Test that all cookies are handled as session cookies if there"
+ "does not exist a directory to save presitent cookies in."}].
session_cookies_only(Config) when is_list(Config) ->
- tsp("session_cookies_only -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
";max-age=60000"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
@@ -166,36 +122,22 @@ session_cookies_only(Config) when is_list(Config) ->
httpc:cookie_header(?URL),
application:stop(inets),
application:start(inets),
- {"cookie", ""} = httpc:cookie_header(?URL),
-
- tsp("session_cookies_only -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
+ {"cookie", ""} = httpc:cookie_header(?URL).
-netscape_cookies(doc) ->
- ["Test that the old (original) format of cookies are accepted."];
-netscape_cookies(suite) ->
- [];
+netscape_cookies() ->
+ [{doc, "Test that the old (original) format of cookies are accepted."}].
netscape_cookies(Config) when is_list(Config) ->
- tsp("netscape_cookies -> Cookies 1: ~p", [httpc:which_cookies()]),
-
Expires = future_netscape_date(),
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; "
"expires=" ++ Expires}],
httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie", "$Version=0; test_cookie=true; $Path=/"} =
- httpc:cookie_header(?URL),
+ httpc:cookie_header(?URL).
- tsp("netscape_cookies -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
-
-cookie_cancel(doc) ->
- ["A cookie can be canceld by sending the same cookie with max-age=0 "
- "this test cheks that cookie is canceled."];
-cookie_cancel(suite) ->
- [];
+cookie_cancel() ->
+ [{doc, "A cookie can be canceld by sending the same cookie with max-age=0 "
+ "this test cheks that cookie is canceled."}].
cookie_cancel(Config) when is_list(Config) ->
- tsp("cookie_cancel -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
@@ -204,155 +146,60 @@ cookie_cancel(Config) when is_list(Config) ->
NewSetCookieHeaders =
[{"set-cookie", "test_cookie=true; path=/;max-age=0"}],
httpc:store_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", ""} = httpc:cookie_header(?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL).
- tsp("cookie_cancel -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
-
-cookie_expires(doc) ->
- ["Test that a cookie is not used when it has expired"];
-cookie_expires(suite) ->
- [];
+cookie_expires() ->
+ [{doc, "Test that a cookie is not used when it has expired"}].
cookie_expires(Config) when is_list(Config) ->
- tsp("cookie_expires -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=5"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie", "$Version=0; test_cookie=true; $Path=/"} =
httpc:cookie_header(?URL),
- test_server:sleep(10000),
- {"cookie", ""} = httpc:cookie_header(?URL),
+ timer:sleep(10000),
+ {"cookie", ""} = httpc:cookie_header(?URL).
- tsp("cookie_expires -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
-
-persistent_cookie(doc) ->
- ["Test domian cookie attribute"];
-persistent_cookie(suite) ->
- [];
+persistent_cookie() ->
+ [{doc, "Test domian cookie attribute"}].
persistent_cookie(Config) when is_list(Config)->
- tsp("persistent_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie", "$Version=0; test_cookie=true; $Path=/"} =
httpc:cookie_header(?URL),
- CaseDir = ?config(case_top_dir, Config),
+ CaseDir = proplists:get_value(case_top_dir, Config),
application:stop(inets),
application:load(inets),
application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
application:start(inets),
httpc:set_options([{cookies, enabled}]),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} = httpc:cookie_header(?URL),
+ {"cookie","$Version=0; test_cookie=true; $Path=/"} = httpc:cookie_header(?URL).
- tsp("persistent_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
-
-
-domain_cookie(doc) ->
- ["Test the domian cookie attribute"];
-domain_cookie(suite) ->
- [];
+domain_cookie() ->
+ [{doc, "Test the domian cookie attribute"}].
domain_cookie(Config) when is_list(Config) ->
- tsp("domain_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"domain=.cookie.test.org"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie","$Version=0; test_cookie=true; $Path=/; "
"$Domain=.cookie.test.org"} =
- httpc:cookie_header(?URL_DOMAIN),
+ httpc:cookie_header(?URL_DOMAIN).
- tsp("domain_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
- ok.
-
-
-secure_cookie(doc) ->
- ["Test the secure cookie attribute"];
-secure_cookie(suite) ->
- [];
+secure_cookie() ->
+ [{doc, "Test the secure cookie attribute"}].
secure_cookie(Config) when is_list(Config) ->
- tsp("secure_cookie -> entry with"
- "~n Config: ~p", [Config]),
-
- %% httpc:reset_cookies(),
-
- tsp("secure_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
-
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; secure"}],
- tsp("secure_cookie -> store cookies (1)"),
ok = httpc:store_cookies(SetCookieHeaders, ?URL),
-
- tsp("secure_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
-
- tsp("secure_cookie -> check cookie (secure)"),
check_cookie("$Version=0; test_cookie=true; $Path=/", ?URL_SECURE),
-
- tsp("secure_cookie -> check cookie (plain)"),
check_cookie("", ?URL),
-
- tsp("secure_cookie -> store cookies (2)"),
SetCookieHeaders1 = [{"set-cookie", "test1_cookie=true; path=/; secure"}],
ok = httpc:store_cookies(SetCookieHeaders1, ?URL),
-
- tsp("secure_cookie -> Cookies 3: ~p", [httpc:which_cookies()]),
-
- tsp("secure_cookie -> cookie header (3)"),
check_cookie("$Version=0; test_cookie=true; $Path=/; "
"test1_cookie=true; $Path=/",
- ?URL_SECURE),
-%% {"cookie","$Version=0; test_cookie=true; $Path=/; "
-%% "test1_cookie=true; $Path=/"} = httpc:cookie_header(?URL_SECURE),
-
- tsp("secure_cookie -> Cookies 4: ~p", [httpc:which_cookies()]),
-
- tsp("secure_cookie -> done"),
- ok.
+ ?URL_SECURE).
-expect_cookie_header(No, ExpectedCookie) ->
- case httpc:cookie_header(?URL) of
- {"cookie", ExpectedCookie} ->
- ok;
- {"cookie", BadCookie} ->
- io:format("Bad Cookie ~w: "
- "~n Expected: ~s"
- "~n Received: ~s"
- "~n", [No, ExpectedCookie, BadCookie]),
- exit({bad_cookie_header, No, ExpectedCookie, BadCookie})
- end.
-
-print_cookies(Pre) ->
- io:format("~s: ", [Pre]),
- print_cookies2(httpc:which_cookies()).
-
-print_cookies2([]) ->
- ok;
-print_cookies2([{cookies, Cookies}|Rest]) ->
- print_cookies3("Cookies", Cookies),
- print_cookies2(Rest);
-print_cookies2([{session_cookies, Cookies}|Rest]) ->
- print_cookies3("Session Cookies", Cookies),
- print_cookies2(Rest);
-print_cookies2([_|Rest]) ->
- print_cookies2(Rest).
-
-print_cookies3(Header, []) ->
- io:format(" ~s: []", [Header]);
-print_cookies3(Header, Cookies) ->
- io:format(" ~s: ", [Header]),
- Prefix = " ",
- PrintCookie =
- fun(Cookie) ->
- io:format("~s", [httpc_cookie:image_of(Prefix, Cookie)])
- end,
- lists:foreach(PrintCookie, Cookies).
-
-update_cookie(doc)->
- ["Test that a (plain) cookie can be updated."];
-update_cookie(suite) ->
- [];
+update_cookie()->
+ [{doc, "Test that a (plain) cookie can be updated."}].
update_cookie(Config) when is_list(Config) ->
print_cookies("Cookies before store"),
@@ -377,10 +224,8 @@ update_cookie(Config) when is_list(Config) ->
"test_cookie=false; $Path=/",
expect_cookie_header(2, ExpectCookie2).
-update_cookie_session(doc)->
- ["Test that a session cookie can be updated."];
-update_cookie_session(suite) ->
- [];
+update_cookie_session()->
+ [{doc, "Test that a session cookie can be updated."}].
update_cookie_session(Config) when is_list(Config)->
print_cookies("Cookies before store"),
@@ -400,23 +245,57 @@ update_cookie_session(Config) when is_list(Config)->
expect_cookie_header(2, ExpectedCookie2).
-cookie_attributes(doc) ->
- ["Test attribute not covered by the other test cases"];
-cookie_attributes(suite) ->
- [];
+cookie_attributes() ->
+ [{doc, "Test attribute not covered by the other test cases"}].
cookie_attributes(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true;version=1;"
"comment=foobar; "%% Comment
"foo=bar;" %% Nonsense should be ignored
"max-age=60000"}],
httpc:store_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=1; test_cookie=true"} = httpc:cookie_header(?URL),
- ok.
+ {"cookie","$Version=1; test_cookie=true"} = httpc:cookie_header(?URL).
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+print_cookies(Pre) ->
+ io:format("~s: ", [Pre]),
+ print_cookies2(httpc:which_cookies()).
+
+print_cookies2([]) ->
+ ok;
+print_cookies2([{cookies, Cookies}|Rest]) ->
+ print_cookies3("Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([{session_cookies, Cookies}|Rest]) ->
+ print_cookies3("Session Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([_|Rest]) ->
+ print_cookies2(Rest).
+
+print_cookies3(Header, []) ->
+ io:format(" ~s: []", [Header]);
+print_cookies3(Header, Cookies) ->
+ io:format(" ~s: ", [Header]),
+ Prefix = " ",
+ PrintCookie =
+ fun(Cookie) ->
+ io:format("~s", [httpc_cookie:image_of(Prefix, Cookie)])
+ end,
+ lists:foreach(PrintCookie, Cookies).
+
+expect_cookie_header(No, ExpectedCookie) ->
+ case httpc:cookie_header(?URL) of
+ {"cookie", ExpectedCookie} ->
+ ok;
+ {"cookie", BadCookie} ->
+ io:format("Bad Cookie ~w: "
+ "~n Expected: ~s"
+ "~n Received: ~s"
+ "~n", [No, ExpectedCookie, BadCookie]),
+ exit({bad_cookie_header, No, ExpectedCookie, BadCookie})
+ end.
check_cookie(Expect, URL) ->
case httpc:cookie_header(URL) of
@@ -426,12 +305,12 @@ check_cookie(Expect, URL) ->
case lists:prefix(Expect, Unexpected) of
true ->
Extra = Unexpected -- Expect,
- tsf({extra_cookie_info, Extra});
+ ct:fail({extra_cookie_info, Extra});
false ->
- tsf({unknown_cookie, Expect, Unexpected})
+ ct:fail({unknown_cookie, Expect, Unexpected})
end;
Bad ->
- tsf({bad_cookies, Bad})
+ ct:fail({bad_cookies, Bad})
end.
@@ -509,11 +388,3 @@ month_str(11) ->"Nov";
month_str(12) ->"Dec".
-tsp(F) ->
- tsp(F, []).
-tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
-
-tsf(Reason) ->
- test_server:fail(Reason).
-
diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
index 6d7af4ea5d..198b245399 100644
--- a/lib/inets/test/httpc_proxy_SUITE.erl
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -141,7 +141,7 @@ end_per_testcase(_Case, Config) ->
%% internal functions
apps(_Case, Config) ->
- case ?config(protocol, Config) of
+ case proplists:get_value(protocol, Config) of
https ->
[ssl];
_ ->
@@ -438,7 +438,7 @@ header_value(Name, [{HeaderName,HeaderValue}|Headers]) ->
https_connect_error(doc) ->
["Error from CONNECT tunnel should be returned"];
https_connect_error(Config) when is_list(Config) ->
- {HttpServer,HttpPort} = ?config(http, Config),
+ {HttpServer,HttpPort} = proplists:get_value(http, Config),
Method = get,
%% using HTTPS scheme with HTTP port to trigger connection error
URL = "https://" ++ HttpServer ++ ":" ++
@@ -477,7 +477,7 @@ app_start(App, Config) ->
inets ->
application:stop(App),
ok = application:start(App),
- case ?config(proxy, Config) of
+ case proplists:get_value(proxy, Config) of
undefined -> ok;
{_,ProxySpec} ->
ok = httpc:set_options([{proxy,ProxySpec}])
@@ -495,7 +495,7 @@ app_stop(App) ->
application:stop(App).
make_cert_files(Alg, Prefix, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
CaInfo = {CaCert,_} = erl_make_certs:make_cert([{key,Alg}]),
{Cert,CertKey} = erl_make_certs:make_cert([{key,Alg},{issuer,CaInfo}]),
CaCertFile = filename:join(PrivDir, Prefix++"cacerts.pem"),
@@ -513,8 +513,8 @@ der_to_pem(File, Entries) ->
url(AbsPath, Config) ->
- Protocol = ?config(protocol, Config),
- {ServerName,ServerPort} = ?config(Protocol, Config),
+ Protocol = proplists:get_value(protocol, Config),
+ {ServerName,ServerPort} = proplists:get_value(Protocol, Config),
atom_to_list(Protocol) ++ "://" ++
ServerName ++ ":" ++ integer_to_list(ServerPort) ++
AbsPath.
@@ -548,8 +548,8 @@ init_local_proxy_string(String, Config) ->
|Config].
rcmd_local_proxy(Args, Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Script = filename:join(DataDir, ?LOCAL_PROXY_SCRIPT),
rcmd(Script, Args, [{cd,PrivDir}]).
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf b/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf
index 03f80aaf6d..b139c4ca51 100644
--- a/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf
+++ b/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2012. All Rights Reserved.
+## Copyright Ericsson AB 2012-2016. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh
index 473024ae63..e8b690a4a1 100755
--- a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh
+++ b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh
@@ -5,7 +5,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2012. All Rights Reserved.
+## Copyright Ericsson AB 2012-2016. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_1_0.erl b/lib/inets/test/httpd_1_0.erl
index 7535b148ae..f61dc3c3fd 100644
--- a/lib/inets/test/httpd_1_0.erl
+++ b/lib/inets/test/httpd_1_0.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index d3a1e3672a..ce9f7acc4d 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -233,14 +233,6 @@ trace(Type, Port, Host, Node)->
"Max-Forwards:2\r\n\r\n",
[{statuscode, 200}]).
head(Type, Port, Host, Node)->
- %% mod_include
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "HEAD /fsize.shtml HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "HEAD /fsize.shtml HTTP/1.1\r\nhost:" ++
- Host ++ "\r\n\r\n", [{statuscode, 200}]),
%% mod_esi
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"HEAD /cgi-bin/erl/httpd_example/newformat"
@@ -413,11 +405,11 @@ getRangeSize(Head)->
{multiPart, BoundaryString};
_X1 ->
case re:run(Head, ?CONTENT_RANGE "bytes=.*\r\n", [{capture, first}]) of
- {match, [{Start, Lenght}]} ->
+ {match, [{Start, Length}]} ->
%% Get the range data remove the fieldname and the
%% end of line.
RangeInfo = string:substr(Head, Start + 1 + 20,
- Lenght - (20 +2)),
+ Length - (20 +2)),
rangeSize(string:strip(RangeInfo));
_X2 ->
error
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 87c504af74..9a85c51d24 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,7 +46,9 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
- [{ct_hooks,[ts_install_cth]}].
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds, 120}}
+ ].
all() ->
[
@@ -71,6 +73,8 @@ all() ->
{group, http_reload},
{group, https_reload},
{group, http_mime_types},
+ {group, http_logging},
+ {group, http_post},
mime_types_format
].
@@ -94,8 +98,10 @@ groups() ->
{https_htaccess, [], [{group, htaccess}]},
{http_security, [], [{group, security}]},
{https_security, [], [{group, security}]},
+ {http_logging, [], [{group, logging}]},
{http_reload, [], [{group, reload}]},
{https_reload, [], [{group, reload}]},
+ {http_post, [], [{group, post}]},
{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, add_default]},
@@ -108,6 +114,7 @@ groups() ->
disturbing_1_0,
disturbing_0_9
]},
+ {post, [], [chunked_post, chunked_chunked_encoded_post]},
{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
]},
@@ -117,8 +124,12 @@ groups() ->
]},
{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, mod_esi_chunk_timeout] ++ http_head() ++ http_get() ++ load()},
+ {logging, [], [disk_log_internal, disk_log_exists,
+ disk_log_bad_size, disk_log_bad_file]},
+ {http_1_1, [],
+ [host, chunked, expect, cgi, cgi_chunked_encoding_test,
+ trace, range, if_modified_since, mod_esi_chunk_timeout,
+ esi_put, esi_post] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
{http_0_9, [], http_head() ++ http_get() ++ load()}
].
@@ -144,14 +155,15 @@ http_get() ->
ipv6
].
+
load() ->
[light, medium
%%,heavy
].
init_per_suite(Config) ->
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
inets_test_lib:stop_apps([inets]),
ServerRoot = filename:join(PrivDir, "server_root"),
inets_test_lib:del_dirs(ServerRoot),
@@ -193,7 +205,14 @@ init_per_group(Group, Config0) when Group == https_basic;
Group == https_security;
Group == https_reload
->
- init_ssl(Group, Config0);
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ init_ssl(Group, Config0)
+ catch
+ _:_ ->
+ {skip, "Crypto did not start"}
+ end;
init_per_group(Group, Config0) when Group == http_basic;
Group == http_limit;
Group == http_custom;
@@ -203,6 +222,7 @@ init_per_group(Group, Config0) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_security;
Group == http_reload;
+ Group == http_post;
Group == http_mime_types
->
ok = start_apps(Group),
@@ -219,23 +239,35 @@ init_per_group(http_0_9, Config) ->
[{http_version, "HTTP/0.9"} | Config]
end;
init_per_group(http_htaccess = Group, Config) ->
- Path = ?config(doc_root, Config),
+ Path = proplists:get_value(doc_root, Config),
catch remove_htaccess(Path),
- create_htaccess_data(Path, ?config(address, Config)),
+ create_htaccess_data(Path, proplists:get_value(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),
+ Path = proplists:get_value(doc_root, Config),
catch remove_htaccess(Path),
- create_htaccess_data(Path, ?config(address, Config)),
- init_ssl(Group, Config);
+ create_htaccess_data(Path, proplists:get_value(address, Config)),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ init_ssl(Group, Config)
+ catch
+ _:_ ->
+ {skip, "Crypto did not start"}
+ end;
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)),
+ start_mnesia(proplists:get_value(node, Config)),
[{auth_prefix, "mnesia_"} | Config];
+init_per_group(http_logging, Config) ->
+ Config1 = [{http_version, "HTTP/1.1"} | Config],
+ ServerRoot = proplists:get_value(server_root, Config1),
+ Path = ServerRoot ++ "/httpd_log_transfer",
+ [{transfer_log, Path} | Config1];
init_per_group(_, Config) ->
Config.
@@ -248,6 +280,7 @@ end_per_group(Group, _Config) when Group == http_basic;
Group == http_htaccess;
Group == http_security;
Group == http_reload;
+ Group == http_post;
Group == http_mime_types
->
inets:stop();
@@ -272,7 +305,8 @@ end_per_group(_, _) ->
%%--------------------------------------------------------------------
init_per_testcase(Case, Config) when Case == host; Case == trace ->
- Prop = ?config(tc_group_properties, Config),
+ ct:timetrap({seconds, 40}),
+ Prop = proplists:get_value(tc_group_properties, Config),
Name = proplists:get_value(name, Prop),
Cb = case Name of
http_1_0 ->
@@ -280,18 +314,100 @@ init_per_testcase(Case, Config) when Case == host; Case == trace ->
http_1_1 ->
httpd_1_1
end,
- [{version_cb, Cb} | proplists:delete(version_cb, Config)];
+ dbg(
+ Case,
+ [{version_cb, Cb} | proplists:delete(version_cb, Config)],
+ init);
init_per_testcase(range, Config) ->
- DocRoot = ?config(doc_root, Config),
+ ct:timetrap({seconds, 20}),
+ DocRoot = proplists:get_value(doc_root, Config),
create_range_data(DocRoot),
- Config;
-
-init_per_testcase(_, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
+ dbg(range, Config, init);
+
+init_per_testcase(disk_log_internal, Config0) ->
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_exists, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ {ok, Log} = disk_log:open([{name, Filename}, {file, Filename},
+ {repair, truncate}, {format, internal},
+ {type, wrap}, {size, {1048576, 5}}]),
+ ok = disk_log:log(Log, {bogus, node(), self()}),
+ ok = disk_log:close(Log),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_bad_size, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ {ok, Log} = disk_log:open([{name, Filename}, {file, Filename},
+ {repair, truncate}, {format, internal},
+ {type, wrap}, {size, {1048576, 5}}]),
+ ok = disk_log:log(Log, {bogus, node(), self()}),
+ ok = disk_log:close(Log),
+ ok = file:delete(Filename ++ ".siz"),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_bad_file, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ ok = file:write_file(Filename ++ ".1", <<>>),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(Case, Config) ->
+ ct:timetrap({seconds, 20}),
+ dbg(Case, Config, init).
+
+end_per_testcase(Case, Config) when
+ Case == disk_log_internal;
+ Case == disk_log_exists;
+ Case == disk_log_bad_size;
+ Case == disk_log_bad_file ->
+ inets:stop(),
+ dbg(Case, Config, 'end');
+
+end_per_testcase(Case, Config) ->
+ dbg(Case, Config, 'end').
+
+
+dbg(Case, Config, Status) ->
+ Cases = [esi_put],
+ case lists:member(Case, Cases) of
+ true ->
+ case Status of
+ init ->
+ dbg:tracer(),
+ dbg:p(all, c),
+ dbg:tpl(httpd_example, cx),
+ dbg:tpl(mod_esi, generate_webpage, cx),
+ io:format("dbg: started~n"),
+ Config;
+ 'end' ->
+ io:format("dbg: stopped~n"),
+ dbg:stop_clear(),
+ ok
+ end;
+ false ->
+ case Status of
+ init ->
+ Config;
+ 'end' ->
+ ok
+ end
+ end.
%%-------------------------------------------------------------------------
%% Test cases starts here.
@@ -301,10 +417,10 @@ 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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config), proplists:get_value(node, Config),
http_request("HEAD /index.html ", Version, Host),
[{statuscode, head_status(Version)},
{version, Version}]).
@@ -313,13 +429,13 @@ 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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
http_request("GET /index.html ", Version, Host),
[{statuscode, 200},
{header, "Content-Type", "text/html"},
@@ -340,8 +456,8 @@ basic_auth() ->
[{doc, "Test Basic authentication with WWW-Authenticate header"}].
basic_auth(Config) ->
- Version = ?config(http_version, Config),
- Host = ?config(host, Config),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(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,
@@ -381,15 +497,15 @@ auth_api() ->
[{doc, "Test mod_auth API"}].
auth_api(Config) when is_list(Config) ->
- Prefix = ?config(auth_prefix, Config),
+ Prefix = proplists:get_value(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Node = proplists:get_value(node, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
ok = http_status("GET / ", Config,
[{statuscode, 200}]),
ok = auth_status(auth_request("/", "one", "WrongPassword", Version, Host), Config,
@@ -484,6 +600,9 @@ do_auth_api(AuthPrefix, Config) ->
"two", "group1"),
add_group_member(Node, ServerRoot, Port, AuthPrefix,
"secret", "Aladdin", "group2"),
+ {ok, Members} = list_group_members(Node, ServerRoot, Port, AuthPrefix, "secret", "group1"),
+ true = lists:member("one", Members),
+ true = lists:member("two", Members),
ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/",
"one", "onePassword", Version, Host),
Config, [{statuscode, 200}]),
@@ -551,12 +670,12 @@ 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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
URI = http_request("GET / ", Version, Host),
- httpd_test_lib:verify_request(?config(type, Config), Host,
- ?config(port, Config), [inet6],
- ?config(code, Config),
+ httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config), [inet6],
+ proplists:get_value(code, Config),
URI,
[{statuscode, 200}, {version, Version}]);
false ->
@@ -564,6 +683,51 @@ ipv6(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
+chunked_post() ->
+ [{doc,"Test option max_client_body_chunk"}].
+chunked_post(Config) when is_list(Config) ->
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Content-Length:833 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]),
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Content-Length:2 \r\n",
+ "ZZ"
+ },
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]).
+
+chunked_chunked_encoded_post() ->
+ [{doc,"Test option max_client_body_chunk with chunked client encoding"}].
+chunked_chunked_encoded_post(Config) when is_list(Config) ->
+ Chunk = http_chunk:encode("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"),
+ LastChunk = http_chunk:encode_last(),
+ Chunks = lists:duplicate(10000, Chunk),
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Transfer-Encoding:chunked \r\n",
+ [Chunks | LastChunk]},
+ [{http_version, "HTTP/1.1"} | Config],
+ [{statuscode, 200}]).
+
+
+%%-------------------------------------------------------------------------
htaccess_1_1(Config) when is_list(Config) ->
htaccess([{http_version, "HTTP/1.1"} | Config]).
@@ -577,11 +741,11 @@ 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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ Port = proplists:get_value(port, Config),
+ Node = proplists:get_value(node, Config),
%% Control that authentication required!
%% Control that the pages that shall be
%% authenticated really need authenticatin
@@ -692,23 +856,23 @@ 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)).
+ Cb = proplists:get_value(version_cb, Config),
+ Cb:host(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(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)).
+ httpd_1_1:chunked(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(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)).
+ httpd_1_1:expect(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)).
%%-------------------------------------------------------------------------
max_clients_1_1() ->
[{doc, "Test max clients limit"}].
@@ -759,14 +923,38 @@ esi(Config) when is_list(Config) ->
{no_header, "cache-control"}]),
ok = http_status("GET /cgi-bin/erl/httpd_example:peer ",
Config, [{statuscode, 200},
- {header, "peer-cert-exist", peer(Config)}]).
-
+ {header, "peer-cert-exist", peer(Config)}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:new_status_and_location ",
+ Config, [{statuscode, 201},
+ {header, "location"}]).
+
+%%-------------------------------------------------------------------------
+esi_put() ->
+ [{doc, "Test mod_esi PUT"}].
+
+esi_put(Config) when is_list(Config) ->
+ ok = http_status("PUT /cgi-bin/erl/httpd_example/put/123342234123 ",
+ Config, [{statuscode, 200}]).
+%%-------------------------------------------------------------------------
+esi_post() ->
+ [{doc, "Test mod_esi POST"}].
+
+esi_post(Config) when is_list(Config) ->
+ Chunk = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ Data = lists:duplicate(10000, Chunk),
+ Length = lists:flatlength(Data),
+ ok = http_status("POST /cgi-bin/erl/httpd_example/post ",
+ {"Content-Length:" ++ integer_to_list(Length) ++ "\r\n",
+ Data},
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]).
+
%%-------------------------------------------------------------------------
mod_esi_chunk_timeout(Config) when is_list(Config) ->
- ok = httpd_1_1:mod_esi_chunk_timeout(?config(type, Config),
- ?config(port, Config),
- ?config(host, Config),
- ?config(node, Config)).
+ ok = httpd_1_1:mod_esi_chunk_timeout(proplists:get_value(type, Config),
+ proplists:get_value(port, Config),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)).
%%-------------------------------------------------------------------------
cgi() ->
@@ -847,7 +1035,7 @@ cgi(Config) when is_list(Config) ->
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),
+ Host = proplists:get_value(host, Config),
Script =
case test_server:os_type() of
{win32, _} ->
@@ -859,9 +1047,9 @@ cgi_chunked_encoding_test(Config) when is_list(Config) ->
["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),
+ httpd_1_1:mod_cgi_chunked_encoding_test(proplists:get_value(type, Config), proplists:get_value(port, Config),
Host,
- ?config(node, Config),
+ proplists:get_value(node, Config),
Requests).
%%-------------------------------------------------------------------------
alias_1_1() ->
@@ -921,52 +1109,52 @@ 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)).
+ httpd_1_1:range(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(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)).
+ httpd_1_1:if_test(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(node, Config),
+ proplists:get_value(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)).
+ Cb = proplists:get_value(version_cb, Config),
+ Cb:trace(proplists:get_value(type, Config), proplists:get_value(port, Config),
+ proplists:get_value(host, Config), proplists:get_value(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).
+ httpd_load:load_test(proplists:get_value(type, Config), proplists:get_value(port, Config), proplists:get_value(host, Config),
+ proplists:get_value(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).
+ httpd_load:load_test(proplists:get_value(type, Config), proplists:get_value(port, Config), proplists:get_value(host, Config),
+ proplists:get_value(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),
+ httpd_load:load_test(proplists:get_value(type, Config), proplists:get_value(port, Config), proplists:get_value(host, Config),
+ proplists:get_value(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config), proplists:get_value(node, Config),
http_request("GET /cgi-bin/erl/httpd_example:get_bin ",
Version, Host),
[{statuscode, 200},
@@ -976,10 +1164,10 @@ content_length(Config) ->
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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config), proplists:get_value(node, Config),
http_request("GET http://www.erlang.org/%skalle ",
Version, Host),
[{statuscode, 400},
@@ -988,10 +1176,10 @@ bad_hex(Config) ->
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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config), proplists:get_value(node, Config),
http_request_missing_CR("GET /index.html ", Version, Host),
[{statuscode, 200},
{version, Version}]).
@@ -1002,12 +1190,12 @@ customize() ->
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),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
http_request("GET /index.html ", Version, Host),
[{statuscode, 200},
{header, "Content-Type", "text/html"},
@@ -1020,12 +1208,12 @@ add_default() ->
add_default(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),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
http_request("GET /index.html ", Version, Host),
[{statuscode, 200},
{header, "Content-Type", "text/html"},
@@ -1037,24 +1225,24 @@ add_default(Config) when is_list(Config) ->
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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(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)
+ dos_hostname(proplists:get_value(type, Config), proplists:get_value(port, Config), Host,
+ proplists:get_value(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).
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ garbage_content_length(proplists:get_value(type, Config), proplists:get_value(port, Config), Host,
+ proplists:get_value(node, Config), Version).
%%-------------------------------------------------------------------------
security_1_1(Config) when is_list(Config) ->
@@ -1066,15 +1254,15 @@ security_1_0(Config) when is_list(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Node = proplists:get_value(node, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
global:register_name(mod_security_test, self()), % Receive events
- test_server:sleep(5000),
+ ct:sleep(5000),
OpenDir = filename:join([ServerRoot, "htdocs", "open"]),
@@ -1172,7 +1360,7 @@ security(Config) ->
["one"] = list_auth_users(Node, Port, OpenDir),
%% Wait for successful auth to timeout.
- test_server:sleep(?AUTH_TIMEOUT*1001),
+ ct:sleep(?AUTH_TIMEOUT*1001),
[] = list_auth_users(Node, Port),
@@ -1195,17 +1383,74 @@ security(Config) ->
true = unblock_user(Node, "two", Port, OpenDir).
%%-------------------------------------------------------------------------
+
+disk_log_internal() ->
+ ["Test mod_disk_log"].
+
+disk_log_internal(Config) ->
+ Version = proplists:get_value(http_version, Config),
+ Request = "GET /" ++ integer_to_list(rand:uniform(1000000)) ++ " ",
+ ok = http_status(Request, Config, [{statuscode, 404}]),
+ Log = proplists:get_value(transfer_log, Config),
+ Match = list_to_binary(Request ++ Version),
+ disk_log_internal1(Log, Match, disk_log:chunk(Log, start)).
+disk_log_internal1(_, _, eof) ->
+ ct:fail(eof);
+disk_log_internal1(Log, Match, {Cont, [H | T]}) ->
+ case binary:match(H, Match) of
+ nomatch ->
+ disk_log_internal1(Log, Match, {Cont, T});
+ _ ->
+ ok
+ end;
+disk_log_internal1(Log, Match, {Cont, []}) ->
+ disk_log_internal1(Log, Match, disk_log:chunk(Log, Cont)).
+
+disk_log_exists() ->
+ ["Test mod_disk_log with existing logs"].
+
+disk_log_exists(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Self = self(),
+ Node = node(),
+ Log = proplists:get_value(transfer_log, Config),
+ {_, [{bogus, Node, Self} | _]} = disk_log:chunk(Log, start).
+
+disk_log_bad_size() ->
+ ["Test mod_disk_log with existing log, missing .siz"].
+
+disk_log_bad_size(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Self = self(),
+ Node = node(),
+ Log = proplists:get_value(transfer_log, Config),
+ {_, [{bogus, Node, Self} | _]} = disk_log:chunk(Log, start).
+
+disk_log_bad_file() ->
+ ["Test mod_disk_log with bad file"].
+
+disk_log_bad_file(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Version = proplists:get_value(http_version, Config),
+ Request = "GET /" ++ integer_to_list(rand:uniform(1000000)) ++ " ",
+ ok = http_status(Request, Config, [{statuscode, 404}]),
+ Log = proplists:get_value(transfer_log, Config),
+ Match = list_to_binary(Request ++ Version),
+ {_, [H | _]} = disk_log:chunk(Log, start),
+ {_, _} = binary:match(H, Match).
+
+%%-------------------------------------------------------------------------
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),
+ Server = proplists:get_value(server_pid, Config),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Type = proplists:get_value(type, Config),
HttpdConfig = httpd:info(Server),
BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
@@ -1236,11 +1481,11 @@ 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),
+ Server = proplists:get_value(server_pid, Config),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Type = proplists:get_value(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)),
@@ -1268,11 +1513,11 @@ 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),
+ Server = proplists:get_value(server_pid, Config),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Type = proplists:get_value(type, Config),
HttpdConfig = httpd:info(Server),
BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
@@ -1406,15 +1651,15 @@ mime_types_format(Config) when is_list(Config) ->
%% Internal functions -----------------------------------
%%--------------------------------------------------------------------
url(http, End, Config) ->
- Port = ?config(port, Config),
+ Port = proplists:get_value(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ Type = proplists:get_value(type, Config),
Request = http_request("GET /index.html ", Version, Host),
BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
@@ -1424,7 +1669,7 @@ do_max_clients(Config) ->
ok = httpd_test_lib:verify_request(Type, Host,
Port,
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
Request,
[{statuscode, 503},
{version, Version}]),
@@ -1437,7 +1682,7 @@ do_max_clients(Config) ->
ok = httpd_test_lib:verify_request(Type, Host,
Port,
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
Request,
[{statuscode, 200},
{version, Version}]).
@@ -1505,7 +1750,9 @@ start_apps(Group) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_htaccess;
Group == http_security;
+ Group == http_logging;
Group == http_reload;
+ Group == http_post;
Group == http_mime_types->
inets_test_lib:start_apps([inets]).
@@ -1516,7 +1763,7 @@ server_start(_, HttpdConfig) ->
{Pid, proplists:get_value(port, Info)}.
init_ssl(Group, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
CaKey = {_Trusted,_} =
erl_make_certs:make_cert([{key, dsa},
{subject,
@@ -1552,6 +1799,8 @@ server_config(https_basic, Config) ->
basic_conf() ++ server_config(https, Config);
server_config(http_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(http, Config);
+server_config(http_post, Config) ->
+ [{max_client_body_chunk, 10}] ++ server_config(http, Config);
server_config(https_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(https, Config);
server_config(http_limit, Config) ->
@@ -1567,54 +1816,56 @@ server_config(https_custom, Config) ->
server_config(https_limit, Config) ->
[{max_clients, 1}] ++ server_config(https, Config);
server_config(http_basic_auth, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_conf(ServerRoot) ++ server_config(http, Config);
server_config(https_basic_auth, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_conf(ServerRoot) ++ server_config(https, Config);
server_config(http_auth_api, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_api_conf(ServerRoot, plain) ++ server_config(http, Config);
server_config(https_auth_api, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_api_conf(ServerRoot, plain) ++ server_config(https, Config);
server_config(http_auth_api_dets, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_api_conf(ServerRoot, dets) ++ server_config(http, Config);
server_config(https_auth_api_dets, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_api_conf(ServerRoot, dets) ++ server_config(https, Config);
server_config(http_auth_api_mnesia, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
auth_api_conf(ServerRoot, mnesia) ++ server_config(http, Config);
server_config(https_auth_api_mnesia, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(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),
+ ServerRoot = proplists:get_value(server_root, Config),
tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(http, Config);
server_config(https_security, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(https, Config);
+server_config(http_logging, Config) ->
+ log_conf() ++ server_config(http, Config);
server_config(http_mime_types, Config0) ->
Config1 = basic_conf() ++ server_config(http, Config0),
- ServerRoot = ?config(server_root, Config0),
+ ServerRoot = proplists:get_value(server_root, Config0),
MimeTypesFile = filename:join([ServerRoot,"config", "mime.types"]),
[{mime_types, MimeTypesFile} | proplists:delete(mime_types, Config1)];
server_config(http, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
[{port, 0},
{socket_type, {ip_comm, [{nodelay, true}]}},
{server_name,"httpd_test"},
{server_root, ServerRoot},
- {document_root, ?config(doc_root, Config)},
+ {document_root, proplists:get_value(doc_root, Config)},
{bind_address, any},
- {ipfamily, ?config(ipfamily, Config)},
+ {ipfamily, proplists:get_value(ipfamily, Config)},
{max_header_size, 256},
{max_header_action, close},
{directory_index, ["index.html", "welcome.html"]},
@@ -1629,7 +1880,7 @@ server_config(http, Config) ->
];
server_config(https, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
[{socket_type, {essl,
[{nodelay, true},
{cacertfile,
@@ -1801,37 +2052,47 @@ mod_security_conf(SecFile, Dir) ->
{path, Dir} %% This is should not be needed, but is atm, awful design!
].
+log_conf() ->
+ [{modules, [mod_alias, mod_dir, mod_get, mod_head, mod_disk_log]},
+ {transfer_disk_log, "httpd_log_transfer"},
+ {security_disk_log, "httpd_log_security"},
+ {error_disk_log, "httpd_log_error"},
+ {transfer_disk_log_size, {1048576, 5}},
+ {error_disk_log_size, {1048576, 5}},
+ {error_disk_log_size, {1048576, 5}},
+ {security_disk_log_size, {1048576, 5}},
+ {disk_log_format, internal}].
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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(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),
+ Version = proplists:get_value(http_version, Config),
+ Host = proplists:get_value(host, Config),
+ Type = proplists:get_value(type, Config),
+ httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
transport_opts(Type, Config),
- ?config(node, Config),
+ proplists:get_value(node, Config),
AuthRequest,
Expected ++ [{version, Version}]).
@@ -1883,11 +2144,11 @@ cleanup_mnesia() ->
ok.
transport_opts(ssl, Config) ->
- PrivDir = ?config(priv_dir, Config),
- [?config(ipfamily, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ [proplists:get_value(ipfamily, Config),
{cacertfile, filename:join(PrivDir, "public_key_cacert.pem")}];
transport_opts(_, Config) ->
- [?config(ipfamily, Config)].
+ [proplists:get_value(ipfamily, Config)].
%%% mod_range
@@ -2110,6 +2371,10 @@ add_group_member(Node, Root, Port, AuthPrefix, Dir, User, Group) ->
Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]),
rpc:call(Node, mod_auth, add_group_member, [Group, User, Addr, Port,
Directory]).
+list_group_members(Node, Root, Port, AuthPrefix, Dir, Group) ->
+ Directory = filename:join([Root, "htdocs", AuthPrefix ++ Dir]),
+ rpc:call(Node, mod_auth, list_group_members, [Group, [{port, Port}, {dir, Directory}]]).
+
getaddr() ->
{ok,HostName} = inet:gethostname(),
{ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet),
@@ -2186,4 +2451,4 @@ peer(Config) ->
"true";
_ ->
"false"
- end. \ No newline at end of file
+ end.
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index db7f3c525d..931cd076cc 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,8 @@
-define(URL_START, "http://localhost:").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() -> [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 30}}].
all() ->
[uri_too_long_414,
@@ -41,7 +42,8 @@ all() ->
escaped_url_in_error_body,
script_timeout,
slowdose,
- keep_alive_timeout
+ keep_alive_timeout,
+ invalid_rfc1123_date
].
groups() ->
@@ -66,8 +68,8 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) ->
inets_test_lib:stop_apps([inets]),
inets_test_lib:start_apps([inets]),
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Dummy =
"<HTML>
@@ -152,7 +154,7 @@ end_per_testcase(_Case, Config) ->
uri_too_long_414() ->
[{doc, "Test that too long uri's get 414 HTTP code"}].
uri_too_long_414(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{max_uri_size, 10}
| HttpdConf]),
Info = httpd:info(Pid),
@@ -173,7 +175,7 @@ uri_too_long_414(Config) when is_list(Config) ->
header_too_long_413() ->
[{doc,"Test that too long headers's get 413 HTTP code"}].
header_too_long_413(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{max_header_size, 10}
| HttpdConf]),
Info = httpd:info(Pid),
@@ -192,7 +194,7 @@ header_too_long_413(Config) when is_list(Config) ->
entity_too_long() ->
[{doc, "Test that too long versions and method strings are rejected"}].
entity_too_long(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, HttpdConf),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
@@ -259,7 +261,7 @@ erl_script_nocache_opt(doc) ->
erl_script_nocache_opt(suite) ->
[];
erl_script_nocache_opt(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{port, 0}, {erl_script_nocache, true} | HttpdConf]),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
@@ -282,7 +284,7 @@ erl_script_nocache_opt(Config) when is_list(Config) ->
escaped_url_in_error_body() ->
[{doc, "Test Url-encoding see OTP-8940"}].
escaped_url_in_error_body(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{port, 0} | HttpdConf]),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
@@ -324,7 +326,7 @@ keep_alive_timeout(doc) ->
keep_alive_timeout(suite) ->
[];
keep_alive_timeout(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{port, 0}, {keep_alive, true}, {keep_alive_timeout, 2} | HttpdConf]),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
@@ -348,9 +350,9 @@ script_timeout(Config) when is_list(Config) ->
ok.
verify_script_timeout(Config, ScriptTimeout, StatusCode) ->
- HttpdConf = ?config(httpd_conf, Config),
- CgiScript = ?config(cgi_sleep, Config),
- CgiDir = ?config(cgi_dir, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
+ CgiScript = proplists:get_value(cgi_sleep, Config),
+ CgiDir = proplists:get_value(cgi_dir, Config),
{ok, Pid} = inets:start(httpd, [{port, 0},
{script_alias,
{"/cgi-bin/", CgiDir ++ "/"}},
@@ -371,7 +373,7 @@ verify_script_timeout(Config, ScriptTimeout, StatusCode) ->
slowdose() ->
[{doc, "Testing minimum bytes per second option"}].
slowdose(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{port, 0}, {minimum_bytes_per_second, 200}|HttpdConf]),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
@@ -382,13 +384,23 @@ slowdose(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
+
+invalid_rfc1123_date() ->
+ [{doc, "Test that a non-DST date is handled correcly"}].
+invalid_rfc1123_date(Config) when is_list(Config) ->
+ Rfc1123FormattedDate = "Sun, 26 Mar 2017 01:00:00 GMT",
+ NonDSTDateTime = {{2017, 03, 26},{1, 0, 0}},
+ Rfc1123FormattedDate =:= httpd_util:rfc1123_date(NonDSTDateTime).
+
+
+%%-------------------------------------------------------------------------
%% Internal functions
%%-------------------------------------------------------------------------
verify_script_nocache(Config, CgiNoCache, EsiNoCache, CgiOption, EsiOption) ->
- HttpdConf = ?config(httpd_conf, Config),
- CgiScript = ?config(cgi_printenv, Config),
- CgiDir = ?config(cgi_dir, Config),
+ HttpdConf = proplists:get_value(httpd_conf, Config),
+ CgiScript = proplists:get_value(cgi_printenv, Config),
+ CgiDir = proplists:get_value(cgi_dir, Config),
{ok, Pid} = inets:start(httpd, [{port, 0},
{script_alias,
{"/cgi-bin/", CgiDir ++ "/"}},
diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl
index ca2ab517fb..45547e6d4e 100644
--- a/lib/inets/test/httpd_block.erl
+++ b/lib/inets/test/httpd_block.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -133,7 +133,7 @@ block_disturbing_active_timeout_released(Type, Port, Host, Node) ->
block_non_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(5000),
+ ct:sleep(5000),
ok = block_nd_server(Node, Host, Port, 40000),
await_normal_process_exit(Poller, "poller", 60000),
blocked = get_admin_state(Node, Host, Port),
diff --git a/lib/inets/test/httpd_load.erl b/lib/inets/test/httpd_load.erl
index a849c71f2d..7f4d16139f 100644
--- a/lib/inets/test/httpd_load.erl
+++ b/lib/inets/test/httpd_load.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(httpd_load).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% General testcases bodies called from httpd_SUITE
-export([load_test/5]).
@@ -63,7 +63,7 @@ load_test(Fun, URIs, Type, Host, Port, Node, 0, List) ->
{'EXIT', Pid, Reason} ->
Str = lists:flatten(io_lib:format("client ~p exited: ~p",
[Pid,Reason])),
- test_server:fail(Str);
+ ct:fail(Str);
_ ->
load_test(Fun, URIs, Type, Host, Port, Node, 0, List)
end;
@@ -86,12 +86,11 @@ load_test_client(Fun, [URI|URIs], Type, Host, Port, Node, Boss, Timeout) ->
{'EXIT', {suite_failed, connection_closed, _, _}} ->
%% Some platforms seems to handle heavy load badly.
%% So, back off and see if this helps
- %%?LOG("load_test_client->requestfailed:connection_closed"[]),
2 * Timeout;
_ ->
Timeout
end,
- test_server:sleep(Timeout1),
+ ct:sleep(Timeout1),
load_test_client(Fun, URIs, Type, Host, Port, Node, Boss, Timeout1).
load_test_client_done(Boss) ->
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index ea2d0a0b85..2035b50248 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(httpd_mod).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% General testcases bodies called from httpd_SUITE
-export([alias/4, actions/4, security/5, auth/4, auth_api/6,
@@ -86,240 +86,116 @@ actions(Type, Port, Host, Node) ->
security(ServerRoot, Type, Port, Host, Node) ->
global:register_name(mod_security_test, self()), % Receive events
-
- tsp("security -> "
- "sleep"),
- test_server:sleep(5000),
+
+ ct:sleep(5000),
OpenDir = filename:join([ServerRoot, "htdocs", "open"]),
%% Test blocking / unblocking of users.
%% /open, require user one Aladdin
- tsp("security -> "
- "blocking and unblocking of users - "
- "remove all existing users"),
+
remove_users(Node, ServerRoot, Host, Port, "open"),
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for nonex user 'one' - expect 401"),
auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword",
[{statuscode, 401}]),
- tsp("security -> "
- "blocking and unblocking of users - "
- "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "onePassword"}]},
Node, Port),
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for nonex user 'two' - expect 401"),
auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword",
[{statuscode, 401}]),
- tsp("security -> "
- "blocking and unblocking of users - "
- "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "two"}, {password, "twoPassword"}]},
Node, Port),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for nonex user 'Alladin' - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "Aladdin",
"AladdinPassword", [{statuscode, 401}]),
- tsp("security -> "
- "blocking and unblocking of users - "
- "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "Aladdin"},
{password, "AladdinPassword"}]},
Node, Port),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "add user 'one'"),
add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []),
- tsp("security -> "
- "blocking and unblocking of users - "
- "add user 'two'"),
add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []),
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request 1 for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "WrongPassword"}]},
Node, Port),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request 2 for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
- tsp("security -> "
- "blocking and unblocking of users - "
- "await fail security event"),
receive_security_event({event, auth_fail, Port, OpenDir,
[{user, "one"}, {password, "WrongPassword"}]},
Node, Port),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "await block security event (two failed attempts)"),
- receive_security_event({event, user_block, Port, OpenDir,
+ receive_security_event({event, user_block, Port, OpenDir,
[{user, "one"}]}, Node, Port),
- tsp("security -> "
- "blocking and unblocking of users - "
- "unregister - no more security events"),
global:unregister_name(mod_security_test), % No more events.
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for user 'one' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword",
[{statuscode, 401}]),
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for user 'one' with correct password - expect 403"),
auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
[{statuscode, 403}]),
%% User "one" should be blocked now..
- tsp("security -> "
- "blocking and unblocking of users - "
- "list blocked users - 'one' should be the only one"),
case list_blocked_users(Node, Port) of
[{"one",_, Port, OpenDir,_}] ->
ok;
Blocked ->
- tsp(" *** unexpected blocked users ***"
- "~n Blocked: ~p", [Blocked]),
exit({unexpected_blocked, Blocked})
end,
- tsp("security -> "
- "blocking and unblocking of users - "
- "list users blocked for dir '~p' - "
- "user 'one' should be the only one", [OpenDir]),
[{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir),
- tsp("security -> "
- "blocking and unblocking of users - "
- "unblock user 'one' for dir '~p'", [OpenDir]),
true = unblock_user(Node, "one", Port, OpenDir),
%% User "one" should not be blocked any more.
- tsp("security -> "
- "blocking and unblocking of users - "
- "ensure user 'one' is no longer blocked"),
[] = list_blocked_users(Node, Port),
-
- tsp("security -> "
- "blocking and unblocking of users - "
- "auth request for user 'one' with correct password - expect 200"),
auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword",
[{statuscode, 200}]),
%% Test list_auth_users & auth_timeout
-
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "auth request for user 'two' with wrong password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword",
[{statuscode, 401}]),
-
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users for dir '~p' - expect user 'one'", [OpenDir]),
["one"] = list_auth_users(Node, Port, OpenDir),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "auth request for user 'two' with correct password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
[{statuscode, 401}]),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users - expect user 'one'"),
["one"] = list_auth_users(Node, Port),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users for dir '~p' - expect user 'one'", [OpenDir]),
["one"] = list_auth_users(Node, Port, OpenDir),
%% Wait for successful auth to timeout.
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "wait for successful auth to timeout"),
- test_server:sleep(?AUTH_TIMEOUT*1001),
-
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users - expect none"),
+ ct:sleep(?AUTH_TIMEOUT*1001),
+
[] = list_auth_users(Node, Port),
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "list auth users for dir '~p'~n - expect none", [OpenDir]),
+
[] = list_auth_users(Node, Port, OpenDir),
%% "two" is blocked.
- tsp("security -> "
- "list-auth-users and auth-timeout - "
- "unblock user 'two' for dir '~p'", [OpenDir]),
true = unblock_user(Node, "two", Port, OpenDir),
-
-
%% Test explicit blocking. Block user 'two'.
- tsp("security -> "
- "explicit blocking - list blocked users - should be none"),
[] = list_blocked_users(Node,Port,OpenDir),
- tsp("security -> "
- "explicit blocking - "
- "block user 'two' for dir '~p'", [OpenDir]),
true = block_user(Node, "two", Port, OpenDir, 10),
-
- tsp("security -> "
- "explicit blocking - "
- "auth request for user 'two' with correct password - expect 401"),
auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword",
- [{statuscode, 401}]),
- tsp("security -> "
- "done").
-
+ [{statuscode, 401}]).
%%-------------------------------------------------------------------------
auth(Type, Port, Host, Node) ->
@@ -743,7 +619,6 @@ cgi(Type, Port, Host, Node) ->
end,
%% The length (> 100) is intentional
-%% tsp("cgi -> request 01 with length > 100"),
ok = httpd_test_lib:
verify_request(Type, Host, Port, Node,
"POST /cgi-bin/" ++ Script3 ++
@@ -771,55 +646,51 @@ cgi(Type, Port, Host, Node) ->
{version, "HTTP/1.0"},
{header, "content-type", "text/plain"}]),
-%% tsp("cgi -> request 02"),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"GET /cgi-bin/"++ Script ++
" HTTP/1.0\r\n\r\n",
[{statuscode, 200},
{version, "HTTP/1.0"}]),
-%% tsp("cgi -> request 03"),
+
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"GET /cgi-bin/not_there "
"HTTP/1.0\r\n\r\n",
[{statuscode, 404},{statuscode, 500},
{version, "HTTP/1.0"}]),
-%% tsp("cgi -> request 04"),
+
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"GET /cgi-bin/"++ Script ++
"?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n",
[{statuscode, 200},
{version, "HTTP/1.0"}]),
-%% tsp("cgi -> request 04"),
+
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"}]),
-%% tsp("cgi -> request 05"),
+
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"}]),
-%% tsp("cgi -> request 06"),
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"}]),
-%% tsp("cgi -> request 07"),
+
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"}]),
-%% tsp("cgi -> request 08"),
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"}]),
-%% tsp("cgi -> request 09"),
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"POST /htbin/"++ Script ++
" HTTP/1.0\r\n\r\n",
@@ -827,31 +698,25 @@ cgi(Type, Port, Host, Node) ->
{version, "HTTP/1.0"}]),
%% Execute an existing, but bad CGI script..
-%% tsp("cgi -> request 10 - bad 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"}]),
-%% tsp("cgi -> request 11 - bad script"),
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"}]),
-%% tsp("cgi -> done"),
-
%% 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"}]),
- ok.
-
+ {version, "HTTP/1.0"}]).
%%--------------------------------------------------------------------
esi(Type, Port, Host, Node) ->
@@ -914,9 +779,14 @@ esi(Type, Port, Host, Node) ->
[{statuscode, 200},
{no_header, "cache-control"},
{version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:new_status_and_location"
+ " HTTP/1.1\r\n\r\n",
+ [{statuscode, 201},
+ {header, "Location"},
+ {version, "HTTP/1.1"}]),
ok.
-
%%--------------------------------------------------------------------
get(Type, Port, Host, Node) ->
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
@@ -1018,18 +888,15 @@ list_users(Node, Root, _Host, Port, Dir) ->
receive_security_event(Event, Node, Port) ->
- tsp("receive_security_event -> await ~w event", [element(2, Event)]),
receive
Event ->
- tsp("receive_security_event -> "
- "received expected ~w event", [element(2, Event)]),
ok;
{'EXIT', _, _} ->
receive_security_event(Event, Node, Port)
after 5000 ->
%% Flush the message queue, to see if we got something...
Msgs = inets_test_lib:flush(),
- tsf({expected_event_not_received, Msgs})
+ ct:fail({expected_event_not_received, Msgs})
end.
@@ -1045,10 +912,10 @@ receive_security_event(Event, Node, Port) ->
%% {'EXIT', _, _} ->
%% receive_security_event(Event, Node, Port);
%% Other ->
-%% test_server:fail({unexpected_event,
+%% ct:fail({unexpected_event,
%% {expected, Event}, {received, Other}})
%% after 5000 ->
-%% test_server:fail(no_event_recived)
+%% ct:fail(no_event_recived)
%% end.
@@ -1130,17 +997,4 @@ check_lists_members1(L1,L2) ->
{error,{lists_not_equal,L1,L2}}.
-%% p(F) ->
-%% p(F, []).
-
-%% p(F, A) ->
-%% io:format(user, "~w:" ++ F ++ "~n", [?MODULE|A]).
-
-tsp(F) ->
- inets_test_lib:tsp(F).
-tsp(F, A) ->
- inets_test_lib:tsp(F, A).
-
-tsf(Reason) ->
- test_server:fail(Reason).
diff --git a/lib/inets/test/httpd_mod_SUITE.erl b/lib/inets/test/httpd_mod_SUITE.erl
index 89b9e0a303..5ec4e0856d 100644
--- a/lib/inets/test/httpd_mod_SUITE.erl
+++ b/lib/inets/test/httpd_mod_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_poll.erl b/lib/inets/test/httpd_poll.erl
index 4a570fb512..f86e3a979b 100644
--- a/lib/inets/test/httpd_poll.erl
+++ b/lib/inets/test/httpd_poll.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_test_data/server_root/Makefile b/lib/inets/test/httpd_test_data/server_root/Makefile
index 4f23295401..ed4d63a3bb 100644
--- a/lib/inets/test/httpd_test_data/server_root/Makefile
+++ b/lib/inets/test/httpd_test_data/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_test_data/server_root/conf/8080.conf b/lib/inets/test/httpd_test_data/server_root/conf/8080.conf
index 48e66f0114..7b1b4a15b2 100644
--- a/lib/inets/test/httpd_test_data/server_root/conf/8080.conf
+++ b/lib/inets/test/httpd_test_data/server_root/conf/8080.conf
@@ -1,7 +1,7 @@
Port 8080
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8080
diff --git a/lib/inets/test/httpd_test_data/server_root/conf/8888.conf b/lib/inets/test/httpd_test_data/server_root/conf/8888.conf
index 79bb7fcca4..042779fcd0 100644
--- a/lib/inets/test/httpd_test_data/server_root/conf/8888.conf
+++ b/lib/inets/test/httpd_test_data/server_root/conf/8888.conf
@@ -1,7 +1,7 @@
Port 8888
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8888
diff --git a/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf b/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf
index 87c2973e5a..3add93cd73 100644
--- a/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf
+++ b/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ SocketType ip_comm
# WARNING! Do not tamper with this directive unless you are familiar with
# EWSAPI.
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.
@@ -128,7 +128,7 @@ SecurityDiskLogSize 200000 10
MaxClients 50
-# KeepAlive set the flag for persistent connections. For peristent connections
+# KeepAlive set the flag for persistent connections. For persistent connections
# set KeepAlive to on. To use One request per connection set the flag to off
# Note: The value has changed since previous version of INETS.
KeepAlive on
diff --git a/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf b/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf
index 8b8c57a98b..de49ceafd0 100644
--- a/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf
+++ b/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf
@@ -1,7 +1,7 @@
Port 8088
#ServerName your.server.net
SocketType ssl
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8088
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 71e201f826..1cecd2642c 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index 1b4d74b28e..e858ddf4f6 100644
--- a/lib/inets/test/httpd_time_test.erl
+++ b/lib/inets/test/httpd_time_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@ main(N, SocketType, Host, Port, Time)
loop(Pollers, Timeout) ->
d("loop -> entry when"
"~n Timeout: ~p", [Timeout]),
- Start = inets_time_compat:monotonic_time(),
+ Start = erlang:monotonic_time(),
receive
{'EXIT', Pid, {poller_stat_failure, SocketType, Host, Port, Time, Reason}} ->
diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl
index 928d9dc391..1abd96a228 100644
--- a/lib/inets/test/inets_SUITE.erl
+++ b/lib/inets/test/inets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,10 +28,13 @@
-define(NUM_DEFAULT_SERVICES, 1).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,5}}
+ ].
all() ->
- [{group, app_test}, {group, appup_test},
+ [{group, app_test},
{group, services_test}, httpd_reload].
groups() ->
@@ -42,8 +45,7 @@ groups() ->
start_ftpc,
start_tftpd
]},
- {app_test, [], [{inets_app_test, all}]},
- {appup_test, [], [{inets_appup_test, all}]}].
+ {app_test, [], [app, appup]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -84,6 +86,10 @@ end_per_suite(_Config) ->
%% 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(httpd_reload, Config) ->
+ inets:stop(),
+ ct:timetrap({seconds, 40}),
+ Config;
init_per_testcase(_Case, Config) ->
inets:stop(),
Config.
@@ -102,6 +108,15 @@ end_per_testcase(_, Config) ->
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
+app() ->
+ [{doc, "Test that the inets app file is ok"}].
+app(Config) when is_list(Config) ->
+ ok = ?t:app_test(inets).
+%%--------------------------------------------------------------------
+appup() ->
+ [{doc, "Test that the inets appup file is ok"}].
+appup(Config) when is_list(Config) ->
+ ok = ?t:appup_test(inets).
start_inets() ->
[{doc, "Test inets API functions"}].
@@ -134,7 +149,7 @@ start_httpc() ->
[{doc, "Start/stop of httpc service"}].
start_httpc(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ok = inets:start(),
{ok, Pid0} = inets:start(httpc, [{profile, foo}]),
@@ -145,7 +160,7 @@ start_httpc(Config) when is_list(Config) ->
inets:stop(httpc, Pid0),
- test_server:sleep(100),
+ ct:sleep(100),
Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
false = lists:member(Pid0, Pids1),
@@ -188,7 +203,7 @@ start_httpd() ->
[{doc, "Start/stop of httpd service"}].
start_httpd(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
HttpdConf = [{server_name, "httpd_test"}, {server_root, PrivDir},
{document_root, PrivDir}, {bind_address, any}],
@@ -197,11 +212,17 @@ start_httpd(Config) when is_list(Config) ->
Pids0 = [ServicePid || {_, ServicePid} <- inets:services()],
true = lists:member(Pid0, Pids0),
[_|_] = inets:services_info(),
-
inets:stop(httpd, Pid0),
- test_server:sleep(500),
+ Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
+ false = lists:member(Pid0, Pids1),
+ {ok, Pid0b} =
+ inets:start(httpd, [{port, 0}, {ipfamily, inet6fb4} | HttpdConf]),
+ Pids0b = [ServicePid || {_, ServicePid} <- inets:services()],
+ true = lists:member(Pid0b, Pids0b),
+ [_|_] = inets:services_info(),
+ inets:stop(httpd, Pid0b),
Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
- false = lists:member(Pid0, Pids1),
+ false = lists:member(Pid0b, Pids1),
{ok, Pid1} =
inets:start(httpd, [{port, 0}, {ipfamily, inet} | HttpdConf],
stand_alone),
@@ -212,7 +233,7 @@ start_httpd(Config) when is_list(Config) ->
{'EXIT', Pid1, shutdown} ->
ok
after 100 ->
- test_server:fail(stand_alone_not_shutdown)
+ ct:fail(stand_alone_not_shutdown)
end,
ok = inets:stop(),
File0 = filename:join(PrivDir, "httpd.conf"),
@@ -279,44 +300,38 @@ start_httpd(Config) when is_list(Config) ->
start_ftpc(doc) ->
[{doc, "Start/stop of ftpc service"}];
-start_ftpc(Config) when is_list(Config) ->
+start_ftpc(Config0) when is_list(Config0) ->
process_flag(trap_exit, true),
ok = inets:start(),
- try
- begin
- {_Tag, FtpdHost} = ftp_suite_lib:dirty_select_ftpd_host(Config),
- case inets:start(ftpc, [{host, FtpdHost}]) of
- {ok, Pid0} ->
- Pids0 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- true = lists:member(Pid0, Pids0),
- [_|_] = inets:services_info(),
- inets:stop(ftpc, Pid0),
- test_server:sleep(100),
- Pids1 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- false = lists:member(Pid0, Pids1),
- {ok, Pid1} =
- inets:start(ftpc, [{host, FtpdHost}], stand_alone),
- Pids2 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- false = lists:member(Pid1, Pids2),
- ok = inets:stop(stand_alone, Pid1),
- receive
- {'EXIT', Pid1, shutdown} ->
- ok
- after 100 ->
- ct:fail(stand_alone_not_shutdown)
- end,
- ok = inets:stop(),
- ok;
- _ ->
- {skip, "Unable to reach selected FTP server " ++ FtpdHost}
- end
- end
- catch
- throw:{error, not_found} ->
- {skip, "No available FTP servers"}
+ case ftp_SUITE:init_per_suite(Config0) of
+ {skip, _} = Skip ->
+ Skip;
+ Config ->
+ FtpdHost = proplists:get_value(ftpd_host,Config),
+ {ok, Pid0} = inets:start(ftpc, [{host, FtpdHost}]),
+ Pids0 = [ServicePid || {_, ServicePid} <-
+ inets:services()],
+ true = lists:member(Pid0, Pids0),
+ [_|_] = inets:services_info(),
+ inets:stop(ftpc, Pid0),
+ ct:sleep(100),
+ Pids1 = [ServicePid || {_, ServicePid} <-
+ inets:services()],
+ false = lists:member(Pid0, Pids1),
+ {ok, Pid1} =
+ inets:start(ftpc, [{host, FtpdHost}], stand_alone),
+ Pids2 = [ServicePid || {_, ServicePid} <-
+ inets:services()],
+ false = lists:member(Pid1, Pids2),
+ ok = inets:stop(stand_alone, Pid1),
+ receive
+ {'EXIT', Pid1, shutdown} ->
+ ok
+ after 100 ->
+ ct:fail(stand_alone_not_shutdown)
+ end,
+ ok = inets:stop(),
+ catch ftp_SUITE:end_per_SUITE(Config)
end.
%%-------------------------------------------------------------------------
@@ -331,7 +346,7 @@ start_tftpd(Config) when is_list(Config) ->
true = lists:member(Pid0, Pids0),
[_|_] = inets:services_info(),
inets:stop(tftpd, Pid0),
- test_server:sleep(100),
+ ct:sleep(100),
Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
false = lists:member(Pid0, Pids1),
{ok, Pid1} =
@@ -343,7 +358,7 @@ start_tftpd(Config) when is_list(Config) ->
{'EXIT', Pid1, shutdown} ->
ok
after 100 ->
- test_server:fail(stand_alone_not_shutdown)
+ ct:fail(stand_alone_not_shutdown)
end,
ok = inets:stop(),
application:load(inets),
@@ -360,34 +375,34 @@ httpd_reload() ->
[{doc, "Reload httpd configuration without restarting service"}].
httpd_reload(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
HttpdConf = [{server_name, "httpd_test"},
{server_root, PrivDir},
{document_root, PrivDir},
{bind_address, "localhost"}],
ok = inets:start(),
- test_server:sleep(5000),
+ ct:sleep(5000),
{ok, Pid0} = inets:start(httpd, [{port, 0},
{ipfamily, inet} | HttpdConf]),
- test_server:sleep(5000),
+ ct:sleep(5000),
[{port, Port0}] = httpd:info(Pid0, [port]),
- test_server:sleep(5000),
+ ct:sleep(5000),
[{document_root, PrivDir}] = httpd:info(Pid0, [document_root]),
- test_server:sleep(5000),
+ ct:sleep(5000),
ok = httpd:reload_config([{port, Port0}, {ipfamily, inet},
{server_name, "httpd_test"},
{server_root, PrivDir},
{document_root, DataDir},
{bind_address, "localhost"}], non_disturbing),
- test_server:sleep(5000),
+ ct:sleep(5000),
[{document_root, DataDir}] = httpd:info(Pid0, [document_root]),
- test_server:sleep(5000),
+ ct:sleep(5000),
ok = httpd:reload_config([{port, Port0}, {ipfamily, inet},
{server_name, "httpd_test"},
diff --git a/lib/inets/test/inets_app_test.erl b/lib/inets/test/inets_app_test.erl
deleted file mode 100644
index c6d0715e1f..0000000000
--- a/lib/inets/test/inets_app_test.erl
+++ /dev/null
@@ -1,245 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the application specifics of the inets application
-%%----------------------------------------------------------------------
--module(inets_app_test).
-
--compile(export_all).
-
--include("inets_test_lib.hrl").
-
-
-% t() -> megaco_test_lib:t(?MODULE).
-% t(Case) -> megaco_test_lib:t({?MODULE, Case}).
-
-
-%% Test server callbacks
-init_per_testcase(_, Config) ->
- Config.
-
-end_per_testcase(_Case, Config) ->
- Config.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [fields, modules, exportall, app_depend].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- case is_app(inets) of
- {ok, AppFile} ->
- io:format("AppFile: ~n~p~n", [AppFile]),
- inets:print_version_info(),
- [{app_file, AppFile}|Config];
- {error, Reason} ->
- fail(Reason)
- end.
-
-is_app(App) ->
- LibDir = code:lib_dir(App),
- File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]),
- case file:consult(File) of
- {ok, [{application, App, AppFile}]} ->
- {ok, AppFile};
- Error ->
- {error, {invalid_format, Error}}
- end.
-
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fields(suite) ->
- [];
-fields(doc) ->
- [];
-fields(Config) when is_list(Config) ->
- AppFile = key1search(app_file, Config),
- Fields = [vsn, description, modules, registered, applications],
- case check_fields(Fields, AppFile, []) of
- [] ->
- ok;
- Missing ->
- fail({missing_fields, Missing})
- end.
-
-check_fields([], _AppFile, Missing) ->
- Missing;
-check_fields([Field|Fields], AppFile, Missing) ->
- check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)).
-
-check_field(Name, AppFile, Missing) ->
- io:format("checking field: ~p~n", [Name]),
- case lists:keymember(Name, 1, AppFile) of
- true ->
- Missing;
- false ->
- [Name|Missing]
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-modules(suite) ->
- [];
-modules(doc) ->
- [];
-modules(Config) when is_list(Config) ->
- AppFile = key1search(app_file, Config),
- Mods = key1search(modules, AppFile),
- EbinList = get_ebin_mods(inets),
- case missing_modules(Mods, EbinList, []) of
- [] ->
- ok;
- Missing ->
- throw({error, {missing_modules, Missing}})
- end,
- case extra_modules(Mods, EbinList, []) of
- [] ->
- ok;
- Extra ->
- throw({error, {extra_modules, Extra}})
- end,
- {ok, Mods}.
-
-get_ebin_mods(App) ->
- LibDir = code:lib_dir(App),
- EbinDir = filename:join([LibDir,"ebin"]),
- {ok, Files0} = file:list_dir(EbinDir),
- Files1 = [lists:reverse(File) || File <- Files0],
- [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1].
-
-
-missing_modules([], _Ebins, Missing) ->
- Missing;
-missing_modules([Mod|Mods], Ebins, Missing) ->
- case lists:member(Mod, Ebins) of
- true ->
- missing_modules(Mods, Ebins, Missing);
- false ->
- io:format("missing module: ~p~n", [Mod]),
- missing_modules(Mods, Ebins, [Mod|Missing])
- end.
-
-
-extra_modules(_Mods, [], Extra) ->
- Extra;
-extra_modules(Mods, [Mod|Ebins], Extra) ->
- case lists:member(Mod, Mods) of
- true ->
- extra_modules(Mods, Ebins, Extra);
- false ->
- io:format("supefluous module: ~p~n", [Mod]),
- extra_modules(Mods, Ebins, [Mod|Extra])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-exportall(suite) ->
- [];
-exportall(doc) ->
- [];
-exportall(Config) when is_list(Config) ->
- AppFile = key1search(app_file, Config),
- Mods = key1search(modules, AppFile),
- check_export_all(Mods).
-
-
-check_export_all([]) ->
- ok;
-check_export_all([Mod|Mods]) ->
- case (catch apply(Mod, module_info, [compile])) of
- {'EXIT', {undef, _}} ->
- check_export_all(Mods);
- O ->
- case lists:keysearch(options, 1, O) of
- false ->
- check_export_all(Mods);
- {value, {options, List}} ->
- case lists:member(export_all, List) of
- true ->
- throw({error, {export_all, Mod}});
- false ->
- check_export_all(Mods)
- end
- end
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-app_depend(suite) ->
- [];
-app_depend(doc) ->
- [];
-app_depend(Config) when is_list(Config) ->
- AppFile = key1search(app_file, Config),
- Apps = key1search(applications, AppFile),
- check_apps(Apps).
-
-
-check_apps([]) ->
- ok;
-check_apps([App|Apps]) ->
- case is_app(App) of
- {ok, _} ->
- check_apps(Apps);
- Error ->
- throw({error, {missing_app, {App, Error}}})
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-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.
diff --git a/lib/inets/test/inets_appup_test.erl b/lib/inets/test/inets_appup_test.erl
deleted file mode 100644
index 999989b8b4..0000000000
--- a/lib/inets/test/inets_appup_test.erl
+++ /dev/null
@@ -1,71 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Verify the application specifics of the Inets application
-%%----------------------------------------------------------------------
--module(inets_appup_test).
-
--compile(export_all).
--include_lib("common_test/include/ct.hrl").
-
-
-%% Test server callbacks
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, Config) ->
- Config.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() ->
- [appup].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_per_suite(suite) -> [];
-init_per_suite(doc) -> [];
-init_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-end_per_suite(suite) -> [];
-end_per_suite(doc) -> [];
-end_per_suite(Config) when is_list(Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-appup() ->
- [{doc, "Perform a simple check of the inets appup file"}].
-appup(Config) when is_list(Config) ->
- ok = ?t:appup_test(inets).
diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl
index cfbda3ccf5..7ea7e08ed1 100644
--- a/lib/inets/test/inets_socketwrap_SUITE.erl
+++ b/lib/inets/test/inets_socketwrap_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,8 +61,8 @@ end_per_testcase(_, Config) ->
start_httpd_fd() ->
[{doc, "Start/stop of httpd service with socket wrapper"}].
start_httpd_fd(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
HttpdConf = [{port, 80}, {ipfamily, inet},
{server_name, "httpd_fd_test"}, {server_root, PrivDir},
{document_root, PrivDir}, {bind_address, any}],
@@ -94,7 +94,7 @@ start_httpd_fd(Config) when is_list(Config) ->
start_tftpd_fd() ->
[{doc, "Start/stop of tfpd service with socket wrapper"}].
start_tftpd_fd(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
case setup_node_info(node()) of
{skip, _} = Skip ->
Skip;
diff --git a/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c
index b28f6b1c08..018d398956 100644
--- a/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c
+++ b/lib/inets/test/inets_socketwrap_SUITE_data/setuid_socket_wrap.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl
index 33ae3bd3f2..1e664337e6 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,11 +26,14 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds, 10}}
+ ].
all() ->
[default_tree, ftpc_worker, tftpd_worker,
- httpd_subtree, httpd_subtree_profile,
+ httpd_config, httpd_subtree, httpd_subtree_profile,
httpc_subtree].
groups() ->
@@ -49,11 +52,32 @@ end_per_suite(_) ->
inets:stop(),
ok.
-init_per_testcase(httpd_subtree, Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- PrivDir = ?config(priv_dir, Config),
- Dir = filename:join(PrivDir, "root"),
+init_per_testcase(httpd_config = TC, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, TC),
+ ok = file:make_dir(Dir),
+
+ FallbackConfig = [{port, 0},
+ {server_name,"www.test"},
+ {modules, [mod_get]},
+ {server_root, Dir},
+ {document_root, Dir},
+ {bind_address, any},
+ {ipfamily, inet6fb4}],
+ try
+ inets:stop(),
+ inets:start(),
+ inets:start(httpd, FallbackConfig),
+ Config
+ catch
+ _:Reason ->
+ inets:stop(),
+ exit({failed_starting_inets, Reason})
+ end;
+
+init_per_testcase(httpd_subtree = TC, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, TC),
ok = file:make_dir(Dir),
SimpleConfig = [{port, 0},
@@ -67,18 +91,16 @@ init_per_testcase(httpd_subtree, Config) ->
inets:stop(),
inets:start(),
inets:start(httpd, SimpleConfig),
- [{watchdog, Dog} | NewConfig]
+ Config
catch
_:Reason ->
inets:stop(),
exit({failed_starting_inets, Reason})
end;
-init_per_testcase(httpd_subtree_profile, Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- PrivDir = ?config(priv_dir, Config),
- Dir = filename:join(PrivDir, "root"),
+init_per_testcase(httpd_subtree_profile = TC, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, TC),
ok = file:make_dir(Dir),
SimpleConfig = [{port, 0},
@@ -93,7 +115,7 @@ init_per_testcase(httpd_subtree_profile, Config) ->
inets:stop(),
inets:start(),
{ok, _} = inets:start(httpd, SimpleConfig),
- [{watchdog, Dog} | NewConfig]
+ Config
catch
_:Reason ->
inets:stop(),
@@ -102,24 +124,18 @@ init_per_testcase(httpd_subtree_profile, Config) ->
init_per_testcase(_Case, Config) ->
- Dog = test_server:timetrap(?t:minutes(5)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
inets:stop(),
ok = inets:start(),
- [{watchdog, Dog} | NewConfig].
+ Config.
end_per_testcase(Case, Config) when Case == httpd_subtree;
Case == httpd_subtree_profile ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "root"),
inets_test_lib:del_dirs(Dir),
ok;
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_, _) ->
inets:stop(),
ok.
@@ -164,29 +180,25 @@ default_tree(Config) when is_list(Config) ->
ftpc_worker() ->
[{doc, "Makes sure the ftp worker processes are added and removed "
"appropriatly to/from the supervison tree."}].
-ftpc_worker(Config) when is_list(Config) ->
+ftpc_worker(Config0) when is_list(Config0) ->
[] = supervisor:which_children(ftp_sup),
- try
- begin
- {_Tag, FtpdHost} = ftp_suite_lib:dirty_select_ftpd_host(Config),
- case inets:start(ftpc, [{host, FtpdHost}]) of
- {ok, Pid} ->
- case supervisor:which_children(ftp_sup) of
- [{_,_, worker, [ftp]}] ->
- inets:stop(ftpc, Pid),
- test_server:sleep(5000),
- [] = supervisor:which_children(ftp_sup),
- ok;
- Children ->
- exit({unexpected_children, Children})
- end;
- _ ->
- {skip, "Unable to reach test FTP server"}
+ case ftp_SUITE:init_per_suite(Config0) of
+ {skip, _} = Skip ->
+ Skip;
+ Config ->
+ FtpdHost = proplists:get_value(ftpd_host,Config),
+ {ok, Pid} = inets:start(ftpc, [{host, FtpdHost}]),
+ case supervisor:which_children(ftp_sup) of
+ [{_,_, worker, [ftp]}] ->
+ inets:stop(ftpc, Pid),
+ ct:sleep(5000),
+ [] = supervisor:which_children(ftp_sup),
+ catch ftp_SUITE:end_per_SUITE(Config),
+ ok;
+ Children ->
+ catch ftp_SUITE:end_per_SUITE(Config),
+ exit({unexpected_children, Children})
end
- end
- catch
- throw:{error, not_found} ->
- {skip, "No available FTP servers"}
end.
tftpd_worker() ->
@@ -200,10 +212,15 @@ tftpd_worker(Config) when is_list(Config) ->
[{_,Pid0, worker, _}] = supervisor:which_children(tftp_sup),
inets:stop(tftpd, Pid0),
- test_server:sleep(5000),
+ ct:sleep(5000),
[] = supervisor:which_children(tftp_sup),
ok.
+httpd_config() ->
+ [{doc, "Makes sure the httpd config works for inet6fb4."}].
+httpd_config(Config) when is_list(Config) ->
+ do_httpd_subtree(Config, default).
+
httpd_subtree() ->
[{doc, "Makes sure the httpd sub tree is correct."}].
httpd_subtree(Config) when is_list(Config) ->
diff --git a/lib/inets/test/inets_test_lib.hrl b/lib/inets/test/inets_test_lib.hrl
index b2989be08d..d436395290 100644
--- a/lib/inets/test/inets_test_lib.hrl
+++ b/lib/inets/test/inets_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,96 +21,8 @@
%%----------------------------------------------------------------------
%% Purpose: Define common macros for testing
%%----------------------------------------------------------------------
-
-%% - Print macros -
-
--ifdef(inets_debug).
--define(DEBUG(F,A), inets_test_lib:debug(F, A, ?MODULE, ?LINE)).
--else.
--define(DEBUG(F,A),ok).
--endif.
-
--ifdef(inets_log).
--define(LOG(F,A), inets_test_lib:log(F, A, ?MODULE, ?LINE)).
--else.
--define(LOG(F,A),ok).
--endif.
-
--define(INFO(F,A), inets_test_lib:info(F, A, ?MODULE, ?LINE)).
--define(PRINT(F,A), inets_test_lib:print(F, A, ?MODULE, ?LINE)).
-
-
-%% - Macros stolen from the test server -
-
--ifndef(line).
--define(line,put(test_server_loc,{?MODULE,?LINE}),).
--endif.
-
-
-%% - OS Command and stuff
-
--define(OSCMD(Cmd), inets_test_lib:oscmd(Cmd)).
-
--define(PRINT_SYSTEM_INFO(P), inets_test_lib:print_system_info(P)).
-
--define(RUN_ON_OS(OS, FUN), inets_test_lib:run_on_os(OS, FUN)).
--define(RUN_ON_WINDOWS(FUN), inets_test_lib:run_on_windows(FUN)).
-
-
-%% - Test case macros -
-
--define(EXPANDABLE(I, C, F), inets_test_lib:expandable(I, C, F)).
--define(OS_BASED_SKIP(Skippable),
- inets_test_lib:os_based_skip(Skippable)).
-
--define(NON_PC_TC_MAYBE_SKIP(Config, Condition),
- inets_test_lib:non_pc_tc_maybe_skip(Config, Condition, ?MODULE, ?LINE)).
-
-
-
%% - Misc macros -
-define(ENSURE_STARTED(A), inets_test_lib:ensure_started(A)).
--define(UPDATE(K,V,C), inets_test_lib:update_config(K,V,C)).
--define(CONFIG(K,C), inets_test_lib:get_config(K,C)).
--define(HOSTNAME(), inets_test_lib:hostname()).
--define(SZ(X), inets_test_lib:sz(X)).
-
-
-%% - Test case macros -
-
--define(SKIP(Reason), inets_test_lib:skip(Reason, ?MODULE, ?LINE)).
--define(FAIL(Reason), inets_test_lib:fail(Reason, ?MODULE, ?LINE)).
-
-
-%% - Socket macros -
-
--define(CONNECT(M,H,P), inets_test_lib:connect(M,H,P)).
--define(SEND(M,S,D), inets_test_lib:send(M,S,D)).
--define(CSEND(M,S,D,C,T), inets_test_lib:csend(M,S,D,C,T)).
--define(CLOSE(M,S), inets_test_lib:close(M,S)).
-
-
-%% - Time macros -
-
--define(HOURS(N), inets_test_lib:hours(N)).
--define(MINS(N), inets_test_lib:minutes(N)).
--define(SECS(N), inets_test_lib:seconds(N)).
-
--define(WD_START(T), inets_test_lib:watchdog_start(T)).
--define(WD_STOP(P), inets_test_lib:watchdog_stop(P)).
-
--define(SLEEP(MSEC), inets_test_lib:sleep(MSEC)).
--define(M(), inets_test_lib:millis()).
--define(MDIFF(A,B), inets_test_lib:millis_diff(A,B)).
-
-
-%% - Process utility macros -
-
--define(FLUSH(), inets_test_lib:flush_mqueue()).
--define(ETRAP_GET(), inets_test_lib:trap_exit()).
--define(ETRAP_SET(O), inets_test_lib:trap_exit(O)).
-
-
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
index 341d27d8b1..172db53844 100644
--- a/lib/inets/test/old_httpd_SUITE.erl
+++ b/lib/inets/test/old_httpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(old_httpd_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
-include_lib("kernel/include/file.hrl").
@@ -286,9 +286,7 @@ init_per_suite(Config) ->
"~n Config: ~p"
"~n", [Config]),
- ?PRINT_SYSTEM_INFO([]),
-
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
SuiteTopDir = filename:join(PrivDir, ?MODULE),
case file:make_dir(SuiteTopDir) of
ok ->
@@ -314,7 +312,7 @@ init_per_suite(Config) ->
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
- %% SuiteTopDir = ?config(suite_top_dir, Config),
+ %% SuiteTopDir = proplists:get_value(suite_top_dir, Config),
%% inets_test_lib:del_dirs(SuiteTopDir),
ok.
@@ -346,8 +344,8 @@ init_per_testcase2(Case, Config) ->
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),
+ DataDir = proplists:get_value(data_dir, Config),
+ SuiteTopDir = proplists:get_value(suite_top_dir, Config),
%% tsp("init_per_testcase2 -> "
%% "~n SuiteDir: ~p"
@@ -499,7 +497,7 @@ init_per_testcase3(Case, Config) ->
Dog = test_server:timetrap(inets_test_lib:minutes(10)),
NewConfig = lists:keydelete(watchdog, 1, Config),
- TcTopDir = ?config(tc_top_dir, Config),
+ TcTopDir = proplists:get_value(tc_top_dir, Config),
CaseRest =
case atom_to_list(Case) of
@@ -581,16 +579,16 @@ init_per_testcase3(Case, Config) ->
{skip, _} = Skip ->
Skip;
"mod_auth_" ++ _ ->
- start_mnesia(?config(node, Config)),
+ start_mnesia(proplists:get_value(node, Config)),
[{watchdog, Dog} | NewConfig];
"mod_htaccess" ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
Path = filename:join([ServerRoot, "htdocs"]),
catch remove_htaccess(Path),
- create_htaccess_data(Path, ?config(address, Config)),
+ create_htaccess_data(Path, proplists:get_value(address, Config)),
[{watchdog, Dog} | NewConfig];
"range" ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
Path = filename:join([ServerRoot, "htdocs"]),
create_range_data(Path),
[{watchdog, Dog} | NewConfig];
@@ -613,7 +611,7 @@ init_per_testcase3(Case, Config) ->
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
end_per_testcase(Case, Config) ->
- Dog = ?config(watchdog, Config),
+ Dog = proplists:get_value(watchdog, Config),
test_server:timetrap_cancel(Dog),
end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)),
ok.
@@ -641,7 +639,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -651,7 +649,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -660,9 +658,9 @@ ip_mod_security(doc) ->
ip_mod_security(suite) ->
[];
ip_mod_security(Config) when is_list(Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -672,7 +670,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -681,9 +679,9 @@ ip_mod_auth_api(doc) ->
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),
+ ServerRoot = proplists:get_value(server_root, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(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),
@@ -695,7 +693,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_mod_htaccess(doc) ->
@@ -704,7 +702,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_mod_cgi(doc) ->
@@ -713,7 +711,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_mod_esi(doc) ->
@@ -722,7 +720,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -732,7 +730,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -742,7 +740,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_mod_all(doc) ->
@@ -751,7 +749,7 @@ 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)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_load_light(doc) ->
@@ -759,8 +757,8 @@ ip_load_light(doc) ->
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),
+ httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ip_comm, light)),
ok.
%%-------------------------------------------------------------------------
@@ -769,8 +767,8 @@ ip_load_medium(doc) ->
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),
+ httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ip_comm, medium)),
ok.
%%-------------------------------------------------------------------------
@@ -779,8 +777,8 @@ ip_load_heavy(doc) ->
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),
+ httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ip_comm, heavy)),
ok.
@@ -791,8 +789,8 @@ ip_dos_hostname(doc) ->
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),
+ dos_hostname(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config), ?MAX_HEADER_SIZE),
ok.
@@ -802,13 +800,7 @@ 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),
+ httpd_time_test:t(ip_comm, proplists:get_value(host, Config), ?IP_PORT),
ok.
%%-------------------------------------------------------------------------
@@ -818,8 +810,8 @@ ip_block_503(doc) ->
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)),
+ httpd_block:block_503(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_block_disturbing_idle(doc) ->
@@ -829,8 +821,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_block_non_disturbing_idle(doc) ->
@@ -840,8 +832,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_block_disturbing_active(doc) ->
@@ -851,8 +843,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_block_non_disturbing_active(doc) ->
@@ -862,8 +854,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -877,9 +869,9 @@ 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,
+ proplists:get_value(host,
Config),
- ?config(node,
+ proplists:get_value(node,
Config)),
ok.
%%-------------------------------------------------------------------------
@@ -893,9 +885,9 @@ ip_block_disturbing_active_timeout_released(Config)
when is_list(Config) ->
httpd_block:block_disturbing_active_timeout_released(ip_comm,
?IP_PORT,
- ?config(host,
+ proplists:get_value(host,
Config),
- ?config(node,
+ proplists:get_value(node,
Config)),
ok.
@@ -910,9 +902,9 @@ ip_block_non_disturbing_active_timeout_not_released(Config)
httpd_block:
block_non_disturbing_active_timeout_not_released(ip_comm,
?IP_PORT,
- ?config(host,
+ proplists:get_value(host,
Config),
- ?config(node,
+ proplists:get_value(node,
Config)),
ok.
%%-------------------------------------------------------------------------
@@ -927,9 +919,9 @@ ip_block_non_disturbing_active_timeout_released(Config)
httpd_block:
block_non_disturbing_active_timeout_released(ip_comm,
?IP_PORT,
- ?config(host,
+ proplists:get_value(host,
Config),
- ?config(node,
+ proplists:get_value(node,
Config)),
ok.
%%-------------------------------------------------------------------------
@@ -939,8 +931,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_block_non_disturbing_blocker_dies(doc) ->
@@ -949,8 +941,8 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_restart_no_block(doc) ->
@@ -958,8 +950,8 @@ 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)),
+ httpd_block:restart_no_block(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_restart_disturbing_block(doc) ->
@@ -967,33 +959,9 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -1002,33 +970,9 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -1043,7 +987,7 @@ essl_mod_alias(Config) when is_list(Config) ->
ssl_mod_alias(Tag, Config) ->
httpd_mod:alias(Tag, ?SSL_PORT,
- ?config(host, Config), ?config(node, Config)),
+ proplists:get_value(host, Config), proplists:get_value(node, Config)),
ok.
@@ -1060,8 +1004,8 @@ essl_mod_actions(Config) when is_list(Config) ->
ssl_mod_actions(Tag, Config) ->
httpd_mod:actions(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1075,12 +1019,12 @@ essl_mod_security(Config) when is_list(Config) ->
ssl_mod_security(essl, Config).
ssl_mod_security(Tag, Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
httpd_mod:security(ServerRoot,
Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1096,8 +1040,8 @@ essl_mod_auth(Config) when is_list(Config) ->
ssl_mod_auth(Tag, Config) ->
httpd_mod:auth(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1112,9 +1056,9 @@ 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),
+ ServerRoot = proplists:get_value(server_root, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(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),
@@ -1134,8 +1078,8 @@ essl_mod_auth_mnesia_api(Config) when is_list(Config) ->
ssl_mod_auth_mnesia_api(Tag, Config) ->
httpd_mod:auth_mnesia_api(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1151,8 +1095,8 @@ essl_mod_htaccess(Config) when is_list(Config) ->
ssl_mod_htaccess(Tag, Config) ->
httpd_mod:htaccess(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1168,8 +1112,8 @@ essl_mod_cgi(Config) when is_list(Config) ->
ssl_mod_cgi(Tag, Config) ->
httpd_mod:cgi(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1185,8 +1129,8 @@ essl_mod_esi(Config) when is_list(Config) ->
ssl_mod_esi(Tag, Config) ->
httpd_mod:esi(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1202,8 +1146,8 @@ essl_mod_get(Config) when is_list(Config) ->
ssl_mod_get(Tag, Config) ->
httpd_mod:get(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1219,8 +1163,8 @@ essl_mod_head(Config) when is_list(Config) ->
ssl_mod_head(Tag, Config) ->
httpd_mod:head(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1236,8 +1180,8 @@ essl_mod_all(Config) when is_list(Config) ->
ssl_mod_all(Tag, Config) ->
httpd_mod:all(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1253,8 +1197,8 @@ essl_load_light(Config) when is_list(Config) ->
ssl_load_light(Tag, Config) ->
httpd_load:load_test(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ssl, light)),
ok.
@@ -1269,16 +1213,10 @@ 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),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ssl, medium)),
ok.
@@ -1293,16 +1231,10 @@ 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),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
get_nof_clients(ssl, heavy)),
ok.
@@ -1320,8 +1252,8 @@ essl_dos_hostname(Config) when is_list(Config) ->
ssl_dos_hostname(Tag, Config) ->
dos_hostname(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config),
?MAX_HEADER_SIZE),
ok.
@@ -1337,23 +1269,8 @@ 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),
+ proplists:get_value(host, Config),
?SSL_PORT),
ok.
@@ -1372,8 +1289,8 @@ essl_block_503(Config) when is_list(Config) ->
ssl_block_503(Tag, Config) ->
httpd_block:block_503(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1391,8 +1308,8 @@ essl_block_disturbing_idle(Config) when is_list(Config) ->
ssl_block_disturbing_idle(Tag, Config) ->
httpd_block:block_disturbing_idle(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1410,8 +1327,8 @@ essl_block_non_disturbing_idle(Config) when is_list(Config) ->
ssl_block_non_disturbing_idle(Tag, Config) ->
httpd_block:block_non_disturbing_idle(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1429,8 +1346,8 @@ essl_block_disturbing_active(Config) when is_list(Config) ->
ssl_block_disturbing_active(Tag, Config) ->
httpd_block:block_disturbing_active(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1448,8 +1365,8 @@ essl_block_non_disturbing_active(Config) when is_list(Config) ->
ssl_block_non_disturbing_active(Tag, Config) ->
httpd_block:block_non_disturbing_idle(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1468,8 +1385,8 @@ essl_block_disturbing_active_timeout_not_released(Config)
ssl_block_disturbing_active_timeout_not_released(Tag, Config) ->
Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(node, Config),
httpd_block:block_disturbing_active_timeout_not_released(Tag,
Port, Host, Node),
ok.
@@ -1490,8 +1407,8 @@ essl_block_disturbing_active_timeout_released(Config)
ssl_block_disturbing_active_timeout_released(Tag, Config) ->
Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(node, Config),
httpd_block:block_disturbing_active_timeout_released(Tag,
Port,
Host,
@@ -1513,8 +1430,8 @@ essl_block_non_disturbing_active_timeout_not_released(Config)
ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) ->
Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(node, Config),
httpd_block:block_non_disturbing_active_timeout_not_released(Tag,
Port,
Host,
@@ -1539,8 +1456,8 @@ essl_block_non_disturbing_active_timeout_released(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),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(node, Config),
httpd_block:block_non_disturbing_active_timeout_released(Tag,
Port,
Host,
@@ -1562,8 +1479,8 @@ essl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_disturbing_blocker_dies(Tag, Config) ->
httpd_block:disturbing_blocker_dies(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1579,8 +1496,8 @@ essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_non_disturbing_blocker_dies(Tag, Config) ->
httpd_block:non_disturbing_blocker_dies(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1597,8 +1514,8 @@ essl_restart_no_block(Config) when is_list(Config) ->
ssl_restart_no_block(Tag, Config) ->
httpd_block:restart_no_block(Tag,
?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1613,43 +1530,9 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1664,34 +1547,10 @@ 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)),
+ proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
@@ -1701,8 +1560,8 @@ ip_host(doc) ->
ip_host(suite)->
[];
ip_host(Config) when is_list(Config) ->
- httpd_1_1:host(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
+ httpd_1_1:host(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_chunked(doc) ->
@@ -1710,8 +1569,8 @@ ip_chunked(doc) ->
ip_chunked(suite) ->
[];
ip_chunked(Config) when is_list(Config) ->
- httpd_1_1:chunked(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
+ httpd_1_1:chunked(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_expect(doc) ->
@@ -1720,8 +1579,8 @@ ip_expect(doc) ->
ip_expect(suite)->
[];
ip_expect(Config) when is_list(Config) ->
- httpd_1_1:expect(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
+ httpd_1_1:expect(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_range(doc) ->
@@ -1729,8 +1588,8 @@ ip_range(doc) ->
ip_range(suite)->
[];
ip_range(Config) when is_list(Config) ->
- httpd_1_1:range(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
+ httpd_1_1:range(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_if_test(doc) ->
@@ -1738,10 +1597,10 @@ ip_if_test(doc) ->
ip_if_test(suite) ->
[];
ip_if_test(Config) when is_list(Config) ->
- ServerRoot = ?config(server_root, Config),
+ ServerRoot = proplists:get_value(server_root, Config),
DocRoot = filename:join([ServerRoot, "htdocs"]),
- httpd_1_1:if_test(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config), DocRoot),
+ httpd_1_1:if_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config), DocRoot),
ok.
%%-------------------------------------------------------------------------
ip_http_trace(doc) ->
@@ -1749,8 +1608,8 @@ ip_http_trace(doc) ->
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)),
+ httpd_1_1:http_trace(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
ip_http1_1_head(doc) ->
@@ -1758,8 +1617,8 @@ ip_http1_1_head(doc) ->
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)),
+ httpd_1_1:head(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
+ proplists:get_value(node, Config)),
ok.
%%-------------------------------------------------------------------------
@@ -1768,8 +1627,8 @@ ip_get_0_9(doc) ->
ip_get_0_9(suite)->
[];
ip_get_0_9(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(node, Config),
ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
"GET / \r\n\r\n",
[{statuscode, 200},
@@ -1791,8 +1650,8 @@ ip_head_1_0(doc) ->
ip_head_1_0(suite)->
[];
ip_head_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(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"}]),
@@ -1804,8 +1663,8 @@ ip_get_1_0(doc) ->
ip_get_1_0(suite)->
[];
ip_get_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(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"}]),
@@ -1817,8 +1676,8 @@ ip_post_1_0(doc) ->
ip_post_1_0(suite)->
[];
ip_post_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
+ Host = proplists:get_value(host, Config),
+ Node = proplists:get_value(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 "
@@ -1832,7 +1691,7 @@ ip_mod_cgi_chunked_encoding_test(doc) ->
ip_mod_cgi_chunked_encoding_test(suite)->
[];
ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
- Host = ?config(host, Config),
+ Host = proplists:get_value(host, Config),
Script =
case test_server:os_type() of
{win32, _} ->
@@ -1846,7 +1705,7 @@ ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
++ Host ++"\r\n\r\n"],
httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT,
Host,
- ?config(node, Config),
+ proplists:get_value(node, Config),
Requests),
ok.
@@ -1875,7 +1734,7 @@ ipv6_hostname(SocketType, Port, Config) when is_list(Config) ->
"~n SocketType: ~p"
"~n Port: ~p"
"~n Config: ~p", [SocketType, Port, Config]),
- Host = ?config(host, Config),
+ Host = proplists:get_value(host, Config),
URI = "GET HTTP://" ++
Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
tsp("ipv6_hostname -> Host: ~p", [Host]),
@@ -1910,7 +1769,7 @@ ipv6_address(SocketType, Port, Config) when is_list(Config) ->
"~n SocketType: ~p"
"~n Port: ~p"
"~n Config: ~p", [SocketType, Port, Config]),
- Host = ?config(host, Config),
+ Host = proplists:get_value(host, Config),
tsp("ipv6_address -> Host: ~p", [Host]),
URI = "GET HTTP://" ++
Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
@@ -1927,8 +1786,8 @@ ticket_5775(doc) ->
ticket_5775(suite) ->
[];
ticket_5775(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
+ ok=httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
+ ?IP_PORT, proplists:get_value(node, Config),
"GET /cgi-bin/erl/httpd_example:get_bin "
"HTTP/1.0\r\n\r\n",
[{statuscode, 200},
@@ -1939,9 +1798,9 @@ ticket_5865(doc) ->
ticket_5865(suite) ->
[];
ticket_5865(Config) ->
- ?SKIP(as_of_r15_behaviour_of_calendar_has_changed),
- Host = ?config(host,Config),
- ServerRoot = ?config(server_root, Config),
+ ct:skip(as_of_r15_behaviour_of_calendar_has_changed),
+ Host = proplists:get_value(host,Config),
+ ServerRoot = proplists:get_value(server_root, Config),
DocRoot = filename:join([ServerRoot, "htdocs"]),
File = filename:join([DocRoot,"last_modified.html"]),
@@ -1957,7 +1816,7 @@ ticket_5865(Config) ->
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),
+ ?IP_PORT, proplists:get_value(node, Config),
"GET /last_modified.html"
" HTTP/1.1\r\nHost:"
++Host++"\r\n\r\n",
@@ -1977,8 +1836,8 @@ 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),
+ ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
+ ?IP_PORT, proplists:get_value(node, Config),
"GET /cgi-bin/erl/httpd_example:get_bin "
"HTTP/1.0\r\n\r\n",
[{statuscode, 200},
@@ -1989,8 +1848,8 @@ 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),
+ ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
+ ?IP_PORT, proplists:get_value(node, Config),
"GET http://www.erlang.org/%skalle "
"HTTP/1.0\r\n\r\n",
[{statuscode, 400},
@@ -2002,8 +1861,8 @@ ticket_7304(doc) ->
ticket_7304(suite) ->
[];
ticket_7304(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
+ ?IP_PORT, proplists:get_value(node, Config),
"GET / HTTP/1.0\r\n\n",
[{statuscode, 200},
{version, "HTTP/1.0"}]),
@@ -2030,11 +1889,11 @@ dos_hostname(Type, Port, Host, Node, Max) ->
%%--------------------------------------------------------------------
%% 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),
+ ServerRoot = proplists:get_value(server_root, Config),
+ TcTopDir = proplists:get_value(tc_top_dir, Config),
+ Port = proplists:get_value(port, Config),
+ Type = proplists:get_value(sock_type, Config),
+ Host = proplists:get_value(host, Config),
Mods = io_lib:format("~p", [httpd_mod]),
Funcs = io_lib:format("~p", [ssl_password_cb]),
MaxHdrSz = io_lib:format("~p", [256]),
@@ -2424,13 +2283,13 @@ create_range_data(Path) ->
"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),
+ ServerRoot = proplists:get_value(server_root, Config),
+ TcTopDir = proplists:get_value(tc_top_dir, Config),
+ Port = proplists:get_value(port, Config),
+ SockType = proplists:get_value(sock_type, Config),
Mods = io_lib:format("~p", [httpd_mod]),
Funcs = io_lib:format("~p", [ssl_password_cb]),
- Host = ?config(ipv6_host, Config),
+ Host = proplists:get_value(ipv6_host, Config),
MaxHdrSz = io_lib:format("~p", [256]),
MaxHdrAct = io_lib:format("~p", [close]),
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
index 4f23295401..ed4d63a3bb 100644
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
index 48e66f0114..7b1b4a15b2 100644
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
@@ -1,7 +1,7 @@
Port 8080
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8080
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
index 79bb7fcca4..042779fcd0 100644
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
@@ -1,7 +1,7 @@
Port 8888
#ServerName your.server.net
SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8888
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
index 87c2973e5a..3add93cd73 100644
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+# Copyright Ericsson AB 1997-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ SocketType ip_comm
# WARNING! Do not tamper with this directive unless you are familiar with
# EWSAPI.
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.
@@ -128,7 +128,7 @@ SecurityDiskLogSize 200000 10
MaxClients 50
-# KeepAlive set the flag for persistent connections. For peristent connections
+# KeepAlive set the flag for persistent connections. For persistent connections
# set KeepAlive to on. To use One request per connection set the flag to off
# Note: The value has changed since previous version of INETS.
KeepAlive on
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
index 8b8c57a98b..de49ceafd0 100644
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
@@ -1,7 +1,7 @@
Port 8088
#ServerName your.server.net
SocketType ssl
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log
+Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
ServerAdmin [email protected]
ServerRoot /var/tmp/server_root
ErrorLog logs/error_log_8088
diff --git a/lib/inets/test/property_test/ftp_simple_client_server.erl b/lib/inets/test/property_test/ftp_simple_client_server.erl
index 8b6aff3c56..c98d87b514 100644
--- a/lib/inets/test/property_test/ftp_simple_client_server.erl
+++ b/lib/inets/test/property_test/ftp_simple_client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/tftp_SUITE.erl b/lib/inets/test/tftp_SUITE.erl
index 497a50e654..09049e36af 100644
--- a/lib/inets/test/tftp_SUITE.erl
+++ b/lib/inets/test/tftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/tftp_test_lib.erl b/lib/inets/test/tftp_test_lib.erl
index 406a49e863..f07795324f 100644
--- a/lib/inets/test/tftp_test_lib.erl
+++ b/lib/inets/test/tftp_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/tftp_test_lib.hrl b/lib/inets/test/tftp_test_lib.hrl
index 4e50f05d04..e7a5a37d2c 100644
--- a/lib/inets/test/tftp_test_lib.hrl
+++ b/lib/inets/test/tftp_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl
index 2642b8fd4e..f973296af6 100644
--- a/lib/inets/test/uri_SUITE.erl
+++ b/lib/inets/test/uri_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-module(uri_SUITE).
+-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
@@ -50,7 +51,8 @@ all() ->
fragments,
escaped,
hexed_query,
- scheme_validation
+ scheme_validation,
+ encode_decode
].
%%--------------------------------------------------------------------
@@ -73,7 +75,10 @@ end_per_testcase(_Case, _Config) ->
ipv4(Config) when is_list(Config) ->
{ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
- http_uri:parse("http://127.0.0.1/foobar.html").
+ http_uri:parse("http://127.0.0.1/foobar.html"),
+
+ {ok, {http,<<>>,<<"127.0.0.1">>,80,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://127.0.0.1/foobar.html">>).
ipv6(Config) when is_list(Config) ->
{ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
@@ -89,24 +94,52 @@ ipv6(Config) when is_list(Config) ->
[{foo, false}]),
{error,
{malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
- http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html").
+ http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
+
+ {ok, {http,<<>>,<<"2010:836B:4179::836B:4179">>,80,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://[2010:836B:4179::836B:4179]/foobar.html">>),
+ {ok, {http,<<>>,<<"[2010:836B:4179::836B:4179]">>,80,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://[2010:836B:4179::836B:4179]/foobar.html">>,
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,<<>>,<<"2010:836B:4179::836B:4179">>,80,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://[2010:836B:4179::836B:4179]/foobar.html">>,
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,<<>>,<<"2010:836B:4179::836B:4179">>,80,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://[2010:836B:4179::836B:4179]/foobar.html">>,
+ [{foo, false}]),
+ {error,
+ {malformed_url, _, <<"http://2010:836B:4179::836B:4179/foobar.html">>}} =
+ http_uri:parse(<<"http://2010:836B:4179::836B:4179/foobar.html">>).
host(Config) when is_list(Config) ->
{ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://localhost:8888/foobar.html").
+ http_uri:parse("http://localhost:8888/foobar.html"),
+
+ {ok, {http,<<>>,<<"localhost">>,8888,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://localhost:8888/foobar.html">>).
userinfo(Config) when is_list(Config) ->
{ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html").
+ http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
+
+ {ok, {http,<<"nisse:foobar">>,<<"localhost">>,8888,<<"/foobar.html">>,<<>>}} =
+ http_uri:parse(<<"http://nisse:foobar@localhost:8888/foobar.html">>).
scheme(Config) when is_list(Config) ->
{error, no_scheme} = http_uri:parse("localhost/foobar.html"),
{error, {malformed_url, _, _}} =
- http_uri:parse("localhost:8888/foobar.html").
+ http_uri:parse("localhost:8888/foobar.html"),
+
+ {error, no_scheme} = http_uri:parse(<<"localhost/foobar.html">>),
+ {error, {malformed_url, _, _}} =
+ http_uri:parse(<<"localhost:8888/foobar.html">>).
queries(Config) when is_list(Config) ->
{ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
- http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42").
+ http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
+
+ {ok, {http,<<>>,<<"localhost">>,8888,<<"/foobar.html">>,<<"?foo=bar&foobar=42">>}} =
+ http_uri:parse(<<"http://localhost:8888/foobar.html?foo=bar&foobar=42">>).
fragments(Config) when is_list(Config) ->
{ok, {http,[],"localhost",80,"/",""}} =
@@ -142,6 +175,41 @@ fragments(Config) when is_list(Config) ->
http_uri:parse("http://localhost?query#", [{fragment,true}]),
{ok, {http,[],"localhost",80,"/path","?query","#"}} =
http_uri:parse("http://localhost/path?query#", [{fragment,true}]),
+
+
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost#fragment">>),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost/path#fragment">>),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>}} =
+ http_uri:parse(<<"http://localhost?query#fragment">>),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>}} =
+ http_uri:parse(<<"http://localhost/path?query#fragment">>),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"#fragment">>}} =
+ http_uri:parse(<<"http://localhost#fragment">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"#fragment">>}} =
+ http_uri:parse(<<"http://localhost/path#fragment">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"#fragment">>}} =
+ http_uri:parse(<<"http://localhost?query#fragment">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"#fragment">>}} =
+ http_uri:parse(<<"http://localhost/path?query#fragment">>,
+ [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost/path">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost?query">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"">>}} =
+ http_uri:parse(<<"http://localhost/path?query">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"#">>}} =
+ http_uri:parse(<<"http://localhost#">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"#">>}} =
+ http_uri:parse(<<"http://localhost/path#">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"#">>}} =
+ http_uri:parse(<<"http://localhost?query#">>, [{fragment,true}]),
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"#">>}} =
+ http_uri:parse(<<"http://localhost/path?query#">>, [{fragment,true}]),
ok.
escaped(Config) when is_list(Config) ->
@@ -152,7 +220,16 @@ escaped(Config) when is_list(Config) ->
{ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
http_uri:parse("http://www.somedomain.com/%25abc"),
{ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
- http_uri:parse("http://www.somedomain.com/%25abc?foo=bar").
+ http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
+
+ {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%2Eabc">>,<<>>}} =
+ http_uri:parse(<<"http://www.somedomain.com/%2Eabc">>),
+ {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%252Eabc">>,<<>>}} =
+ http_uri:parse(<<"http://www.somedomain.com/%252Eabc">>),
+ {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%25abc">>,<<>>}} =
+ http_uri:parse(<<"http://www.somedomain.com/%25abc">>),
+ {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%25abc">>, <<"?foo=bar">>}} =
+ http_uri:parse(<<"http://www.somedomain.com/%25abc?foo=bar">>).
hexed_query(doc) ->
[{doc, "Solves OTP-6191"}];
@@ -196,6 +273,17 @@ scheme_validation(Config) when is_list(Config) ->
http_uri:parse("https://localhost#fragment",
[{scheme_validation_fun, none}]).
+encode_decode(Config) when is_list(Config) ->
+ ?assertEqual("foo%20bar", http_uri:encode("foo bar")),
+ ?assertEqual(<<"foo%20bar">>, http_uri:encode(<<"foo bar">>)),
+
+ ?assertEqual("foo+bar", http_uri:decode("foo+bar")),
+ ?assertEqual(<<"foo+bar">>, http_uri:decode(<<"foo+bar">>)),
+ ?assertEqual("foo bar", http_uri:decode("foo%20bar")),
+ ?assertEqual(<<"foo bar">>, http_uri:decode(<<"foo%20bar">>)),
+ ?assertEqual("foo\r\n", http_uri:decode("foo%0D%0A")),
+ ?assertEqual(<<"foo\r\n">>, http_uri:decode(<<"foo%0D%0A">>)).
+
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 9f1a2c0ee9..560d524bac 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2015. All Rights Reserved.
+# Copyright Ericsson AB 2001-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.2.4.1
+INETS_VSN = 6.4.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"