aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/doc/src/Makefile3
-rw-r--r--lib/inets/doc/src/http_server.xml188
-rw-r--r--lib/inets/doc/src/httpc.xml2
-rw-r--r--lib/inets/doc/src/httpd.xml33
-rw-r--r--lib/inets/doc/src/httpd_custom_api.xml63
-rw-r--r--lib/inets/doc/src/notes.xml18
-rw-r--r--lib/inets/doc/src/ref_man.xml3
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_random_html.erl7
-rw-r--r--lib/inets/src/ftp/ftp.erl12
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl40
-rw-r--r--lib/inets/src/http_server/Makefile4
-rw-r--r--lib/inets/src/http_server/httpd.erl116
-rw-r--r--lib/inets/src/http_server/httpd_acceptor_sup.erl36
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl312
-rw-r--r--lib/inets/src/http_server/httpd_custom.erl69
-rw-r--r--lib/inets/src/http_server/httpd_example.erl4
-rw-r--r--lib/inets/src/http_server/httpd_instance_sup.erl60
-rw-r--r--lib/inets/src/http_server/httpd_internal.hrl2
-rw-r--r--lib/inets/src/http_server/httpd_manager.erl23
-rw-r--r--lib/inets/src/http_server/httpd_misc_sup.erl38
-rw-r--r--lib/inets/src/http_server/httpd_request.erl140
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl11
-rw-r--r--lib/inets/src/http_server/httpd_response.erl52
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl68
-rw-r--r--lib/inets/src/http_server/httpd_util.erl15
-rw-r--r--lib/inets/src/http_server/mod_actions.erl4
-rw-r--r--lib/inets/src/http_server/mod_alias.erl6
-rw-r--r--lib/inets/src/http_server/mod_auth.erl670
-rw-r--r--lib/inets/src/http_server/mod_auth_dets.erl46
-rw-r--r--lib/inets/src/http_server/mod_auth_plain.erl192
-rw-r--r--lib/inets/src/http_server/mod_auth_server.erl240
-rw-r--r--lib/inets/src/http_server/mod_cgi.erl8
-rw-r--r--lib/inets/src/http_server/mod_disk_log.erl42
-rw-r--r--lib/inets/src/http_server/mod_esi.erl16
-rw-r--r--lib/inets/src/http_server/mod_htaccess.erl2
-rw-r--r--lib/inets/src/http_server/mod_include.erl598
-rw-r--r--lib/inets/src/http_server/mod_log.erl8
-rw-r--r--lib/inets/src/http_server/mod_security.erl234
-rw-r--r--lib/inets/src/http_server/mod_security_server.erl359
-rw-r--r--lib/inets/src/inets_app/Makefile6
-rw-r--r--lib/inets/src/inets_app/inets.app.src8
-rw-r--r--lib/inets/src/inets_app/inets_lib.erl49
-rw-r--r--lib/inets/src/inets_app/inets_time_compat.erl71
-rw-r--r--lib/inets/src/inets_app/inets_trace.erl32
-rw-r--r--lib/inets/src/tftp/tftp_logger.erl6
-rw-r--r--lib/inets/src/tftp/tftp_sup.erl4
-rw-r--r--lib/inets/test/erl_make_certs.erl10
-rw-r--r--lib/inets/test/ftp_suite_lib.erl8
-rw-r--r--lib/inets/test/httpc_SUITE.erl67
-rw-r--r--lib/inets/test/httpc_proxy_SUITE.erl4
-rw-r--r--lib/inets/test/httpd_SUITE.erl105
-rw-r--r--lib/inets/test/httpd_SUITE_data/server_root/config/mime.types4
-rw-r--r--lib/inets/test/httpd_block.erl2
-rw-r--r--lib/inets/test/httpd_time_test.erl49
-rw-r--r--lib/inets/test/inets_SUITE.erl19
-rw-r--r--lib/inets/test/inets_app_test.erl67
-rw-r--r--lib/inets/test/inets_sup_SUITE.erl226
-rw-r--r--lib/inets/test/inets_test_lib.erl23
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl6
-rw-r--r--lib/inets/vsn.mk4
60 files changed, 1775 insertions, 2739 deletions
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index 1a8e1c7ca8..961bfa838d 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2015. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -52,6 +52,7 @@ XML_REF3_FILES = \
httpc.xml\
httpd.xml \
httpd_conf.xml \
+ httpd_custom_api.xml \
httpd_socket.xml \
httpd_util.xml \
mod_alias.xml \
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index e3b763b4f3..65e89db391 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -46,8 +46,7 @@
Layer), ESI (Erlang Scripting Interface), CGI (Common Gateway
Interface), User Authentication(using Mnesia, dets or plain text
database), Common Logfile Format (with or without disk_log(3)
- support), URL Aliasing, Action Mappings, Directory Listings and SSI
- (Server-Side Includes).</p>
+ support), URL Aliasing, Action Mappings, and Directory Listings</p>
<p>The configuration of the server is provided as an erlang
property list, and for backwards compatibility also a configuration
@@ -478,170 +477,9 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
</p>
<p><em>[date]</em> access to <em>path</em> failed for
<em>remotehost</em>, reason: <em>reason</em></p>
-
- <marker id="ssi"></marker>
</section>
-
+
<section>
- <title>Server Side Includes</title>
- <p>Server Side Includes enables the server to run code embedded
- in HTML pages to generate the response to the client.</p>
- <note>
- <p>Having the server parse HTML pages is a double edged sword!
- It can be costly for a heavily loaded server to perform
- parsing of HTML pages while sending them. Furthermore, it can
- be considered a security risk to have average users executing
- commands in the name of the Erlang node user. Carefully
- consider these items before activating server-side includes.</p>
- </note>
-
- <section>
- <marker id="ssi_setup"></marker>
- <title>SERVER-SIDE INCLUDES (SSI) SETUP</title>
- <p>The server must be told which filename extensions to be used
- for the parsed files. These files, while very similar to HTML,
- are not HTML and are thus not treated the same. Internally, the
- server uses the magic MIME type <c>text/x-server-parsed-html</c>
- to identify parsed documents. It will then perform a format
- conversion to change these files into HTML for the
- client. Update the <c>mime.types</c> file, as described in the
- Mime Type Settings, to tell the server which extension to use
- for parsed files, for example:
- </p>
- <pre>
- text/x-server-parsed-html shtml shtm
- </pre>
- <p>This makes files ending with <c>.shtml</c> and <c>.shtm</c>
- into parsed files. Alternatively, if the performance hit is not a
- problem, <em>all</em> HTML pages can be marked as parsed:
- </p>
- <pre>
- text/x-server-parsed-html html htm
- </pre>
- </section>
-
- <section>
- <marker id="ssi_format"></marker>
- <title>Server-Side Includes (SSI) Format</title>
- <p>All server-side include directives to the server are formatted
- as SGML comments within the HTML page. This is in case the
- document should ever find itself in the client's hands
- unparsed. Each directive has the following format:
- </p>
- <pre>
- &lt;!--#command tag1="value1" tag2="value2" --&gt;
- </pre>
- <p>Each command takes different arguments, most only accept one
- tag at a time. Here is a breakdown of the commands and their
- associated tags:
- </p>
- <p>The config directive controls various aspects of the
- file parsing. There are two valid tags:
- </p>
- <taglist>
- <tag><c>errmsg</c></tag>
- <item>
- <p>controls the message sent back to the client if an
- error occurred while parsing the document. All errors are
- logged in the server's error log.</p>
- </item>
- <tag><c>sizefmt</c></tag>
- <item>
- <p>determines the format used to display the size of
- a file. Valid choices are <c>bytes</c> or
- <c>abbrev</c>. <c>bytes</c> for a formatted byte count
- or <c>abbrev</c> for an abbreviated version displaying
- the number of kilobytes.</p>
- </item>
- </taglist>
- <p>The include directory
- will insert the text of a document into the parsed
- document. This command accepts two tags:</p>
- <taglist>
- <tag><c>virtual</c></tag>
- <item>
- <p>gives a virtual path to a document on the
- server. Only normal files and other parsed documents can
- be accessed in this way.</p>
- </item>
- <tag><c>file</c></tag>
- <item>
- <p>gives a pathname relative to the current
- directory. <c>../</c> cannot be used in this pathname, nor
- can absolute paths. As above, you can send other parsed
- documents, but you cannot send CGI scripts.</p>
- </item>
- </taglist>
- <p>The echo directive prints the value of one of the include
- variables (defined below). The only valid tag to this
- command is <c>var</c>, whose value is the name of the
- variable you wish to echo.</p>
- <p>The fsize directive prints the size of the specified
- file. Valid tags are the same as with the <c>include</c>
- command. The resulting format of this command is subject
- to the <c>sizefmt</c> parameter to the <c>config</c>
- command.</p>
- <p>The lastmod directive prints the last modification date of
- the specified file. Valid tags are the same as with the
- <c>include</c> command.</p>
- <p>The exec directive executes a given shell command or CGI
- script. Valid tags are:</p>
- <taglist>
- <tag><c>cmd</c></tag>
- <item>
- <p>executes the given string using <c>/bin/sh</c>. All
- of the variables defined below are defined, and can be
- used in the command.</p>
- </item>
- <tag><c>cgi</c></tag>
- <item>
- <p>executes the given virtual path to a CGI script and
- includes its output. The server does not perform error
- checking on the script output.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <marker id="ssi_environment_variables"></marker>
- <title>Server-Side Includes (SSI) Environment Variables</title>
- <p>A number of variables are made available to parsed
- documents. In addition to the CGI variable set, the following
- variables are made available:
- </p>
- <taglist>
- <tag><c>DOCUMENT_NAME</c></tag>
- <item>
- <p>The current filename.</p>
- </item>
- <tag><c>DOCUMENT_URI</c></tag>
- <item>
- <p>The virtual path to this document (such as
- <c>/docs/tutorials/foo.shtml</c>).</p>
- </item>
- <tag><c>QUERY_STRING_UNESCAPED</c></tag>
- <item>
- <p>The unescaped version of any search query the client
- sent, with all shell-special characters escaped with
- <c>\</c>.</p>
- </item>
- <tag><c>DATE_LOCAL</c></tag>
- <item>
- <p>The current date, local time zone.</p>
- </item>
- <tag><c>DATE_GMT</c></tag>
- <item>
- <p>Same as DATE_LOCAL but in Greenwich mean time.</p>
- </item>
- <tag><c>LAST_MODIFIED</c></tag>
- <item>
- <p>The last modification date of the current document.</p>
- </item>
- </taglist>
- </section>
- </section>
-
- <section>
<title>The Erlang Web Server API</title>
<p>The process of handling a HTTP request involves several steps
such as:</p>
@@ -907,28 +745,6 @@ start() ->
</taglist>
</section>
- <section>
- <title>mod_include - SSI</title>
- <p>This module makes it possible to expand "macros" embedded in
- HTML pages before they are delivered to the client, that is
- Server-Side Includes (SSI).
- </p>
- <p>Uses the following Erlang Webserver API interaction data:
- </p>
- <list type="bulleted">
- <item>real_name - from mod_alias</item>
- <item>remote_user - from mod_auth</item>
- </list>
- <p>Exports the following Erlang Webserver API interaction data:
- </p>
- <taglist>
- <tag><c>{mime_type, MimeType}</c></tag>
- <item>The file suffix of the incoming URL mapped into a
- <c>MimeType</c> as defined in the Mime Type Settings
- section.</item>
- </taglist>
- </section>
-
<section>
<title>mod_log - Logging Using Text Files.</title>
<p>Standard logging using the "Common Logfile Format" and text
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 4178cb7d4c..6984408932 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -366,7 +366,7 @@ filename() = string()
<tag><c><![CDATA[receiver]]></c></tag>
<item>
<p>Defines how the client will deliver the result of an
- asynchroneous request (<c>sync</c> has the value
+ asynchronous request (<c>sync</c> has the value
<c>false</c>). </p>
<taglist>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index e40660ab39..e6aa8d5e07 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -162,6 +162,20 @@
in the apache like configuration file. </p>
</item>
+ <marker id="profile"></marker>
+ <tag>{profile, atom()}</tag>
+ <item>
+ <p>Used together with <seealso marker="prop_bind_address"><c>bind_address</c></seealso>
+ and <seealso marker="prop_port"><c>port</c></seealso> to uniquely identify
+ a HTTP server. This can be useful in a virtualized environment,
+ where there can
+ be more that one server that has the same bind_address and port.
+ If this property is not explicitly set, it is assumed that the
+ <seealso marker="prop_bind_address"><c>bind_address</c></seealso> and
+ <seealso marker="prop_port"><c>port</c></seealso>uniquely identifies the HTTP server.
+ </p>
+ </item>
+
<marker id="prop_socket_type"></marker>
<tag>{socket_type, ip_comm | {essl, Config::proplist()}}</tag>
<item>
@@ -176,6 +190,8 @@
<p>Note that this option is only used when the option
<c>socket_type</c> has the value <c>ip_comm</c>. </p>
</item>
+
+
<marker id="prop_minimum_bytes_per_second"></marker>
<tag>{minimum_bytes_per_second, integer()}</tag>
<item>
@@ -204,7 +220,15 @@
<marker id="props_limit"></marker>
<p><em>Limit properties</em> </p>
- <taglist>
+ <taglist>
+
+ <marker id="prop_customize"></marker>
+ <tag>{customize, atom()}</tag>
+ <item>
+ <p>A callback module to customize the inets HTTP servers behaviour
+ see <seealso marker="http_custom_api"> httpd_custom_api</seealso> </p>
+ </item>
+
<marker id="prop_disable_chunked_encoding"></marker>
<tag>{disable_chunked_transfer_encoding_send, boolean()}</tag>
<item>
@@ -927,19 +951,22 @@ bytes
<func>
<marker id="info2"></marker>
<name>info(Address, Port) -> </name>
+ <name>info(Address, Port, Profile) -> </name>
+ <name>info(Address, Port, Profile, Properties) -> [{Option, Value}] </name>
<name>info(Address, Port, Properties) -> [{Option, Value}] </name>
<fsummary>Fetches information about the HTTP server</fsummary>
<type>
<v>Address = ip_address()</v>
<v>Port = integer()</v>
+ <v>Profile = atom()</v>
<v>Properties = [property()]</v>
<v>Option = property()</v>
<v>Value = term()</v>
</type>
<desc>
<p>Fetches information about the HTTP server. When called with
- only the Address and Port all properties are fetched, when
- called with a list of specific properties they are fetched.
+ only the Address, Port and Profile, if relevant, all properties are fetched.
+ When called with a list of specific properties they are fetched.
Available properties are the same as the server's start
options.
</p>
diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml
new file mode 100644
index 0000000000..faf1d277df
--- /dev/null
+++ b/lib/inets/doc/src/httpd_custom_api.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2015</year><year>2015</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>httpd_custom_api</title>
+ <file>httpd_custom_api.xml</file>
+ </header>
+ <module>httpd_custom_api</module>
+ <modulesummary>Behaviour with optional callbacks to customize the inets HTTP server.</modulesummary>
+ <description>
+ <p> The module implementing this behaviour shall be supplied to to the servers
+ configuration with the option <seealso marker="httpd:prop_customize"> customize</seealso></p>
+
+ </description>
+ <funcs>
+ <func>
+ <name>response_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
+ <fsummary>Filter and possible alter HTTP response headers.</fsummary>
+ <type>
+ <v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
+ <d>The header name will be in lower case and should not be altered.</d>
+ </type>
+ <desc>
+ <p> Filter and possible alter HTTP response headers before they are sent to the client.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>request_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
+ <fsummary>Filter and possible alter HTTP request headers.</fsummary>
+ <type>
+ <v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
+ <d>The header name will be in lower case and should not be altered.</d>
+ </type>
+ <desc>
+ <p> Filter and possible alter HTTP request headers before they are processed by the server.
+ </p>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
+
+
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index bae8e327a3..f563a8c4b0 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -32,7 +32,23 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 5.10.8</title>
+ <section><title>Inets 5.10.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add behaviour with optional callbacks to customize the
+ inets HTTP server.</p>
+ <p>
+ Own Id: OTP-12776</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 5.10.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml
index aaedf330b4..3afb020431 100644
--- a/lib/inets/doc/src/ref_man.xml
+++ b/lib/inets/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,6 +39,7 @@
<xi:include href="httpc.xml"/>
<xi:include href="httpd.xml"/>
<xi:include href="httpd_conf.xml"/>
+ <xi:include href="httpd_custom_api.xml"/>
<xi:include href="httpd_socket.xml"/>
<xi:include href="httpd_util.xml"/>
<xi:include href="mod_alias.xml"/>
diff --git a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl b/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
index e3a572c61f..59073a3d23 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,10 @@ stop() ->
".
content(WorkSim, SzSim) ->
- {A, B, C} = now(),
+ {A, B, C} = {erlang:phash2([node()]),
+ inets_time_compat:monotonic_time(),
+ inets_time_compat:unique_integer()},
+
random:seed(A, B, C),
lists:sort([random:uniform(X) || X <- lists:seq(1, WorkSim)]),
lists:flatten(lists:duplicate(SzSim, "Dummy data ")).
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index 8e51b1be5a..7eebe8d5bf 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2176,16 +2176,16 @@ 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 = millisec_time(),
+ MsTime = inets_time_compat:monotonic_time(),
case connect(Host, Port, Timeout, State) of
{ok, IpFam, CSock} ->
NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
activate_ctrl_connection(NewState),
- case Timeout - (millisec_time() - MsTime) of
+ case Timeout - inets_lib:millisec_passed(MsTime) of
Timeout2 when (Timeout2 >= 0) ->
{ok, NewState#state{caller = open}, Timeout2};
_ ->
- %% Oups: Simulate timeout
+ %% Oups: Simulate timeout
{ok, NewState#state{caller = open}, 0}
end;
Error ->
@@ -2501,10 +2501,6 @@ progress_report(Report, #state{progress = ProgressPid}) ->
ftp_progress:report(ProgressPid, Report).
-millisec_time() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
peername({tcp, Socket}) -> inet:peername(Socket);
peername({ssl, Socket}) -> ssl:peername(Socket).
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 0bbd40d656..ce9a0e3d26 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -87,7 +87,7 @@
%% block the httpc manager process in odd cases such as trying to call
%% a server that does not exist. (See OTP-6735) The only API function
%% sending messages to the handler process that can be called before
-%% init has compleated is cancel and that is not a problem! (Send and
+%% init has completed is cancel and that is not a problem! (Send and
%% stream will not be called before the first request has been sent and
%% the reply or part of it has arrived.)
%%--------------------------------------------------------------------
@@ -316,8 +316,9 @@ handle_call(#request{address = Addr} = Request, _,
{reply, ok, State}
end;
{error, Reason} ->
- ?hcri("failed sending request", [{reason, Reason}]),
- {reply, {pipeline_failed, Reason}, State0}
+ ?hcri("failed sending request", [{reason, Reason}]),
+ NewPipeline = queue:in(Request, State0#state.pipeline),
+ {stop, shutdown, {pipeline_failed, Reason}, State0#state{pipeline = NewPipeline}}
end;
handle_call(#request{address = Addr} = Request, _,
@@ -355,25 +356,25 @@ handle_call(#request{address = Addr} = Request, _,
?hcrd("no current request", []),
cancel_timer(Timers#timers.queue_timer,
timeout_queue),
+ NewTimers = Timers#timers{queue_timer = undefined},
+ State1 = State0#state{timers = NewTimers},
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
- State1 =
- activate_request_timeout(State0#state{request = Request}),
- NewTimers = State1#state.timers,
+ State2 =
+ activate_request_timeout(State1#state{request = Request}),
NewSession =
Session#session{queue_length = 1,
client_close = ClientClose},
insert_session(NewSession, ProfileName),
- State = init_wait_for_response_state(Request, State1#state{session = NewSession,
- timers = NewTimers}),
+ State = init_wait_for_response_state(Request, State2#state{session = NewSession}),
{reply, ok, State};
{error, Reason} ->
?hcri("failed sending request", [{reason, Reason}]),
- {reply, {request_failed, Reason}, State0}
+ {stop, shutdown, {keepalive_failed, Reason}, State1}
end
end;
@@ -391,7 +392,7 @@ handle_call(info, _, State) ->
%% 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
-%% based on the assumption that it is proably cheaper to reissue the
+%% based on the assumption that it is probably cheaper to reissue the
%% requests than to wait for a potentiall large response that we then
%% only throw away. This of course is not always true maybe we could
%% do something smarter here?! If the request canceled is not
@@ -1121,7 +1122,7 @@ handle_http_body(Body, #state{headers = Headers,
handle_response(State#state{headers = NewHeaders,
body = NewBody});
_ ->
- {NewBody2, NewRequest} =
+ {NewBody2, _NewRequest} =
stream(NewBody, Request, Code),
handle_response(State#state{headers = NewHeaders,
body = NewBody2})
@@ -1301,7 +1302,8 @@ handle_pipeline(#state{status = pipeline,
handle_keep_alive_queue(#state{status = keep_alive,
session = Session,
profile_name = ProfileName,
- options = #options{keep_alive_timeout = TimeOut}} = State,
+ options = #options{keep_alive_timeout = TimeOut,
+ proxy = Proxy}} = State,
Data) ->
?hcrd("handle keep_alive", [{profile, ProfileName},
@@ -1322,14 +1324,15 @@ handle_keep_alive_queue(#state{status = keep_alive,
State#state{keep_alive = KeepAlive}, Data);
false ->
?hcrv("next request", [{request, NextRequest}]),
- #request{address = Address} = NextRequest,
+ #request{address = Addr} = NextRequest,
+ Address = handle_proxy(Addr, Proxy),
case httpc_request:send(Address, Session, NextRequest) of
ok ->
receive_response(NextRequest,
Session, <<>>,
State#state{keep_alive = KeepAlive});
{error, Reason} ->
- {reply, {keep_alive_failed, Reason}, State}
+ {stop, {shutdown, {keepalive_failed, Reason}}, State}
end
end
end.
@@ -1344,7 +1347,7 @@ handle_empty_queue(Session, ProfileName, TimeOut, State) ->
%% 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 initilized when a new request
+ %% Note mfa will be initialized when a new request
%% arrives.
{noreply,
NewState#state{request = undefined,
@@ -1387,6 +1390,8 @@ case_insensitive_header(Str) ->
activate_once(#session{socket = Socket, socket_type = SocketType}) ->
http_transport:setopts(SocketType, Socket, [{active, once}]).
+close_socket(#session{socket = {remote_close,_}}) ->
+ ok;
close_socket(#session{socket = Socket, socket_type = SocketType}) ->
http_transport:close(SocketType, Socket).
@@ -1850,6 +1855,7 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
Session2 = erlang:setelement(Pos, Session, Value),
insert_session(Session2, ProfileName);
T:E ->
+ Stacktrace = erlang:get_stacktrace(),
error_logger:error_msg("Failed updating session: "
"~n ProfileName: ~p"
"~n SessionId: ~p"
@@ -1873,7 +1879,7 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
{value, Value},
{etype, T},
{error, E},
- {stacktrace, erlang:get_stacktrace()}]})
+ {stacktrace, Stacktrace}]})
end.
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index 2660d04d16..00bad51ff9 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2013. All Rights Reserved.
+# Copyright Ericsson AB 2005-2015. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -46,6 +46,7 @@ MODULES = \
httpd_connection_sup\
httpd_cgi \
httpd_conf \
+ httpd_custom \
httpd_example \
httpd_esi \
httpd_file\
@@ -75,7 +76,6 @@ MODULES = \
mod_get \
mod_head \
mod_htaccess \
- mod_include \
mod_log \
mod_range \
mod_responsecontrol \
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index e8148ea362..71be6dde00 100644
--- a/lib/inets/src/http_server/httpd.erl
+++ b/lib/inets/src/http_server/httpd.erl
@@ -23,6 +23,7 @@
-behaviour(inets_service).
-include("httpd.hrl").
+-include("httpd_internal.hrl").
%% Behavior callbacks
-export([
@@ -61,18 +62,27 @@ info(Pid, Properties) when is_pid(Pid) andalso is_list(Properties) ->
{ok, ServiceInfo} = service_info(Pid),
Address = proplists:get_value(bind_address, ServiceInfo),
Port = proplists:get_value(port, ServiceInfo),
+ Profile = proplists:get_value(profile, ServiceInfo, default),
case Properties of
[] ->
- info(Address, Port);
+ info(Address, Port, Profile);
_ ->
- info(Address, Port, Properties)
+ info(Address, Port, Profile, Properties)
end;
+
info(Address, Port) when is_integer(Port) ->
- httpd_conf:get_config(Address, Port).
+ info(Address, Port, default).
+
+info(Address, Port, Profile) when is_integer(Port), is_atom(Profile) ->
+ httpd_conf:get_config(Address, Port, Profile);
info(Address, Port, Properties) when is_integer(Port) andalso
is_list(Properties) ->
- httpd_conf:get_config(Address, Port, Properties).
+ httpd_conf:get_config(Address, Port, default, Properties).
+
+info(Address, Port, Profile, Properties) when is_integer(Port) andalso
+ is_atom(Profile) andalso is_list(Properties) ->
+ httpd_conf:get_config(Address, Port, Profile, Properties).
%%%========================================================================
@@ -86,14 +96,16 @@ start_service(Conf) ->
httpd_sup:start_child(Conf).
stop_service({Address, Port}) ->
- httpd_sup:stop_child(Address, Port);
-
+ stop_service({Address, Port, ?DEFAULT_PROFILE});
+stop_service({Address, Port, Profile}) ->
+ httpd_sup:stop_child(Address, Port, Profile);
stop_service(Pid) when is_pid(Pid) ->
case service_info(Pid) of
{ok, Info} ->
Address = proplists:get_value(bind_address, Info),
Port = proplists:get_value(port, Info),
- stop_service({Address, Port});
+ Profile = proplists:get_value(profile, Info, ?DEFAULT_PROFILE),
+ stop_service({Address, Port, Profile});
Error ->
Error
end.
@@ -101,7 +113,6 @@ stop_service(Pid) when is_pid(Pid) ->
services() ->
[{httpd, ChildPid} || {_, ChildPid, _, _} <-
supervisor:which_children(httpd_sup)].
-
service_info(Pid) ->
try
[{ChildName, ChildPid} ||
@@ -114,7 +125,6 @@ service_info(Pid) ->
{error, service_not_available}
end.
-
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -128,12 +138,12 @@ child_name(Pid, [_ | Children]) ->
child_name2info(undefined) ->
{error, no_such_service};
-child_name2info({httpd_instance_sup, any, Port}) ->
+child_name2info({httpd_instance_sup, any, Port, Profile}) ->
{ok, Host} = inet:gethostname(),
- Info = info(any, Port, [server_name]),
+ Info = info(any, Port, Profile, [server_name]),
{ok, [{bind_address, any}, {host, Host}, {port, Port} | Info]};
-child_name2info({httpd_instance_sup, Address, Port}) ->
- Info = info(Address, Port, [server_name]),
+child_name2info({httpd_instance_sup, Address, Port, Profile}) ->
+ Info = info(Address, Port, Profile, [server_name]),
case inet:gethostbyaddr(Address) of
{ok, {_, Host, _, _,_, _}} ->
{ok, [{bind_address, Address},
@@ -143,8 +153,8 @@ child_name2info({httpd_instance_sup, Address, Port}) ->
end.
-reload(Config, Address, Port) ->
- Name = make_name(Address,Port),
+reload(Config, Address, Port, Profile) ->
+ Name = make_name(Address,Port, Profile),
case whereis(Name) of
Pid when is_pid(Pid) ->
httpd_manager:reload(Pid, Config);
@@ -191,51 +201,19 @@ reload(Config, Address, Port) ->
%%% Timeout -> integer()
%%%
-block(Addr, Port, disturbing) when is_integer(Port) ->
- do_block(Addr, Port, disturbing);
-block(Addr, Port, non_disturbing) when is_integer(Port) ->
- do_block(Addr, Port, non_disturbing);
-
-block(ConfigFile, Mode, Timeout)
- when is_list(ConfigFile) andalso
- is_atom(Mode) andalso
- is_integer(Timeout) ->
- case get_addr_and_port(ConfigFile) of
- {ok, Addr, Port} ->
- block(Addr, Port, Mode, Timeout);
- Error ->
- Error
- end.
-
-
-block(Addr, Port, non_disturbing, Timeout)
- when is_integer(Port) andalso is_integer(Timeout) ->
- do_block(Addr, Port, non_disturbing, Timeout);
-block(Addr,Port,disturbing,Timeout)
- when is_integer(Port) andalso is_integer(Timeout) ->
- do_block(Addr, Port, disturbing, Timeout).
-
-do_block(Addr, Port, Mode) when is_integer(Port) andalso is_atom(Mode) ->
- Name = make_name(Addr,Port),
+block(Addr, Port, Profile, disturbing) when is_integer(Port) ->
+ do_block(Addr, Port, Profile, disturbing);
+block(Addr, Port, Profile, non_disturbing) when is_integer(Port) ->
+ do_block(Addr, Port, Profile, non_disturbing).
+do_block(Addr, Port, Profile, Mode) when is_integer(Port) andalso is_atom(Mode) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
Pid when is_pid(Pid) ->
- httpd_manager:block(Pid,Mode);
+ httpd_manager:block(Pid, Mode);
_ ->
{error,not_started}
end.
-
-do_block(Addr, Port, Mode, Timeout)
- when is_integer(Port) andalso is_atom(Mode) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:block(Pid,Mode,Timeout);
- _ ->
- {error,not_started}
- end.
-
-
%%% =========================================================
%%% Function: unblock/2
%%% unblock(Addr, Port)
@@ -248,8 +226,8 @@ do_block(Addr, Port, Mode, Timeout)
%%% ConfigFile -> string()
%%%
-unblock(Addr, Port) when is_integer(Port) ->
- Name = make_name(Addr,Port),
+unblock(Addr, Port, Profile) when is_integer(Port) ->
+ Name = make_name(Addr,Port, Profile),
case whereis(Name) of
Pid when is_pid(Pid) ->
httpd_manager:unblock(Pid);
@@ -269,24 +247,9 @@ foreach([KeyValue|Rest]) ->
foreach(Rest)
end.
-get_addr_and_port(ConfigFile) ->
- case httpd_conf:load(ConfigFile) of
- {ok, ConfigList} ->
- case (catch httpd_conf:validate_properties(ConfigList)) of
- {ok, Config} ->
- Address = proplists:get_value(bind_address, Config, any),
- Port = proplists:get_value(port, Config, 80),
- {ok, Address, Port};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
-
-make_name(Addr, Port) ->
- httpd_util:make_name("httpd", Addr, Port).
+make_name(Addr, Port, Profile) ->
+ httpd_util:make_name("httpd", Addr, Port, Profile).
do_reload_config(ConfigList, Mode) ->
@@ -294,10 +257,11 @@ do_reload_config(ConfigList, Mode) ->
{ok, Config} ->
Address = proplists:get_value(bind_address, Config, any),
Port = proplists:get_value(port, Config, 80),
- case block(Address, Port, Mode) of
+ Profile = proplists:get_value(profile, Config, default),
+ case block(Address, Port, Profile, Mode) of
ok ->
- reload(Config, Address, Port),
- unblock(Address, Port);
+ reload(Config, Address, Port, Profile),
+ unblock(Address, Port, Profile);
Error ->
Error
end;
diff --git a/lib/inets/src/http_server/httpd_acceptor_sup.erl b/lib/inets/src/http_server/httpd_acceptor_sup.erl
index cc2b582b52..a6a0fe2eea 100644
--- a/lib/inets/src/http_server/httpd_acceptor_sup.erl
+++ b/lib/inets/src/http_server/httpd_acceptor_sup.erl
@@ -26,6 +26,8 @@
-behaviour(supervisor).
+-include("httpd_internal.hrl").
+
%% API
-export([start_link/1]).
%%, start_acceptor/6, start_acceptor/7, stop_acceptor/2]).
@@ -36,8 +38,9 @@
%%%=========================================================================
%%% API
%%%=========================================================================
-start_link([Addr, Port| _] = Args) ->
- SupName = make_name(Addr, Port),
+start_link([Addr, Port, Config| _] = Args) ->
+ Profile = proplists:get_value(profile, Config, ?DEFAULT_PROFILE),
+ SupName = make_name(Addr, Port, Profile),
supervisor:start_link({local, SupName}, ?MODULE, [Args]).
%%%=========================================================================
@@ -54,20 +57,23 @@ init([Args]) ->
%%% Internal functions
%%%=========================================================================
child_spec([Address, Port, ConfigList, AcceptTimeout, ListenInfo]) ->
- Name = id(Address, Port),
- Manager = httpd_util:make_name("httpd", Address, Port),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
+ Name = id(Address, Port, Profile),
+ Manager = httpd_util:make_name("httpd", Address, Port, Profile),
SockType = proplists:get_value(socket_type, ConfigList, ip_comm),
IpFamily = proplists:get_value(ipfamily, ConfigList, inet),
StartFunc = case ListenInfo of
undefined ->
- {httpd_acceptor, start_link, [Manager, SockType, Address, Port, IpFamily,
- httpd_util:make_name("httpd_conf", Address, Port),
- AcceptTimeout]};
+ {httpd_acceptor, start_link,
+ [Manager, SockType, Address, Port, IpFamily,
+ httpd_util:make_name("httpd_conf", Address, Port, Profile),
+ AcceptTimeout]};
_ ->
- {httpd_acceptor, start_link, [Manager, SockType, Address, Port, ListenInfo,
- IpFamily,
- httpd_util:make_name("httpd_conf", Address, Port),
- AcceptTimeout]}
+ {httpd_acceptor, start_link,
+ [Manager, SockType, Address, Port, ListenInfo,
+ IpFamily,
+ httpd_util:make_name("httpd_conf", Address, Port, Profile),
+ AcceptTimeout]}
end,
Restart = transient,
Shutdown = brutal_kill,
@@ -75,9 +81,9 @@ child_spec([Address, Port, ConfigList, AcceptTimeout, ListenInfo]) ->
Type = worker,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-id(Address, Port) ->
- {httpd_acceptor_sup, Address, Port}.
+id(Address, Port, Profile) ->
+ {httpd_acceptor_sup, Address, Port, Profile}.
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_acceptor_sup", Addr, Port).
+make_name(Addr, Port, Profile) ->
+ httpd_util:make_name("httpd_acceptor_sup", Addr, Port, Profile).
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index dbdc1be272..89a7e96f3e 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -19,141 +19,29 @@
%%
-module(httpd_conf).
-%% EWSAPI
--export([is_directory/1, is_file/1, make_integer/1, clean/1,
- custom_clean/3, check_enum/2]).
-
%% Application internal API
-export([load/1, load/2, load_mime_types/1, store/1, store/2,
- remove/1, remove_all/1, get_config/2, get_config/3,
+ remove/1, remove_all/1, get_config/3, get_config/4,
lookup_socket_type/1,
lookup/2, lookup/3, lookup/4,
- validate_properties/1]).
+ validate_properties/1, white_space_clean/1]).
+
+%% Deprecated
+-export([is_directory/1, is_file/1, make_integer/1, clean/1,
+ custom_clean/3, check_enum/2]).
+
+-deprecated({is_directory, 1, next_major_release}).
+-deprecated({is_file, 1, next_major_release}).
+-deprecated({make_integer, 1, next_major_release}).
+-deprecated({clean, 1, next_major_release}).
+-deprecated({custom_clean, 3, next_major_release}).
+-deprecated({check_enum, 2, next_major_release}).
-define(VMODULE,"CONF").
-include("httpd_internal.hrl").
-include("httpd.hrl").
-include_lib("inets/src/http_lib/http_internal.hrl").
-
-%%%=========================================================================
-%%% EWSAPI
-%%%=========================================================================
-%%-------------------------------------------------------------------------
-%% is_directory(FilePath) -> Result
-%% FilePath = string()
-%% Result = {ok,Directory} | {error,Reason}
-%% Directory = string()
-%% Reason = string() | enoent | eacces | enotdir | FileInfo
-%% FileInfo = File info record
-%%
-%% Description: Checks if FilePath is a directory in which case it is
-%% returned.
-%%-------------------------------------------------------------------------
-is_directory(Directory) ->
- case file:read_file_info(Directory) of
- {ok,FileInfo} ->
- #file_info{type = Type, access = Access} = FileInfo,
- is_directory(Type,Access,FileInfo,Directory);
- {error,Reason} ->
- {error,Reason}
- end.
-is_directory(directory,read,_FileInfo,Directory) ->
- {ok,Directory};
-is_directory(directory,read_write,_FileInfo,Directory) ->
- {ok,Directory};
-is_directory(_Type,_Access,FileInfo,_Directory) ->
- {error,FileInfo}.
-
-
-%%-------------------------------------------------------------------------
-%% is_file(FilePath) -> Result
-%% FilePath = string()
-%% Result = {ok,File} | {error,Reason}
-%% File = string()
-%% Reason = string() | enoent | eacces | enotdir | FileInfo
-%% FileInfo = File info record
-%%
-%% Description: Checks if FilePath is a regular file in which case it
-%% is returned.
-%%-------------------------------------------------------------------------
-is_file(File) ->
- case file:read_file_info(File) of
- {ok,FileInfo} ->
- #file_info{type = Type, access = Access} = FileInfo,
- is_file(Type,Access,FileInfo,File);
- {error,Reason} ->
- {error,Reason}
- end.
-is_file(regular,read,_FileInfo,File) ->
- {ok,File};
-is_file(regular,read_write,_FileInfo,File) ->
- {ok,File};
-is_file(_Type,_Access,FileInfo,_File) ->
- {error,FileInfo}.
-
-
-%%-------------------------------------------------------------------------
-%% make_integer(String) -> Result
-%% String = string()
-%% Result = {ok,integer()} | {error,nomatch}
-%%
-%% Description: make_integer/1 returns an integer representation of String.
-%%-------------------------------------------------------------------------
-make_integer(String) ->
- case inets_regexp:match(clean(String),"[0-9]+") of
- {match, _, _} ->
- {ok, list_to_integer(clean(String))};
- nomatch ->
- {error, nomatch}
- end.
-
-
-%%-------------------------------------------------------------------------
-%% clean(String) -> Stripped
-%% String = Stripped = string()
-%%
-%% Description:clean/1 removes leading and/or trailing white spaces
-%% from String.
-%%-------------------------------------------------------------------------
-clean(String) ->
- {ok,CleanedString,_} =
- inets_regexp:gsub(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$",""),
- CleanedString.
-
-
-%%-------------------------------------------------------------------------
-%% custom_clean(String,Before,After) -> Stripped
-%% Before = After = regexp()
-%% String = Stripped = string()
-%%
-%% Description: custom_clean/3 removes leading and/or trailing white
-%% spaces and custom characters from String.
-%%-------------------------------------------------------------------------
-custom_clean(String,MoreBefore,MoreAfter) ->
- {ok,CleanedString,_} = inets_regexp:gsub(String,"^[ \t\n\r\f"++MoreBefore++
- "]*|[ \t\n\r\f"++MoreAfter++"]*\$",""),
- CleanedString.
-
-
-%%-------------------------------------------------------------------------
-%% check_enum(EnumString,ValidEnumStrings) -> Result
-%% EnumString = string()
-%% ValidEnumStrings = [string()]
-%% Result = {ok,atom()} | {error,not_valid}
-%%
-%% Description: check_enum/2 checks if EnumString is a valid
-%% enumeration of ValidEnumStrings in which case it is returned as an
-%% atom.
-%%-------------------------------------------------------------------------
-check_enum(_Enum,[]) ->
- {error, not_valid};
-check_enum(Enum,[Enum|_Rest]) ->
- {ok, list_to_atom(Enum)};
-check_enum(Enum, [_NotValid|Rest]) ->
- check_enum(Enum, Rest).
-
-
%%%=========================================================================
%%% Application internal API
%%%=========================================================================
@@ -192,7 +80,7 @@ load("MaxHeaderSize " ++ MaxHeaderSize, []) ->
{ok, Integer} ->
{ok, [], {max_header_size,Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxHeaderSize)++
+ {error, ?NICE(string:strip(MaxHeaderSize)++
" is an invalid number of MaxHeaderSize")}
end;
@@ -201,7 +89,7 @@ load("MaxURISize " ++ MaxHeaderSize, []) ->
{ok, Integer} ->
{ok, [], {max_uri_size, Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxHeaderSize)++
+ {error, ?NICE(string:strip(MaxHeaderSize)++
" is an invalid number of MaxHeaderSize")}
end;
@@ -210,12 +98,12 @@ load("MaxContentLength " ++ Max, []) ->
{ok, Integer} ->
{ok, [], {max_content_length, Integer}};
{error, _} ->
- {error, ?NICE(clean(Max) ++
+ {error, ?NICE(string:strip(Max) ++
" is an invalid number of MaxContentLength")}
end;
load("ServerName " ++ ServerName, []) ->
- {ok,[], {server_name, clean(ServerName)}};
+ {ok,[], {server_name, string:strip(ServerName)}};
load("ServerTokens " ++ ServerTokens, []) ->
%% These are the valid *plain* server tokens:
@@ -223,28 +111,28 @@ load("ServerTokens " ++ ServerTokens, []) ->
%% It can also be a "private" server token: private:<any string>
case string:tokens(ServerTokens, [$:]) of
["private", Private] ->
- {ok,[], {server_tokens, clean(Private)}};
+ {ok,[], {server_tokens, string:strip(Private)}};
[TokStr] ->
- Tok = list_to_atom(clean(TokStr)),
+ Tok = list_to_atom(string:strip(TokStr)),
case lists:member(Tok, [none, prod, major, minor, minimum, os, full]) of
true ->
{ok,[], {server_tokens, Tok}};
false ->
- {error, ?NICE(clean(ServerTokens) ++
+ {error, ?NICE(string:strip(ServerTokens) ++
" is an invalid ServerTokens")}
end;
_ ->
- {error, ?NICE(clean(ServerTokens) ++ " is an invalid ServerTokens")}
+ {error, ?NICE(string:strip(ServerTokens) ++ " is an invalid ServerTokens")}
end;
load("SocketType " ++ SocketType, []) ->
%% ssl is the same as HTTP_DEFAULT_SSL_KIND
%% essl is the pure Erlang-based ssl (the "new" ssl)
- case check_enum(clean(SocketType), ["ssl", "essl", "ip_comm"]) of
+ case check_enum(string:strip(SocketType), ["ssl", "essl", "ip_comm"]) of
{ok, ValidSocketType} ->
{ok, [], {socket_type, ValidSocketType}};
{error,_} ->
- {error, ?NICE(clean(SocketType) ++ " is an invalid SocketType")}
+ {error, ?NICE(string:strip(SocketType) ++ " is an invalid SocketType")}
end;
load("Port " ++ Port, []) ->
@@ -252,7 +140,7 @@ load("Port " ++ Port, []) ->
{ok, Integer} ->
{ok, [], {port, Integer}};
{error, _} ->
- {error, ?NICE(clean(Port)++" is an invalid Port")}
+ {error, ?NICE(string:strip(Port)++" is an invalid Port")}
end;
load("BindAddress " ++ Address0, []) ->
@@ -308,7 +196,7 @@ load("BindAddress " ++ Address0, []) ->
end;
load("KeepAlive " ++ OnorOff, []) ->
- case list_to_atom(clean(OnorOff)) of
+ case list_to_atom(string:strip(OnorOff)) of
off ->
{ok, [], {keep_alive, false}};
_ ->
@@ -320,7 +208,7 @@ load("MaxKeepAliveRequests " ++ MaxRequests, []) ->
{ok, Integer} ->
{ok, [], {max_keep_alive_request, Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxRequests) ++
+ {error, ?NICE(string:strip(MaxRequests) ++
" is an invalid MaxKeepAliveRequests")}
end;
@@ -330,7 +218,7 @@ load("MaxKeepAliveRequest " ++ MaxRequests, []) ->
{ok, Integer} ->
{ok, [], {max_keep_alive_request, Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxRequests) ++
+ {error, ?NICE(string:strip(MaxRequests) ++
" is an invalid MaxKeepAliveRequest")}
end;
@@ -339,7 +227,7 @@ load("KeepAliveTimeout " ++ Timeout, []) ->
{ok, Integer} ->
{ok, [], {keep_alive_timeout, Integer}};
{error, _} ->
- {error, ?NICE(clean(Timeout)++" is an invalid KeepAliveTimeout")}
+ {error, ?NICE(string:strip(Timeout)++" is an invalid KeepAliveTimeout")}
end;
load("Modules " ++ Modules, []) ->
@@ -347,18 +235,18 @@ load("Modules " ++ Modules, []) ->
{ok, [], {modules,[list_to_atom(X) || X <- ModuleList]}};
load("ServerAdmin " ++ ServerAdmin, []) ->
- {ok, [], {server_admin,clean(ServerAdmin)}};
+ {ok, [], {server_admin,string:strip(ServerAdmin)}};
load("ServerRoot " ++ ServerRoot, []) ->
- case is_directory(clean(ServerRoot)) of
+ case is_directory(string:strip(ServerRoot)) of
{ok, Directory} ->
{ok, [], [{server_root,string:strip(Directory,right,$/)}]};
{error, _} ->
- {error, ?NICE(clean(ServerRoot)++" is an invalid ServerRoot")}
+ {error, ?NICE(string:strip(ServerRoot)++" is an invalid ServerRoot")}
end;
load("MimeTypes " ++ MimeTypes, []) ->
- case load_mime_types(clean(MimeTypes)) of
+ case load_mime_types(white_space_clean(MimeTypes)) of
{ok, MimeTypesList} ->
{ok, [], [{mime_types, MimeTypesList}]};
{error, Reason} ->
@@ -370,24 +258,24 @@ load("MaxClients " ++ MaxClients, []) ->
{ok, Integer} ->
{ok, [], {max_clients,Integer}};
{error, _} ->
- {error, ?NICE(clean(MaxClients) ++
+ {error, ?NICE(string:strip(MaxClients) ++
" is an invalid number of MaxClients")}
end;
load("DocumentRoot " ++ DocumentRoot,[]) ->
- case is_directory(clean(DocumentRoot)) of
+ case is_directory(string:strip(DocumentRoot)) of
{ok, Directory} ->
{ok, [], {document_root,string:strip(Directory,right,$/)}};
{error, _} ->
- {error, ?NICE(clean(DocumentRoot)++" is an invalid DocumentRoot")}
+ {error, ?NICE(string:strip(DocumentRoot)++" is an invalid DocumentRoot")}
end;
load("DefaultType " ++ DefaultType, []) ->
- {ok, [], {default_type,clean(DefaultType)}};
+ {ok, [], {default_type,string:strip(DefaultType)}};
load("SSLCertificateFile " ++ SSLCertificateFile, []) ->
- case is_file(clean(SSLCertificateFile)) of
+ case is_file(string:strip(SSLCertificateFile)) of
{ok, File} ->
{ok, [], {ssl_certificate_file,File}};
{error, _} ->
- {error, ?NICE(clean(SSLCertificateFile)++
+ {error, ?NICE(string:strip(SSLCertificateFile)++
" is an invalid SSLCertificateFile")}
end;
load("SSLLogLevel " ++ SSLLogAlert, []) ->
@@ -398,69 +286,69 @@ load("SSLLogLevel " ++ SSLLogAlert, []) ->
{ok, [], {ssl_log_alert, true}}
end;
load("SSLCertificateKeyFile " ++ SSLCertificateKeyFile, []) ->
- case is_file(clean(SSLCertificateKeyFile)) of
+ case is_file(string:strip(SSLCertificateKeyFile)) of
{ok, File} ->
{ok, [], {ssl_certificate_key_file,File}};
{error, _} ->
- {error, ?NICE(clean(SSLCertificateKeyFile)++
+ {error, ?NICE(string:strip(SSLCertificateKeyFile)++
" is an invalid SSLCertificateKeyFile")}
end;
load("SSLVerifyClient " ++ SSLVerifyClient, []) ->
- case make_integer(clean(SSLVerifyClient)) of
+ case make_integer(string:strip(SSLVerifyClient)) of
{ok, Integer} when (Integer >=0) andalso (Integer =< 2) ->
{ok, [], {ssl_verify_client,Integer}};
{ok, _Integer} ->
- {error,?NICE(clean(SSLVerifyClient) ++
+ {error,?NICE(string:strip(SSLVerifyClient) ++
" is an invalid SSLVerifyClient")};
{error, nomatch} ->
- {error,?NICE(clean(SSLVerifyClient) ++
+ {error,?NICE(string:strip(SSLVerifyClient) ++
" is an invalid SSLVerifyClient")}
end;
load("SSLVerifyDepth " ++ SSLVerifyDepth, []) ->
- case make_integer(clean(SSLVerifyDepth)) of
+ case make_integer(string:strip(SSLVerifyDepth)) of
{ok, Integer} when Integer > 0 ->
{ok, [], {ssl_verify_client_depth,Integer}};
{ok, _Integer} ->
- {error,?NICE(clean(SSLVerifyDepth) ++
+ {error,?NICE(string:strip(SSLVerifyDepth) ++
" is an invalid SSLVerifyDepth")};
{error, nomatch} ->
- {error,?NICE(clean(SSLVerifyDepth) ++
+ {error,?NICE(string:strip(SSLVerifyDepth) ++
" is an invalid SSLVerifyDepth")}
end;
load("SSLCiphers " ++ SSLCiphers, []) ->
- {ok, [], {ssl_ciphers, clean(SSLCiphers)}};
+ {ok, [], {ssl_ciphers, string:strip(SSLCiphers)}};
load("SSLCACertificateFile " ++ SSLCACertificateFile, []) ->
- case is_file(clean(SSLCACertificateFile)) of
+ case is_file(string:strip(SSLCACertificateFile)) of
{ok, File} ->
{ok, [], {ssl_ca_certificate_file,File}};
{error, _} ->
- {error, ?NICE(clean(SSLCACertificateFile)++
+ {error, ?NICE(string:strip(SSLCACertificateFile)++
" is an invalid SSLCACertificateFile")}
end;
load("SSLPasswordCallbackModule " ++ SSLPasswordCallbackModule, []) ->
{ok, [], {ssl_password_callback_module,
- list_to_atom(clean(SSLPasswordCallbackModule))}};
+ list_to_atom(string:strip(SSLPasswordCallbackModule))}};
load("SSLPasswordCallbackFunction " ++ SSLPasswordCallbackFunction, []) ->
{ok, [], {ssl_password_callback_function,
- list_to_atom(clean(SSLPasswordCallbackFunction))}};
+ list_to_atom(string:strip(SSLPasswordCallbackFunction))}};
load("SSLPasswordCallbackArguments " ++ SSLPasswordCallbackArguments, []) ->
{ok, [], {ssl_password_callback_arguments,
SSLPasswordCallbackArguments}};
load("DisableChunkedTransferEncodingSend " ++ TrueOrFalse, []) ->
- case list_to_atom(clean(TrueOrFalse)) of
+ case list_to_atom(string:strip(TrueOrFalse)) of
true ->
{ok, [], {disable_chunked_transfer_encoding_send, true}};
_ ->
{ok, [], {disable_chunked_transfer_encoding_send, false}}
end;
load("LogFormat " ++ LogFormat, []) ->
- {ok,[],{log_format, list_to_atom(httpd_conf:clean(LogFormat))}};
+ {ok,[],{log_format, list_to_atom(string:strip(LogFormat))}};
load("ErrorLogFormat " ++ LogFormat, []) ->
- {ok,[],{error_log_format, list_to_atom(httpd_conf:clean(LogFormat))}}.
+ {ok,[],{error_log_format, list_to_atom(string:strip(LogFormat))}}.
clean_address(Addr) ->
- string:strip(string:strip(clean(Addr), left, $[), right, $]).
+ string:strip(string:strip(string:strip(Addr), left, $[), right, $]).
make_ipfamily(IpFamilyStr) ->
@@ -757,8 +645,9 @@ store(ConfigList0) ->
?hdrt("store", [{modules, Modules}]),
Port = proplists:get_value(port, ConfigList0),
Addr = proplists:get_value(bind_address, ConfigList0, any),
+ Profile = proplists:get_value(profile, ConfigList0, default),
ConfigList = fix_mime_types(ConfigList0),
- Name = httpd_util:make_name("httpd_conf", Addr, Port),
+ Name = httpd_util:make_name("httpd_conf", Addr, Port, Profile),
ConfigDB = ets:new(Name, [named_table, bag, protected]),
store(ConfigDB, ConfigList,
lists:append(Modules, [?MODULE]),
@@ -785,8 +674,15 @@ fix_mime_types(ConfigList0) ->
[{"html","text/html"},{"htm","text/html"}]}
| ConfigList0]
end;
- _ ->
- ConfigList0
+ MimeTypes ->
+ case filelib:is_file(MimeTypes) of
+ true ->
+ {ok, MimeTypesList} = load_mime_types(MimeTypes),
+ ConfigList = proplists:delete(mime_types, ConfigList0),
+ [{mime_types, MimeTypesList} | ConfigList];
+ false ->
+ ConfigList0
+ end
end.
store({mime_types,MimeTypesList},ConfigList) ->
@@ -902,15 +798,15 @@ remove(ConfigDB) ->
%% end.
-get_config(Address, Port) ->
- Tab = httpd_util:make_name("httpd_conf", Address, Port),
+get_config(Address, Port, Profile) ->
+ Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile),
Properties = ets:tab2list(Tab),
MimeTab = proplists:get_value(mime_types, Properties),
NewProperties = proplists:delete(mime_types, Properties),
[{mime_types, ets:tab2list(MimeTab)} | NewProperties].
-get_config(Address, Port, Properties) ->
- Tab = httpd_util:make_name("httpd_conf", Address, Port),
+get_config(Address, Port, Profile, Properties) ->
+ Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile),
Config =
lists:map(fun(Prop) -> {Prop, httpd_util:lookup(Tab, Prop)} end,
Properties),
@@ -1078,7 +974,7 @@ verify_modules([]) ->
verify_modules([Mod|Rest]) ->
case code:which(Mod) of
non_existing ->
- {error, ?NICE(atom_to_list(Mod)++" does not exist")};
+ {error, ?NICE(string:strip(atom_to_list(Mod), right, $\n) ++" does not exist")};
_Path ->
verify_modules(Rest)
end.
@@ -1120,7 +1016,7 @@ parse_mime_types(Stream,MimeTypesList) ->
eof ->
eof;
String ->
- clean(String)
+ white_space_clean(String)
end,
parse_mime_types(Stream, MimeTypesList, Line).
parse_mime_types(Stream, MimeTypesList, eof) ->
@@ -1306,4 +1202,68 @@ plain_server_tokens() ->
error_report(Where,M,F,Error) ->
error_logger:error_report([{?MODULE, Where},
{apply, {M, F, []}}, Error]).
+white_space_clean(String) ->
+ {ok,CleanedString,_} =
+ inets_regexp:gsub(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$",""),
+ CleanedString.
+
+
+%%%=========================================================================
+%%% Deprecated remove in 19
+%%%=========================================================================
+is_directory(Directory) ->
+ case file:read_file_info(Directory) of
+ {ok,FileInfo} ->
+ #file_info{type = Type, access = Access} = FileInfo,
+ is_directory(Type,Access,FileInfo,Directory);
+ {error,Reason} ->
+ {error,Reason}
+ end.
+is_directory(directory,read,_FileInfo,Directory) ->
+ {ok,Directory};
+is_directory(directory,read_write,_FileInfo,Directory) ->
+ {ok,Directory};
+is_directory(_Type,_Access,FileInfo,_Directory) ->
+ {error,FileInfo}.
+
+is_file(File) ->
+ case file:read_file_info(File) of
+ {ok,FileInfo} ->
+ #file_info{type = Type, access = Access} = FileInfo,
+ is_file(Type,Access,FileInfo,File);
+ {error,Reason} ->
+ {error,Reason}
+ end.
+is_file(regular,read,_FileInfo,File) ->
+ {ok,File};
+is_file(regular,read_write,_FileInfo,File) ->
+ {ok,File};
+is_file(_Type,_Access,FileInfo,_File) ->
+ {error,FileInfo}.
+
+make_integer(String) ->
+ case inets_regexp:match(string:strip(String),"[0-9]+") of
+ {match, _, _} ->
+ {ok, list_to_integer(string:strip(String))};
+ nomatch ->
+ {error, nomatch}
+ end.
+
+clean(String) ->
+ {ok,CleanedString,_} =
+ inets_regexp:gsub(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$",""),
+ CleanedString.
+
+custom_clean(String,MoreBefore,MoreAfter) ->
+ {ok,CleanedString,_} = inets_regexp:gsub(String,"^[ \t\n\r\f"++MoreBefore++
+ "]*|[ \t\n\r\f"++MoreAfter++"]*\$",""),
+ CleanedString.
+
+check_enum(_Enum,[]) ->
+ {error, not_valid};
+check_enum(Enum,[Enum|_Rest]) ->
+ {ok, list_to_atom(Enum)};
+check_enum(Enum, [_NotValid|Rest]) ->
+ check_enum(Enum, Rest).
+
diff --git a/lib/inets/src/http_server/httpd_custom.erl b/lib/inets/src/http_server/httpd_custom.erl
new file mode 100644
index 0000000000..342469a579
--- /dev/null
+++ b/lib/inets/src/http_server/httpd_custom.erl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(httpd_custom).
+
+-export([response_header/1, request_header/1]).
+-export([customize_headers/3]).
+
+-include_lib("inets/src/inets_app/inets_internal.hrl").
+
+response_header(Header) ->
+ {true, httpify(Header)}.
+request_header(Header) ->
+ {true, Header}.
+
+customize_headers(?MODULE, Function, Arg) ->
+ ?MODULE:Function(Arg);
+customize_headers(Module, Function, Arg) ->
+ try Module:Function(Arg) of
+ {true, Value} ->
+ ?MODULE:Function(Value);
+ false ->
+ false
+ catch
+ _:_ ->
+ ?MODULE:Function(Arg)
+ end.
+
+httpify({Key0, Value}) ->
+ %% make sure first letter is capital (defacto standard)
+ Words1 = string:tokens(Key0, "-"),
+ Words2 = upify(Words1, []),
+ Key = new_key(Words2),
+ Key ++ ": " ++ Value ++ ?CRLF .
+
+new_key([]) ->
+ "";
+new_key([W]) ->
+ W;
+new_key([W1,W2]) ->
+ W1 ++ "-" ++ W2;
+new_key([W|R]) ->
+ W ++ "-" ++ new_key(R).
+
+upify([], Acc) ->
+ lists:reverse(Acc);
+upify([Key|Rest], Acc) ->
+ upify(Rest, [upify2(Key)|Acc]).
+
+upify2([C|Rest]) when (C >= $a) andalso (C =< $z) ->
+ [C-($a-$A)|Rest];
+upify2(Str) ->
+ Str.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index 6fc07f033c..b2c2ea7480 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -126,9 +126,7 @@ delay(Time) when is_integer(Time) ->
i("httpd_example:delay(~p) -> done, now reply",[Time]),
delay_reply("delay ok");
delay(Time) when is_list(Time) ->
- delay(httpd_conf:make_integer(Time));
-delay({ok,Time}) when is_integer(Time) ->
- delay(Time);
+ delay(list_to_integer(Time));
delay({error,_Reason}) ->
i("delay -> called with invalid time"),
delay_reply("delay failed: invalid delay time").
diff --git a/lib/inets/src/http_server/httpd_instance_sup.erl b/lib/inets/src/http_server/httpd_instance_sup.erl
index b95be44b2a..90800f2724 100644
--- a/lib/inets/src/http_server/httpd_instance_sup.erl
+++ b/lib/inets/src/http_server/httpd_instance_sup.erl
@@ -27,6 +27,8 @@
-behaviour(supervisor).
+-include("httpd_internal.hrl").
+
%% Internal application API
-export([start_link/3, start_link/4]).
@@ -41,7 +43,8 @@ start_link([{_, _}| _] = Config, AcceptTimeout, Debug) ->
{ok, Config2} ->
Address = proplists:get_value(bind_address, Config2),
Port = proplists:get_value(port, Config2),
- Name = make_name(Address, Port),
+ Profile = proplists:get_value(profile, Config2, ?DEFAULT_PROFILE),
+ Name = make_name(Address, Port, Profile),
SupName = {local, Name},
supervisor:start_link(SupName, ?MODULE,
[undefined, Config2, AcceptTimeout,
@@ -54,7 +57,8 @@ start_link([{_, _}| _] = Config, AcceptTimeout, Debug) ->
start_link(ConfigFile, AcceptTimeout, Debug) ->
case file_2_config(ConfigFile) of
{ok, ConfigList, Address, Port} ->
- Name = make_name(Address, Port),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
+ Name = make_name(Address, Port, Profile),
SupName = {local, Name},
supervisor:start_link(SupName, ?MODULE,
[ConfigFile, ConfigList, AcceptTimeout,
@@ -70,7 +74,8 @@ start_link([{_, _}| _] = Config, AcceptTimeout, ListenInfo, Debug) ->
{ok, Config2} ->
Address = proplists:get_value(bind_address, Config2),
Port = proplists:get_value(port, Config2),
- Name = make_name(Address, Port),
+ Profile = proplists:get_value(profile, Config2, ?DEFAULT_PROFILE),
+ Name = make_name(Address, Port, Profile),
SupName = {local, Name},
supervisor:start_link(SupName, ?MODULE,
[undefined, Config2, AcceptTimeout,
@@ -83,7 +88,8 @@ start_link([{_, _}| _] = Config, AcceptTimeout, ListenInfo, Debug) ->
start_link(ConfigFile, AcceptTimeout, ListenInfo, Debug) ->
case file_2_config(ConfigFile) of
{ok, ConfigList, Address, Port} ->
- Name = make_name(Address, Port),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
+ Name = make_name(Address, Port, Profile),
SupName = {local, Name},
supervisor:start_link(SupName, ?MODULE,
[ConfigFile, ConfigList, AcceptTimeout,
@@ -99,22 +105,24 @@ start_link(ConfigFile, AcceptTimeout, ListenInfo, Debug) ->
%%%=========================================================================
init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port]) ->
httpd_util:enable_debug(Debug),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
Flags = {one_for_one, 0, 1},
- Children = [httpd_connection_sup_spec(Address, Port),
- httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout,
+ Children = [httpd_connection_sup_spec(Address, Port, Profile),
+ httpd_acceptor_sup_spec(Address, Port, Profile, ConfigList, AcceptTimeout,
undefined),
- sup_spec(httpd_misc_sup, Address, Port),
- worker_spec(httpd_manager, Address, Port,
+ sup_spec(httpd_misc_sup, Address, Port, Profile),
+ worker_spec(httpd_manager, Address, Port, Profile,
ConfigFile, ConfigList,AcceptTimeout)],
{ok, {Flags, Children}};
init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo]) ->
httpd_util:enable_debug(Debug),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
Flags = {one_for_one, 0, 1},
- Children = [httpd_connection_sup_spec(Address, Port),
- httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout,
- ListenInfo),
- sup_spec(httpd_misc_sup, Address, Port),
- worker_spec(httpd_manager, Address, Port, ListenInfo,
+ Children = [httpd_connection_sup_spec(Address, Port, Profile),
+ httpd_acceptor_sup_spec(Address, Port, Profile, ConfigList, AcceptTimeout,
+ ListenInfo),
+ sup_spec(httpd_misc_sup, Address, Port, Profile),
+ worker_spec(httpd_manager, Address, Port, Profile, ListenInfo,
ConfigFile, ConfigList, AcceptTimeout)],
{ok, {Flags, Children}}.
@@ -122,8 +130,8 @@ init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo])
%%%=========================================================================
%%% Internal functions
%%%=========================================================================
-httpd_connection_sup_spec(Address, Port) ->
- Name = {httpd_connection_sup, Address, Port},
+httpd_connection_sup_spec(Address, Port, Profile) ->
+ Name = {httpd_connection_sup, Address, Port, Profile},
StartFunc = {httpd_connection_sup, start_link, [[Address, Port]]},
Restart = permanent,
Shutdown = 5000,
@@ -131,8 +139,8 @@ httpd_connection_sup_spec(Address, Port) ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, ListenInfo) ->
- Name = {httpd_acceptor_sup, Address, Port},
+httpd_acceptor_sup_spec(Address, Port, Profile, ConfigList, AcceptTimeout, ListenInfo) ->
+ Name = {httpd_acceptor_sup, Address, Port, Profile},
StartFunc = {httpd_acceptor_sup, start_link, [[Address, Port, ConfigList, AcceptTimeout, ListenInfo]]},
Restart = permanent,
Shutdown = infinity,
@@ -140,18 +148,18 @@ httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, ListenInfo) ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-sup_spec(SupModule, Address, Port) ->
- Name = {SupModule, Address, Port},
- StartFunc = {SupModule, start_link, [Address, Port]},
+sup_spec(SupModule, Address, Port, Profile) ->
+ Name = {SupModule, Address, Port, Profile},
+ StartFunc = {SupModule, start_link, [Address, Port, Profile]},
Restart = permanent,
Shutdown = infinity,
Modules = [SupModule],
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-worker_spec(WorkerModule, Address, Port, ConfigFile,
+worker_spec(WorkerModule, Address, Port, Profile, ConfigFile,
ConfigList, AcceptTimeout) ->
- Name = {WorkerModule, Address, Port},
+ Name = {WorkerModule, Address, Port, Profile},
StartFunc = {WorkerModule, start_link,
[ConfigFile, ConfigList, AcceptTimeout]},
Restart = permanent,
@@ -160,9 +168,9 @@ worker_spec(WorkerModule, Address, Port, ConfigFile,
Type = worker,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-worker_spec(WorkerModule, Address, Port, ListenInfo, ConfigFile,
+worker_spec(WorkerModule, Address, Port, Profile, ListenInfo, ConfigFile,
ConfigList, AcceptTimeout) ->
- Name = {WorkerModule, Address, Port},
+ Name = {WorkerModule, Address, Port, Profile},
StartFunc = {WorkerModule, start_link,
[ConfigFile, ConfigList, AcceptTimeout, ListenInfo]},
Restart = permanent,
@@ -171,8 +179,8 @@ worker_spec(WorkerModule, Address, Port, ListenInfo, ConfigFile,
Type = worker,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-make_name(Address,Port) ->
- httpd_util:make_name("httpd_instance_sup", Address, Port).
+make_name(Address, Port, Profile) ->
+ httpd_util:make_name("httpd_instance_sup", Address, Port, Profile).
file_2_config(ConfigFile) ->
diff --git a/lib/inets/src/http_server/httpd_internal.hrl b/lib/inets/src/http_server/httpd_internal.hrl
index 108469ea0a..9829ca255c 100644
--- a/lib/inets/src/http_server/httpd_internal.hrl
+++ b/lib/inets/src/http_server/httpd_internal.hrl
@@ -31,6 +31,8 @@
-define(SOCKET_MAX_POLL,25).
-define(FILE_CHUNK_SIZE,64*1024).
-define(GATEWAY_INTERFACE,"CGI/1.1").
+-define(DEFAULT_PROFILE, default).
+
-define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
-define(DEFAULT_CONTEXT,
[{errmsg,"[an error occurred while processing this directive]"},
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index 3da0343401..995316d5e8 100644
--- a/lib/inets/src/http_server/httpd_manager.erl
+++ b/lib/inets/src/http_server/httpd_manager.erl
@@ -28,7 +28,7 @@
-export([start/2, start_link/2, start_link/3, start_link/4,
stop/1, reload/2]).
-export([new_connection/1]).
--export([config_match/2, config_match/3]).
+-export([config_match/3, config_match/4]).
-export([block/2, block/3, unblock/1]).
%% gen_server exports
@@ -54,7 +54,8 @@
start(ConfigFile, ConfigList) ->
Port = proplists:get_value(port,ConfigList,80),
Addr = proplists:get_value(bind_address, ConfigList),
- Name = make_name(Addr,Port),
+ Profile = proplists:get_value(profile, ConfigList, default),
+ Name = make_name(Addr, Port, Profile),
gen_server:start({local,Name},?MODULE,
[ConfigFile, ConfigList, 15000, Addr, Port],[]).
@@ -65,7 +66,8 @@ start_link(ConfigFile, ConfigList) ->
start_link(ConfigFile, ConfigList, AcceptTimeout) ->
Port = proplists:get_value(port, ConfigList, 80),
Addr = proplists:get_value(bind_address, ConfigList),
- Name = make_name(Addr, Port),
+ Profile = proplists:get_value(profile, ConfigList, default),
+ Name = make_name(Addr, Port, Profile),
gen_server:start_link({local, Name},?MODULE,
[ConfigFile, ConfigList,
@@ -74,7 +76,8 @@ start_link(ConfigFile, ConfigList, AcceptTimeout) ->
start_link(ConfigFile, ConfigList, AcceptTimeout, ListenSocket) ->
Port = proplists:get_value(port, ConfigList, 80),
Addr = proplists:get_value(bind_address, ConfigList),
- Name = make_name(Addr, Port),
+ Profile = proplists:get_value(profile, ConfigList, default),
+ Name = make_name(Addr, Port, Profile),
gen_server:start_link({local, Name},?MODULE,
[ConfigFile, ConfigList, AcceptTimeout, Addr,
@@ -97,10 +100,10 @@ unblock(ServerRef) ->
new_connection(Manager) ->
call(Manager, {new_connection, self()}).
-config_match(Port, Pattern) ->
- config_match(undefined,Port,Pattern).
-config_match(Addr, Port, Pattern) ->
- Name = httpd_util:make_name("httpd",Addr,Port),
+config_match(Port, Profile, Pattern) ->
+ config_match(undefined,Port, Profile, Pattern).
+config_match(Addr, Port, Profile, Pattern) ->
+ Name = httpd_util:make_name("httpd",Addr,Port, Profile),
call(whereis(Name), {config_match, Pattern}).
%%%--------------------------------------------------------------------
@@ -446,8 +449,8 @@ get_ustate(ConnectionCnt,State) ->
active
end.
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd",Addr,Port).
+make_name(Addr, Port, Profile) ->
+ httpd_util:make_name("httpd", Addr, Port, Profile).
report_error(State,String) ->
diff --git a/lib/inets/src/http_server/httpd_misc_sup.erl b/lib/inets/src/http_server/httpd_misc_sup.erl
index fd7c28bd7d..e5de66d773 100644
--- a/lib/inets/src/http_server/httpd_misc_sup.erl
+++ b/lib/inets/src/http_server/httpd_misc_sup.erl
@@ -27,8 +27,8 @@
-behaviour(supervisor).
%% API
--export([start_link/2, start_auth_server/2, stop_auth_server/2,
- start_sec_server/2, stop_sec_server/2]).
+-export([start_link/3, start_auth_server/3, stop_auth_server/3,
+ start_sec_server/3, stop_sec_server/3]).
%% Supervisor callback
-export([init/1]).
@@ -37,26 +37,26 @@
%%% API
%%%=========================================================================
-start_link(Addr, Port) ->
- SupName = make_name(Addr, Port),
+start_link(Addr, Port, Profile) ->
+ SupName = make_name(Addr, Port, Profile),
supervisor:start_link({local, SupName}, ?MODULE, []).
%%----------------------------------------------------------------------
%% Function: [start|stop]_[auth|sec]_server/3
%% Description: Starts a [auth | security] worker (child) process
%%----------------------------------------------------------------------
-start_auth_server(Addr, Port) ->
- start_permanent_worker(mod_auth_server, Addr, Port, [gen_server]).
+start_auth_server(Addr, Port, Profile) ->
+ start_permanent_worker(mod_auth_server, Addr, Port, Profile, [gen_server]).
-stop_auth_server(Addr, Port) ->
- stop_permanent_worker(mod_auth_server, Addr, Port).
+stop_auth_server(Addr, Port, Profile) ->
+ stop_permanent_worker(mod_auth_server, Addr, Port, Profile).
-start_sec_server(Addr, Port) ->
- start_permanent_worker(mod_security_server, Addr, Port, [gen_server]).
+start_sec_server(Addr, Port, Profile) ->
+ start_permanent_worker(mod_security_server, Addr, Port, Profile, [gen_server]).
-stop_sec_server(Addr, Port) ->
- stop_permanent_worker(mod_security_server, Addr, Port).
+stop_sec_server(Addr, Port, Profile) ->
+ stop_permanent_worker(mod_security_server, Addr, Port, Profile).
%%%=========================================================================
@@ -70,15 +70,15 @@ init(_) ->
%%%=========================================================================
%%% Internal functions
%%%=========================================================================
-start_permanent_worker(Mod, Addr, Port, Modules) ->
- SupName = make_name(Addr, Port),
+start_permanent_worker(Mod, Addr, Port, Profile, Modules) ->
+ SupName = make_name(Addr, Port, Profile),
Spec = {{Mod, Addr, Port},
- {Mod, start_link, [Addr, Port]},
+ {Mod, start_link, [Addr, Port, Profile]},
permanent, timer:seconds(1), worker, [Mod] ++ Modules},
supervisor:start_child(SupName, Spec).
-stop_permanent_worker(Mod, Addr, Port) ->
- SupName = make_name(Addr, Port),
+stop_permanent_worker(Mod, Addr, Port, Profile) ->
+ SupName = make_name(Addr, Port, Profile),
Name = {Mod, Addr, Port},
case supervisor:terminate_child(SupName, Name) of
ok ->
@@ -87,5 +87,5 @@ stop_permanent_worker(Mod, Addr, Port) ->
Error
end.
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_misc_sup",Addr,Port).
+make_name(Addr,Port, Profile) ->
+ httpd_util:make_name("httpd_misc_sup",Addr,Port, Profile).
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 3ff07616f9..782120c284 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -42,28 +42,28 @@
%%%=========================================================================
%%% Internal application API
%%%=========================================================================
-parse([Bin, MaxSizes]) ->
- ?hdrt("parse", [{bin, Bin}, {max_sizes, MaxSizes}]),
- parse_method(Bin, [], 0, proplists:get_value(max_method, MaxSizes), MaxSizes, []);
+parse([Bin, Options]) ->
+ ?hdrt("parse", [{bin, Bin}, {max_sizes, Options}]),
+ parse_method(Bin, [], 0, proplists:get_value(max_method, Options), Options, []);
parse(Unknown) ->
?hdrt("parse", [{unknown, Unknown}]),
exit({bad_args, Unknown}).
%% Functions that may be returned during the decoding process
%% if the input data is incompleate.
-parse_method([Bin, Method, Current, Max, MaxSizes, Result]) ->
- parse_method(Bin, Method, Current, Max, MaxSizes, Result).
+parse_method([Bin, Method, Current, Max, Options, Result]) ->
+ parse_method(Bin, Method, Current, Max, Options, Result).
-parse_uri([Bin, URI, Current, Max, MaxSizes, Result]) ->
- parse_uri(Bin, URI, Current, Max, MaxSizes, Result).
+parse_uri([Bin, URI, Current, Max, Options, Result]) ->
+ parse_uri(Bin, URI, Current, Max, Options, Result).
-parse_version([Bin, Rest, Version, Current, Max, MaxSizes, Result]) ->
- parse_version(<<Rest/binary, Bin/binary>>, Version, Current, Max, MaxSizes,
+parse_version([Bin, Rest, Version, Current, Max, Options, Result]) ->
+ parse_version(<<Rest/binary, Bin/binary>>, Version, Current, Max, Options,
Result).
-parse_headers([Bin, Rest, Header, Headers, Current, Max, MaxSizes, Result]) ->
+parse_headers([Bin, Rest, Header, Headers, Current, Max, Options, Result]) ->
parse_headers(<<Rest/binary, Bin/binary>>,
- Header, Headers, Current, Max, MaxSizes, Result).
+ Header, Headers, Current, Max, Options, Result).
whole_body([Bin, Body, Length]) ->
whole_body(<<Body/binary, Bin/binary>>, Length).
@@ -134,13 +134,13 @@ update_mod_data(ModData, Method, RequestURI, HTTPVersion, Headers)->
%%%========================================================================
%%% Internal functions
%%%========================================================================
-parse_method(<<>>, Method, Current, Max, MaxSizes, Result) ->
- {?MODULE, parse_method, [Method, Current, Max, MaxSizes, Result]};
-parse_method(<<?SP, Rest/binary>>, Method, _Current, _Max, MaxSizes, Result) ->
- parse_uri(Rest, [], 0, proplists:get_value(max_uri, MaxSizes), MaxSizes,
+parse_method(<<>>, Method, Current, Max, Options, Result) ->
+ {?MODULE, parse_method, [Method, Current, Max, Options, Result]};
+parse_method(<<?SP, Rest/binary>>, Method, _Current, _Max, Options, Result) ->
+ parse_uri(Rest, [], 0, proplists:get_value(max_uri, Options), Options,
[string:strip(lists:reverse(Method)) | Result]);
-parse_method(<<Octet, Rest/binary>>, Method, Current, Max, MaxSizes, Result) when Current =< Max ->
- parse_method(Rest, [Octet | Method], Current + 1, Max, MaxSizes, Result);
+parse_method(<<Octet, Rest/binary>>, Method, Current, Max, Options, Result) when Current =< Max ->
+ parse_method(Rest, [Octet | Method], Current + 1, Max, Options, Result);
parse_method(_, _, _, Max, _, _) ->
%% We do not know the version of the client as it comes after the
%% method send the lowest version in the response so that the client
@@ -153,30 +153,30 @@ parse_uri(_, _, Current, MaxURI, _, _)
%% uri send the lowest version in the response so that the client
%% will be able to handle it.
{error, {size_error, MaxURI, 414, "URI unreasonably long"},lowest_version()};
-parse_uri(<<>>, URI, Current, Max, MaxSizes, Result) ->
- {?MODULE, parse_uri, [URI, Current, Max, MaxSizes, Result]};
-parse_uri(<<?SP, Rest/binary>>, URI, _, _, MaxSizes, Result) ->
- parse_version(Rest, [], 0, proplists:get_value(max_version, MaxSizes), MaxSizes,
+parse_uri(<<>>, URI, Current, Max, Options, Result) ->
+ {?MODULE, parse_uri, [URI, Current, Max, Options, Result]};
+parse_uri(<<?SP, Rest/binary>>, URI, _, _, Options, Result) ->
+ parse_version(Rest, [], 0, proplists:get_value(max_version, Options), Options,
[string:strip(lists:reverse(URI)) | Result]);
%% Can happen if it is a simple HTTP/0.9 request e.i "GET /\r\n\r\n"
-parse_uri(<<?CR, _Rest/binary>> = Data, URI, _, _, MaxSizes, Result) ->
- parse_version(Data, [], 0, proplists:get_value(max_version, MaxSizes), MaxSizes,
+parse_uri(<<?CR, _Rest/binary>> = Data, URI, _, _, Options, Result) ->
+ parse_version(Data, [], 0, proplists:get_value(max_version, Options), Options,
[string:strip(lists:reverse(URI)) | Result]);
-parse_uri(<<Octet, Rest/binary>>, URI, Current, Max, MaxSizes, Result) ->
- parse_uri(Rest, [Octet | URI], Current + 1, Max, MaxSizes, Result).
+parse_uri(<<Octet, Rest/binary>>, URI, Current, Max, Options, Result) ->
+ parse_uri(Rest, [Octet | URI], Current + 1, Max, Options, Result).
-parse_version(<<>>, Version, Current, Max, MaxSizes, Result) ->
- {?MODULE, parse_version, [<<>>, Version, Current, Max, MaxSizes, Result]};
-parse_version(<<?LF, Rest/binary>>, Version, Current, Max, MaxSizes, Result) ->
+parse_version(<<>>, Version, Current, Max, Options, Result) ->
+ {?MODULE, parse_version, [<<>>, Version, Current, Max, Options, Result]};
+parse_version(<<?LF, Rest/binary>>, Version, Current, Max, Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
- parse_version(<<?CR, ?LF, Rest/binary>>, Version, Current, Max, MaxSizes, Result);
-parse_version(<<?CR, ?LF, Rest/binary>>, Version, _, _, MaxSizes, Result) ->
- parse_headers(Rest, [], [], 0, proplists:get_value(max_header, MaxSizes), MaxSizes,
+ parse_version(<<?CR, ?LF, Rest/binary>>, Version, Current, Max, Options, Result);
+parse_version(<<?CR, ?LF, Rest/binary>>, Version, _, _, Options, Result) ->
+ parse_headers(Rest, [], [], 0, proplists:get_value(max_header, Options), Options,
[string:strip(lists:reverse(Version)) | Result]);
-parse_version(<<?CR>> = Data, Version, Current, Max, MaxSizes, Result) ->
- {?MODULE, parse_version, [Data, Version, Current, Max, MaxSizes, Result]};
-parse_version(<<Octet, Rest/binary>>, Version, Current, Max, MaxSizes, Result) when Current =< Max ->
- parse_version(Rest, [Octet | Version], Current + 1, Max, MaxSizes, Result);
+parse_version(<<?CR>> = Data, Version, Current, Max, Options, Result) ->
+ {?MODULE, parse_version, [Data, Version, Current, Max, Options, Result]};
+parse_version(<<Octet, Rest/binary>>, Version, Current, Max, Options, Result) when Current =< Max ->
+ parse_version(Rest, [Octet | Version], Current + 1, Max, Options, Result);
parse_version(_, _, _, Max,_,_) ->
{error, {size_error, Max, 413, "Version string unreasonably long"}, lowest_version()}.
@@ -185,34 +185,42 @@ parse_headers(_, _, _, Current, Max, _, Result)
HttpVersion = lists:nth(3, lists:reverse(Result)),
{error, {size_error, Max, 413, "Headers unreasonably long"}, HttpVersion};
-parse_headers(<<>>, Header, Headers, Current, Max, MaxSizes, Result) ->
+parse_headers(<<>>, Header, Headers, Current, Max, Options, Result) ->
{?MODULE, parse_headers, [<<>>, Header, Headers, Current, Max,
- MaxSizes, Result]};
-parse_headers(<<?CR,?LF,?LF,Body/binary>>, [], [], Current, Max, MaxSizes, Result) ->
+ Options, Result]};
+parse_headers(<<?CR,?LF,?LF,Body/binary>>, [], [], Current, Max, Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, [], [], Current, Max,
- MaxSizes, Result);
+ Options, Result);
-parse_headers(<<?LF,?LF,Body/binary>>, [], [], Current, Max, MaxSizes, Result) ->
+parse_headers(<<?LF,?LF,Body/binary>>, [], [], Current, Max, Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, [], [], Current, Max,
- MaxSizes, Result);
+ Options, Result);
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, [], [], _, _, _, Result) ->
NewResult = list_to_tuple(lists:reverse([Body, {#http_request_h{}, []} |
Result])),
{ok, NewResult};
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers, _, _,
- MaxSizes, Result) ->
+ Options, Result) ->
+ Customize = proplists:get_value(customize, Options),
case http_request:key_value(lists:reverse(Header)) of
undefined -> %% Skip headers with missing :
- {ok, list_to_tuple(lists:reverse([Body, {http_request:headers(Headers, #http_request_h{}), Headers} | Result]))};
+ FinalHeaders = lists:filtermap(fun(H) ->
+ httpd_custom:customize_headers(Customize, request_header, H)
+ end,
+ Headers),
+ {ok, list_to_tuple(lists:reverse([Body, {http_request:headers(FinalHeaders, #http_request_h{}), FinalHeaders} | Result]))};
NewHeader ->
- case check_header(NewHeader, MaxSizes) of
+ case check_header(NewHeader, Options) of
ok ->
- {ok, list_to_tuple(lists:reverse([Body, {http_request:headers([NewHeader | Headers],
+ FinalHeaders = lists:filtermap(fun(H) ->
+ httpd_custom:customize_headers(Customize, request_header, H)
+ end, [NewHeader | Headers]),
+ {ok, list_to_tuple(lists:reverse([Body, {http_request:headers(FinalHeaders,
#http_request_h{}),
- [NewHeader | Headers]} | Result]))};
+ FinalHeaders} | Result]))};
{error, Reason} ->
HttpVersion = lists:nth(3, lists:reverse(Result)),
@@ -221,12 +229,12 @@ parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers, _, _,
end;
parse_headers(<<?CR,?LF,?CR>> = Data, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
{?MODULE, parse_headers, [Data, Header, Headers, Current, Max,
- MaxSizes, Result]};
-parse_headers(<<?LF>>, [], [], Current, Max, MaxSizes, Result) ->
+ Options, Result]};
+parse_headers(<<?LF>>, [], [], Current, Max, Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
- parse_headers(<<?CR,?LF>>, [], [], Current, Max, MaxSizes, Result);
+ parse_headers(<<?CR,?LF>>, [], [], Current, Max, Options, Result);
%% There where no headers, which is unlikely to happen.
parse_headers(<<?CR,?LF>>, [], [], _, _, _, Result) ->
@@ -235,30 +243,30 @@ parse_headers(<<?CR,?LF>>, [], [], _, _, _, Result) ->
{ok, NewResult};
parse_headers(<<?LF>>, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
- parse_headers(<<?CR,?LF>>, Header, Headers, Current, Max, MaxSizes, Result);
+ parse_headers(<<?CR,?LF>>, Header, Headers, Current, Max, Options, Result);
parse_headers(<<?CR,?LF>> = Data, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
{?MODULE, parse_headers, [Data, Header, Headers, Current, Max,
- MaxSizes, Result]};
+ Options, Result]};
parse_headers(<<?LF, Octet, Rest/binary>>, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, Current, Max,
- MaxSizes, Result);
+ Options, Result);
parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, _, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
case http_request:key_value(lists:reverse(Header)) of
undefined -> %% Skip headers with missing :
parse_headers(Rest, [Octet], Headers,
- 0, Max, MaxSizes, Result);
+ 0, Max, Options, Result);
NewHeader ->
- case check_header(NewHeader, MaxSizes) of
+ case check_header(NewHeader, Options) of
ok ->
parse_headers(Rest, [Octet], [NewHeader | Headers],
- 0, Max, MaxSizes, Result);
+ 0, Max, Options, Result);
{error, Reason} ->
HttpVersion = lists:nth(3, lists:reverse(Result)),
{error, Reason, HttpVersion}
@@ -266,19 +274,19 @@ parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, _, Max,
end;
parse_headers(<<?CR>> = Data, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
{?MODULE, parse_headers, [Data, Header, Headers, Current, Max,
- MaxSizes, Result]};
+ Options, Result]};
parse_headers(<<?LF>>, Header, Headers, Current, Max,
- MaxSizes, Result) ->
+ Options, Result) ->
%% If ?CR is is missing RFC2616 section-19.3
parse_headers(<<?CR, ?LF>>, Header, Headers, Current, Max,
- MaxSizes, Result);
+ Options, Result);
parse_headers(<<Octet, Rest/binary>>, Header, Headers, Current,
- Max, MaxSizes, Result) ->
+ Max, Options, Result) ->
parse_headers(Rest, [Octet | Header], Headers, Current + 1, Max,
- MaxSizes, Result).
+ Options, Result).
whole_body(Body, Length) ->
case size(Body) of
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index f7a9fe5d49..9947e17b47 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -121,13 +121,15 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
MaxURISize = max_uri_size(ConfigDB),
NrOfRequest = max_keep_alive_request(ConfigDB),
MaxContentLen = max_content_length(ConfigDB),
+ Customize = customize(ConfigDB),
{_, Status} = httpd_manager:new_connection(Manager),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
{max_version, ?HTTP_MAX_VERSION_STRING},
{max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, MaxContentLen}
+ {max_content_length, MaxContentLen},
+ {customize, Customize}
]]},
State = #state{mod = Mod,
@@ -550,11 +552,13 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
MaxHeaderSize = max_header_size(ModData#mod.config_db),
MaxURISize = max_uri_size(ModData#mod.config_db),
MaxContentLen = max_content_length(ModData#mod.config_db),
+ Customize = customize(ModData#mod.config_db),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
{max_version, ?HTTP_MAX_VERSION_STRING},
{max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, MaxContentLen}
+ {max_content_length, MaxContentLen},
+ {customize, Customize}
]]},
TmpState = State#state{mod = NewModData,
mfa = MFA,
@@ -640,3 +644,6 @@ max_keep_alive_request(ConfigDB) ->
max_content_length(ConfigDB) ->
httpd_util:lookup(ConfigDB, max_content_length, ?HTTP_MAX_CONTENT_LENGTH).
+
+customize(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, customize, httpd_custom).
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 2fa91d47a0..71dc05e46d 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-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -176,7 +176,7 @@ send_header(#mod{socket_type = Type,
StatusLine = [NewVer, " ", io_lib:write(NewStatusCode), " ",
httpd_util:reason_phrase(NewStatusCode), ?CRLF],
ConnectionHeader = get_connection(Conn, NewVer),
- Head = list_to_binary([StatusLine, Headers, ConnectionHeader , ?CRLF]),
+ Head = [StatusLine, Headers, ConnectionHeader , ?CRLF],
httpd_socket:deliver(Type, Sock, Head).
map_status_code("HTTP/1.0", Code)
@@ -286,45 +286,21 @@ create_header(ConfigDb, KeyValueTupleHeaders) ->
Date = httpd_util:rfc1123_date(),
ContentType = "text/html",
Server = server(ConfigDb),
- NewHeaders = add_default_headers([{"date", Date},
- {"content-type", ContentType}
- | if Server=="" -> [];
- true -> [{"server", Server}]
- end
- ],
- KeyValueTupleHeaders),
- lists:map(fun fix_header/1, NewHeaders).
-
-
+ Headers0 = add_default_headers([{"date", Date},
+ {"content-type", ContentType}
+ | if Server=="" -> [];
+ true -> [{"server", Server}]
+ end
+ ],
+ KeyValueTupleHeaders),
+ CustomizeCB = httpd_util:lookup(ConfigDb, customize, httpd_custom),
+ lists:filtermap(fun(H) ->
+ httpd_custom:customize_headers(CustomizeCB, response_header, H)
+ end,
+ [Header || Header <- Headers0]).
server(ConfigDb) ->
httpd_util:lookup(ConfigDb, server, ?SERVER_SOFTWARE).
-fix_header({Key0, Value}) ->
- %% make sure first letter is capital
- Words1 = string:tokens(Key0, "-"),
- Words2 = upify(Words1, []),
- Key = new_key(Words2),
- Key ++ ": " ++ Value ++ ?CRLF .
-
-new_key([]) ->
- "";
-new_key([W]) ->
- W;
-new_key([W1,W2]) ->
- W1 ++ "-" ++ W2;
-new_key([W|R]) ->
- W ++ "-" ++ new_key(R).
-
-upify([], Acc) ->
- lists:reverse(Acc);
-upify([Key|Rest], Acc) ->
- upify(Rest, [upify2(Key)|Acc]).
-
-upify2([C|Rest]) when (C >= $a) andalso (C =< $z) ->
- [C-($a-$A)|Rest];
-upify2(Str) ->
- Str.
-
add_default_headers([], Headers) ->
Headers;
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index 3b1e16cf78..b45742136a 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -28,7 +28,7 @@
%% Internal application API
-export([start_link/1, start_link/2]).
--export([start_child/1, restart_child/2, stop_child/2]).
+-export([start_child/1, restart_child/3, stop_child/3]).
%% Supervisor callback
-export([init/1]).
@@ -37,7 +37,6 @@
-define(TIMEOUT, 15000).
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
%%%=========================================================================
%%% API
@@ -64,33 +63,32 @@ start_child(Config) ->
end.
-restart_child(Address, Port) ->
- Name = id(Address, Port),
+restart_child(Address, Port, Profile) ->
+ Name = id(Address, Port, Profile),
case supervisor:terminate_child(?MODULE, Name) of
- ok ->
- supervisor:restart_child(?MODULE, Name);
- Error ->
- Error
- end.
-
-stop_child(Address, Port) ->
- Name = id(Address, Port),
+ ok ->
+ supervisor:restart_child(?MODULE, Name);
+ Error ->
+ Error
+ end.
+
+stop_child(Address, Port, Profile) ->
+ Name = id(Address, Port, Profile),
case supervisor:terminate_child(?MODULE, Name) of
- ok ->
- supervisor:delete_child(?MODULE, Name);
- Error ->
+ ok ->
+ supervisor:delete_child(?MODULE, Name);
+ Error ->
Error
end.
-
-id(Address, Port) ->
- {httpd_instance_sup, Address, Port}.
+
+id(Address, Port, Profile) ->
+ {httpd_instance_sup, Address, Port, Profile}.
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
init([HttpdServices]) ->
- ?hdrd("starting", [{httpd_service, HttpdServices}]),
RestartStrategy = one_for_one,
MaxR = 10,
MaxT = 3600,
@@ -118,23 +116,18 @@ init([HttpdServices]) ->
child_specs([], Acc) ->
Acc;
child_specs([{httpd, HttpdService} | Rest], Acc) ->
- ?hdrd("child specs", [{httpd, HttpdService}]),
NewHttpdService = (catch mk_tuple_list(HttpdService)),
- ?hdrd("child specs", [{new_httpd, NewHttpdService}]),
case catch child_spec(NewHttpdService) of
{error, Reason} ->
- ?hdri("failed generating child spec", [{reason, Reason}]),
error_msg("Failed to start service: ~n~p ~n due to: ~p~n",
[HttpdService, Reason]),
child_specs(Rest, Acc);
Spec ->
- ?hdrt("child spec", [{child_spec, Spec}]),
child_specs(Rest, [Spec | Acc])
end.
child_spec(HttpdService) ->
{ok, Config} = httpd_config(HttpdService),
- ?hdrt("child spec", [{config, Config}]),
Debug = proplists:get_value(debug, Config, []),
AcceptTimeout = proplists:get_value(accept_timeout, Config, 15000),
httpd_util:valid_options(Debug, AcceptTimeout, Config),
@@ -162,32 +155,27 @@ httpd_config([Value| _] = Config) when is_tuple(Value) ->
httpd_child_spec([Value| _] = Config, AcceptTimeout, Debug)
when is_tuple(Value) ->
- ?hdrt("httpd_child_spec - entry", [{accept_timeout, AcceptTimeout},
- {debug, Debug}]),
Address = proplists:get_value(bind_address, Config, any),
Port = proplists:get_value(port, Config, 80),
- httpd_child_spec(Config, AcceptTimeout, Debug, Address, Port);
+ Profile = proplists:get_value(profile, Config, ?DEFAULT_PROFILE),
+ httpd_child_spec(Config, AcceptTimeout, Debug, Address, Port, Profile);
%% In this case the AcceptTimeout and Debug will only have default values...
httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) ->
- ?hdrt("httpd_child_spec - entry", [{config_file, ConfigFile},
- {accept_timeout_def, AcceptTimeoutDef},
- {debug_def, DebugDef}]),
case httpd_conf:load(ConfigFile) of
{ok, ConfigList} ->
- ?hdrt("httpd_child_spec - loaded", [{config_list, ConfigList}]),
case (catch httpd_conf:validate_properties(ConfigList)) of
{ok, Config} ->
- ?hdrt("httpd_child_spec - validated", [{config, Config}]),
Address = proplists:get_value(bind_address, Config, any),
Port = proplists:get_value(port, Config, 80),
+ Profile = proplists:get_value(profile, Config, ?DEFAULT_PROFILE),
AcceptTimeout =
proplists:get_value(accept_timeout, Config,
AcceptTimeoutDef),
Debug =
proplists:get_value(debug, Config, DebugDef),
httpd_child_spec([{file, ConfigFile} | Config],
- AcceptTimeout, Debug, Address, Port);
+ AcceptTimeout, Debug, Address, Port, Profile);
Error ->
Error
end;
@@ -195,19 +183,19 @@ httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) ->
Error
end.
-httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port) ->
+httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port, Profile) ->
Fd = proplists:get_value(fd, Config, undefined),
case Port == 0 orelse Fd =/= undefined of
true ->
- httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port);
+ httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile);
false ->
- httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port)
+ httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile)
end.
-httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port) ->
+httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port, Profile) ->
case start_listen(Addr, Port, Config) of
{Pid, {NewPort, NewConfig, ListenSocket}} ->
- Name = {httpd_instance_sup, Addr, NewPort},
+ Name = {httpd_instance_sup, Addr, NewPort, Profile},
StartFunc = {httpd_instance_sup, start_link,
[NewConfig, AcceptTimeout,
{Pid, ListenSocket}, Debug]},
@@ -221,8 +209,8 @@ httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port) ->
{error, Reason}
end.
-httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port) ->
- Name = {httpd_instance_sup, Addr, Port},
+httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port, Profile) ->
+ Name = {httpd_instance_sup, Addr, Port, Profile},
StartFunc = {httpd_instance_sup, start_link,
[Config, AcceptTimeout, Debug]},
Restart = permanent,
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 0d04a75205..b1ddc1abbb 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -572,7 +572,10 @@ make_name(Prefix,Port) ->
make_name(Prefix,Addr,Port) ->
make_name(Prefix,Addr,Port,"").
-
+
+make_name(Prefix, Addr,Port,Postfix) when is_atom(Postfix)->
+ make_name(Prefix, Addr,Port, atom_to_list(Postfix));
+
make_name(Prefix,"*",Port,Postfix) ->
make_name(Prefix,undefined,Port,Postfix);
@@ -595,15 +598,7 @@ make_name2({A,B,C,D}) ->
io_lib:format("~w_~w_~w_~w", [A,B,C,D]);
make_name2({A, B, C, D, E, F, G, H}) ->
- io_lib:format("~s_~s_~s_~s_~s_~s_~s_~s", [integer_to_hexlist(A),
- integer_to_hexlist(B),
- integer_to_hexlist(C),
- integer_to_hexlist(D),
- integer_to_hexlist(E),
- integer_to_hexlist(F),
- integer_to_hexlist(G),
- integer_to_hexlist(H)
- ]);
+ io_lib:format("~w_~w_~w_~w_~w_~w_~w_~w", [A,B,C,D,E,F,G,H]);
make_name2(Addr) ->
search_and_replace(Addr,$.,$_).
diff --git a/lib/inets/src/http_server/mod_actions.erl b/lib/inets/src/http_server/mod_actions.erl
index c3946ff9b4..e493ddbf93 100644
--- a/lib/inets/src/http_server/mod_actions.erl
+++ b/lib/inets/src/http_server/mod_actions.erl
@@ -84,14 +84,14 @@ load("Action "++ Action, []) ->
{ok,[MimeType, CGIScript]} ->
{ok,[],{action, {MimeType, CGIScript}}};
{ok,_} ->
- {error,?NICE(httpd_conf:clean(Action)++" is an invalid Action")}
+ {error,?NICE(string:strip(Action)++" is an invalid Action")}
end;
load("Script " ++ Script,[]) ->
case inets_regexp:split(Script, " ") of
{ok,[Method, CGIScript]} ->
{ok,[],{script, {Method, CGIScript}}};
{ok,_} ->
- {error,?NICE(httpd_conf:clean(Script)++" is an invalid Script")}
+ {error,?NICE(string:strip(Script)++" is an invalid Script")}
end.
store({action, {MimeType, CGIScript}} = Conf, _) when is_list(MimeType),
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 5039cd56b5..e0d34288cd 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -212,7 +212,7 @@ load("Alias " ++ Alias, []) ->
{ok, [FakeName, RealName]} ->
{ok,[],{alias,{FakeName,RealName}}};
{ok, _} ->
- {error,?NICE(httpd_conf:clean(Alias)++" is an invalid Alias")}
+ {error,?NICE(string:strip(Alias)++" is an invalid Alias")}
end;
load("ReWrite " ++ Rule, Acc) ->
load_re_write(Rule, Acc, "ReWrite", re_write);
@@ -223,7 +223,7 @@ load("ScriptAlias " ++ ScriptAlias, []) ->
RealName1 = filename:join(filename:split(RealName)),
{ok, [], {script_alias, {FakeName, RealName1++"/"}}};
{ok, _} ->
- {error, ?NICE(httpd_conf:clean(ScriptAlias)++
+ {error, ?NICE(string:strip(ScriptAlias)++
" is an invalid ScriptAlias")}
end;
load("ScriptReWrite " ++ Rule, Acc) ->
@@ -234,7 +234,7 @@ load_re_write(Rule0, Acc, Type, Tag) ->
fun ($\s) -> true; ($\t) -> true; (_) -> false end,
Rule0) of
"" ->
- {error, ?NICE(httpd_conf:clean(Rule0)++" is an invalid "++Type)};
+ {error, ?NICE(string:strip(Rule0)++" is an invalid "++Type)};
Rule ->
case string:chr(Rule, $\s) of
0 ->
diff --git a/lib/inets/src/http_server/mod_auth.erl b/lib/inets/src/http_server/mod_auth.erl
index 85a87ab884..ae716a6cff 100644
--- a/lib/inets/src/http_server/mod_auth.erl
+++ b/lib/inets/src/http_server/mod_auth.erl
@@ -38,15 +38,16 @@
-include("httpd.hrl").
-include("mod_auth.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-define(VMODULE,"AUTH").
-define(NOPASSWORD,"NoPassword").
-%% do
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
do(Info) ->
- ?hdrt("do", [{info, Info}]),
case proplists:get_value(status,Info#mod.data) of
%% A status code has been generated!
{_StatusCode, _PhraseArgs, _Reason} ->
@@ -61,22 +62,15 @@ do(Info) ->
%% Is it a secret area?
case secretp(Path,Info#mod.config_db) of
{yes, {Directory, DirectoryData}} ->
- ?hdrt("secret area",
- [{directory, Directory},
- {directory_data, DirectoryData}]),
-
- %% Authenticate (allow)
case allow((Info#mod.init_data)#init_data.peername,
Info#mod.socket_type,Info#mod.socket,
DirectoryData) of
allowed ->
- ?hdrt("allowed", []),
case deny((Info#mod.init_data)#init_data.peername,
Info#mod.socket_type,
Info#mod.socket,
DirectoryData) of
not_denied ->
- ?hdrt("not denied", []),
case proplists:get_value(auth_type,
DirectoryData) of
undefined ->
@@ -90,15 +84,13 @@ do(Info) ->
AuthType)
end;
{denied, Reason} ->
- ?hdrt("denied", [{reason, Reason}]),
{proceed,
[{status, {403,
- Info#mod.request_uri,
- Reason}}|
+ Info#mod.request_uri,
+ Reason}}|
Info#mod.data]}
end;
{not_allowed, Reason} ->
- ?hdrt("not allowed", [{reason, Reason}]),
{proceed,[{status,{403,
Info#mod.request_uri,
Reason}} |
@@ -114,18 +106,299 @@ do(Info) ->
end.
-do_auth(Info, Directory, DirectoryData, AuthType) ->
+%% mod_auth recognizes the following Configuration Directives:
+%% <Directory /path/to/directory>
+%% AuthDBType
+%% AuthName
+%% AuthUserFile
+%% AuthGroupFile
+%% AuthAccessPassword
+%% require
+%% allow
+%% </Directory>
+
+%% When a <Directory> directive is found, a new context is set to
+%% [{directory, Directory, DirData}|OtherContext]
+%% DirData in this case is a key-value list of data belonging to the
+%% directory in question.
+%%
+%% When the </Directory> statement is found, the Context created earlier
+%% will be returned as a ConfigList and the context will return to the
+%% state it was previously.
+
+load("<Directory " ++ Directory,[]) ->
+ Dir = string:strip(string:strip(Directory),right, $>),
+ {ok,[{directory, {Dir, [{path, Dir}]}}]};
+load(eof,[{directory, {Directory, _DirData}}|_]) ->
+ {error, ?NICE("Premature end-of-file in "++ Directory)};
+
+load("AuthName " ++ AuthName, [{directory, {Directory, DirData}}|Rest]) ->
+ {ok, [{directory, {Directory,
+ [{auth_name, string:strip(AuthName)} | DirData]}}
+ | Rest ]};
+load("AuthUserFile " ++ AuthUserFile0,
+ [{directory, {Directory, DirData}}|Rest]) ->
+ AuthUserFile = string:strip(AuthUserFile0),
+ {ok, [{directory, {Directory,
+ [{auth_user_file, AuthUserFile}|DirData]}} | Rest ]};
+load("AuthGroupFile " ++ AuthGroupFile0,
+ [{directory, {Directory, DirData}}|Rest]) ->
+ AuthGroupFile = string:strip(AuthGroupFile0),
+ {ok,[{directory, {Directory,
+ [{auth_group_file, AuthGroupFile}|DirData]}} | Rest]};
+
+load("AuthAccessPassword " ++ AuthAccessPassword0,
+ [{directory, {Directory, DirData}}|Rest]) ->
+ AuthAccessPassword = string:strip(AuthAccessPassword0),
+ {ok,[{directory, {Directory,
+ [{auth_access_password, AuthAccessPassword}|DirData]}} | Rest]};
+
+load("AuthDBType " ++ Type,
+ [{directory, {Dir, DirData}}|Rest]) ->
+ case string:strip(Type) of
+ "plain" ->
+ {ok, [{directory, {Dir, [{auth_type, plain}|DirData]}} | Rest ]};
+ "mnesia" ->
+ {ok, [{directory, {Dir, [{auth_type, mnesia}|DirData]}} | Rest ]};
+ "dets" ->
+ {ok, [{directory, {Dir, [{auth_type, dets}|DirData]}} | Rest ]};
+ _ ->
+ {error, ?NICE(string:strip(Type)++" is an invalid AuthDBType")}
+ end;
+
+load("require " ++ Require,[{directory, {Directory, DirData}}|Rest]) ->
+ case inets_regexp:split(Require," ") of
+ {ok,["user"|Users]} ->
+ {ok,[{directory, {Directory,
+ [{require_user,Users}|DirData]}} | Rest]};
+ {ok,["group"|Groups]} ->
+ {ok,[{directory, {Directory,
+ [{require_group,Groups}|DirData]}} | Rest]};
+ {ok,_} ->
+ {error,?NICE(string:strip(Require) ++" is an invalid require")}
+ end;
+
+load("allow " ++ Allow,[{directory, {Directory, DirData}}|Rest]) ->
+ case inets_regexp:split(Allow," ") of
+ {ok,["from","all"]} ->
+ {ok,[{directory, {Directory,
+ [{allow_from,all}|DirData]}} | Rest]};
+ {ok,["from"|Hosts]} ->
+ {ok,[{directory, {Directory,
+ [{allow_from,Hosts}|DirData]}} | Rest]};
+ {ok,_} ->
+ {error,?NICE(string:strip(Allow) ++" is an invalid allow")}
+ end;
+
+load("deny " ++ Deny,[{directory, {Directory, DirData}}|Rest]) ->
+ case inets_regexp:split(Deny," ") of
+ {ok, ["from", "all"]} ->
+ {ok,[{{directory, Directory,
+ [{deny_from, all}|DirData]}} | Rest]};
+ {ok, ["from"|Hosts]} ->
+ {ok,[{{directory, Directory,
+ [{deny_from, Hosts}|DirData]}} | Rest]};
+ {ok, _} ->
+ {error,?NICE(string:strip(Deny) ++" is an invalid deny")}
+ end;
+
+load("</Directory>",[{directory, {Directory, DirData}}|Rest]) ->
+ {ok, Rest, {directory, {Directory, DirData}}};
+
+load("AuthMnesiaDB " ++ AuthMnesiaDB,
+ [{directory, {Dir, DirData}}|Rest]) ->
+ case string:strip(AuthMnesiaDB) of
+ "On" ->
+ {ok,[{directory, {Dir,[{auth_type,mnesia}|DirData]}}|Rest]};
+ "Off" ->
+ {ok,[{directory, {Dir,[{auth_type,plain}|DirData]}}|Rest]};
+ _ ->
+ {error, ?NICE(string:strip(AuthMnesiaDB) ++
+ " is an invalid AuthMnesiaDB")}
+ end.
+
+store({directory, {Directory, DirData}}, ConfigList)
+ when is_list(Directory) andalso is_list(DirData) ->
+ try directory_config_check(Directory, DirData) of
+ ok ->
+ store_directory(Directory, DirData, ConfigList)
+ catch
+ throw:Error ->
+ {error, Error, {directory, Directory, DirData}}
+ end;
+store({directory, {Directory, DirData}}, _) ->
+ {error, {wrong_type, {directory, {Directory, DirData}}}}.
+
+remove(ConfigDB) ->
+ lists:foreach(fun({directory, {_Dir, DirData}}) ->
+ AuthMod = auth_mod_name(DirData),
+ (catch apply(AuthMod, remove, [DirData]))
+ end,
+ ets:match_object(ConfigDB,{directory,{'_','_'}})),
+
+ Addr = httpd_util:lookup(ConfigDB, bind_address, undefined),
+ Port = httpd_util:lookup(ConfigDB, port),
+ Profile = httpd_util:lookup(ConfigDB, profile, ?DEFAULT_PROFILE),
+ mod_auth_server:stop(Addr, Port, Profile),
+ ok.
+
+add_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ case get_options(Opt, userData) of
+ {error, Reason}->
+ {error, Reason};
+ {UserData, Password}->
+ User = [#httpd_user{username = UserName,
+ password = Password,
+ user_data = UserData}],
+ mod_auth_server:add_user(Addr, Port, Dir, User, AuthPwd)
+ end
+ end.
+
+
+add_user(UserName, Password, UserData, Port, Dir) ->
+ add_user(UserName, Password, UserData, undefined, Port, Dir).
+add_user(UserName, Password, UserData, Addr, Port, Dir) ->
+ User = [#httpd_user{username = UserName,
+ password = Password,
+ user_data = UserData}],
+ mod_auth_server:add_user(Addr, Port, Dir, User, ?NOPASSWORD).
+
+get_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:get_user(Addr, Port, Dir, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+get_user(UserName, Port, Dir) ->
+ get_user(UserName, undefined, Port, Dir).
+get_user(UserName, Addr, Port, Dir) ->
+ mod_auth_server:get_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
+
+add_group_member(GroupName, UserName, Opt)->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ mod_auth_server:add_group_member(Addr, Port, Dir,
+ GroupName, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+add_group_member(GroupName, UserName, Port, Dir) ->
+ add_group_member(GroupName, UserName, undefined, Port, Dir).
+
+add_group_member(GroupName, UserName, Addr, Port, Dir) ->
+ mod_auth_server:add_group_member(Addr, Port, Dir,
+ GroupName, UserName, ?NOPASSWORD).
+
+delete_group_member(GroupName, UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:delete_group_member(Addr, Port, Dir,
+ GroupName, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_group_member(GroupName, UserName, Port, Dir) ->
+ delete_group_member(GroupName, UserName, undefined, Port, Dir).
+delete_group_member(GroupName, UserName, Addr, Port, Dir) ->
+ mod_auth_server:delete_group_member(Addr, Port, Dir,
+ GroupName, UserName, ?NOPASSWORD).
+
+list_users(Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:list_users(Addr, Port, Dir, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_users(Port, Dir) ->
+ list_users(undefined, Port, Dir).
+list_users(Addr, Port, Dir) ->
+ mod_auth_server:list_users(Addr, Port, Dir, ?NOPASSWORD).
+
+delete_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:delete_user(Addr, Port, Dir, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_user(UserName, Port, Dir) ->
+ delete_user(UserName, undefined, Port, Dir).
+delete_user(UserName, Addr, Port, Dir) ->
+ mod_auth_server:delete_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
+
+delete_group(GroupName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:delete_group(Addr, Port, Dir, GroupName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_group(GroupName, Port, Dir) ->
+ delete_group(GroupName, undefined, Port, Dir).
+delete_group(GroupName, Addr, Port, Dir) ->
+ mod_auth_server:delete_group(Addr, Port, Dir, GroupName, ?NOPASSWORD).
+
+list_groups(Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:list_groups(Addr, Port, Dir, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_groups(Port, Dir) ->
+ list_groups(undefined, Port, Dir).
+list_groups(Addr, Port, Dir) ->
+ mod_auth_server:list_groups(Addr, Port, Dir, ?NOPASSWORD).
+
+list_group_members(GroupName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:list_group_members(Addr, Port, Dir, GroupName,
+ AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_group_members(GroupName, Port, Dir) ->
+ list_group_members(GroupName, undefined, Port, Dir).
+list_group_members(GroupName, Addr, Port, Dir) ->
+ mod_auth_server:list_group_members(Addr, Port, Dir,
+ GroupName, ?NOPASSWORD).
+
+update_password(Port, Dir, Old, New, New)->
+ update_password(undefined, Port, Dir, Old, New, New).
+
+update_password(Addr, Port, Dir, Old, New, New) when is_list(New) ->
+ mod_auth_server:update_password(Addr, Port, Dir, Old, New);
+
+update_password(_Addr, _Port, _Dir, _Old, _New, _New) ->
+ {error, badtype};
+update_password(_Addr, _Port, _Dir, _Old, _New, _New1) ->
+ {error, notqeual}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+do_auth(Info, Directory, DirectoryData, _AuthType) ->
%% Authenticate (require)
- ?hdrt("authenticate", [{auth_type, AuthType}]),
case require(Info, Directory, DirectoryData) of
authorized ->
- ?hdrt("authorized", []),
{proceed,Info#mod.data};
{authorized, User} ->
- ?hdrt("authorized", [{user, User}]),
{proceed, [{remote_user,User}|Info#mod.data]};
{authorization_required, Realm} ->
- ?hdrt("authorization required", [{realm, Realm}]),
ReasonPhrase = httpd_util:reason_phrase(401),
Message = httpd_util:message(401,none,Info#mod.config_db),
{proceed,
@@ -142,8 +415,6 @@ do_auth(Info, Directory, DirectoryData, AuthType) ->
Info#mod.data]}
end.
-%% require
-
require(Info, Directory, DirectoryData) ->
ParsedHeader = Info#mod.parsed_header,
ValidUsers = proplists:get_value(require_user, DirectoryData),
@@ -270,13 +541,6 @@ auth_mod_name(DirData) ->
dets -> mod_auth_dets
end.
-
-%%
-%% Is it a secret area?
-%%
-
-%% secretp
-
secretp(Path,ConfigDB) ->
Directories = ets:match(ConfigDB,{directory, {'$1','_'}}),
case secret_path(Path, Directories) of
@@ -307,12 +571,6 @@ secret_path(Path, [[NewDirectory] | Rest], Directory) ->
secret_path(Path, Rest, Directory)
end.
-%%
-%% Authenticate
-%%
-
-%% allow
-
allow({_,RemoteAddr}, _SocketType, _Socket, DirectoryData) ->
Hosts = proplists:get_value(allow_from, DirectoryData, all),
case validate_addr(RemoteAddr, Hosts) of
@@ -336,8 +594,6 @@ validate_addr(RemoteAddr, [HostRegExp | Rest]) ->
validate_addr(RemoteAddr,Rest)
end.
-%% deny
-
deny({_,RemoteAddr}, _SocketType, _Socket,DirectoryData) ->
Hosts = proplists:get_value(deny_from, DirectoryData, none),
case validate_addr(RemoteAddr,Hosts) of
@@ -347,124 +603,6 @@ deny({_,RemoteAddr}, _SocketType, _Socket,DirectoryData) ->
not_denied
end.
-%%
-%% Configuration
-%%
-
-%% load/2
-%%
-
-%% mod_auth recognizes the following Configuration Directives:
-%% <Directory /path/to/directory>
-%% AuthDBType
-%% AuthName
-%% AuthUserFile
-%% AuthGroupFile
-%% AuthAccessPassword
-%% require
-%% allow
-%% </Directory>
-
-%% When a <Directory> directive is found, a new context is set to
-%% [{directory, Directory, DirData}|OtherContext]
-%% DirData in this case is a key-value list of data belonging to the
-%% directory in question.
-%%
-%% When the </Directory> statement is found, the Context created earlier
-%% will be returned as a ConfigList and the context will return to the
-%% state it was previously.
-
-load("<Directory " ++ Directory,[]) ->
- Dir = httpd_conf:custom_clean(Directory,"",">"),
- {ok,[{directory, {Dir, [{path, Dir}]}}]};
-load(eof,[{directory, {Directory, _DirData}}|_]) ->
- {error, ?NICE("Premature end-of-file in "++ Directory)};
-
-load("AuthName " ++ AuthName, [{directory, {Directory, DirData}}|Rest]) ->
- {ok, [{directory, {Directory,
- [{auth_name, httpd_conf:clean(AuthName)} | DirData]}}
- | Rest ]};
-load("AuthUserFile " ++ AuthUserFile0,
- [{directory, {Directory, DirData}}|Rest]) ->
- AuthUserFile = httpd_conf:clean(AuthUserFile0),
- {ok, [{directory, {Directory,
- [{auth_user_file, AuthUserFile}|DirData]}} | Rest ]};
-load("AuthGroupFile " ++ AuthGroupFile0,
- [{directory, {Directory, DirData}}|Rest]) ->
- AuthGroupFile = httpd_conf:clean(AuthGroupFile0),
- {ok,[{directory, {Directory,
- [{auth_group_file, AuthGroupFile}|DirData]}} | Rest]};
-
-%AuthAccessPassword
-load("AuthAccessPassword " ++ AuthAccessPassword0,
- [{directory, {Directory, DirData}}|Rest]) ->
- AuthAccessPassword = httpd_conf:clean(AuthAccessPassword0),
- {ok,[{directory, {Directory,
- [{auth_access_password, AuthAccessPassword}|DirData]}} | Rest]};
-
-load("AuthDBType " ++ Type,
- [{directory, {Dir, DirData}}|Rest]) ->
- case httpd_conf:clean(Type) of
- "plain" ->
- {ok, [{directory, {Dir, [{auth_type, plain}|DirData]}} | Rest ]};
- "mnesia" ->
- {ok, [{directory, {Dir, [{auth_type, mnesia}|DirData]}} | Rest ]};
- "dets" ->
- {ok, [{directory, {Dir, [{auth_type, dets}|DirData]}} | Rest ]};
- _ ->
- {error, ?NICE(httpd_conf:clean(Type)++" is an invalid AuthDBType")}
- end;
-
-load("require " ++ Require,[{directory, {Directory, DirData}}|Rest]) ->
- case inets_regexp:split(Require," ") of
- {ok,["user"|Users]} ->
- {ok,[{directory, {Directory,
- [{require_user,Users}|DirData]}} | Rest]};
- {ok,["group"|Groups]} ->
- {ok,[{directory, {Directory,
- [{require_group,Groups}|DirData]}} | Rest]};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Require) ++" is an invalid require")}
- end;
-
-load("allow " ++ Allow,[{directory, {Directory, DirData}}|Rest]) ->
- case inets_regexp:split(Allow," ") of
- {ok,["from","all"]} ->
- {ok,[{directory, {Directory,
- [{allow_from,all}|DirData]}} | Rest]};
- {ok,["from"|Hosts]} ->
- {ok,[{directory, {Directory,
- [{allow_from,Hosts}|DirData]}} | Rest]};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Allow) ++" is an invalid allow")}
- end;
-
-load("deny " ++ Deny,[{directory, {Directory, DirData}}|Rest]) ->
- case inets_regexp:split(Deny," ") of
- {ok, ["from", "all"]} ->
- {ok,[{{directory, Directory,
- [{deny_from, all}|DirData]}} | Rest]};
- {ok, ["from"|Hosts]} ->
- {ok,[{{directory, Directory,
- [{deny_from, Hosts}|DirData]}} | Rest]};
- {ok, _} ->
- {error,?NICE(httpd_conf:clean(Deny) ++" is an invalid deny")}
- end;
-
-load("</Directory>",[{directory, {Directory, DirData}}|Rest]) ->
- {ok, Rest, {directory, {Directory, DirData}}};
-
-load("AuthMnesiaDB " ++ AuthMnesiaDB,
- [{directory, {Dir, DirData}}|Rest]) ->
- case httpd_conf:clean(AuthMnesiaDB) of
- "On" ->
- {ok,[{directory, {Dir,[{auth_type,mnesia}|DirData]}}|Rest]};
- "Off" ->
- {ok,[{directory, {Dir,[{auth_type,plain}|DirData]}}|Rest]};
- _ ->
- {error, ?NICE(httpd_conf:clean(AuthMnesiaDB) ++
- " is an invalid AuthMnesiaDB")}
- end.
directory_config_check(Directory, DirData) ->
case proplists:get_value(auth_type, DirData) of
@@ -482,25 +620,7 @@ check_filename_present(Dir,AuthFile,DirData) ->
throw({missing_auth_file, AuthFile, {directory, {Dir, DirData}}})
end.
-%% store
-
-store({directory, {Directory, DirData}}, ConfigList)
- when is_list(Directory) andalso is_list(DirData) ->
- ?hdrt("store",
- [{directory, Directory}, {dir_data, DirData}]),
- try directory_config_check(Directory, DirData) of
- ok ->
- store_directory(Directory, DirData, ConfigList)
- catch
- throw:Error ->
- {error, Error, {directory, Directory, DirData}}
- end;
-store({directory, {Directory, DirData}}, _) ->
- {error, {wrong_type, {directory, {Directory, DirData}}}}.
-
store_directory(Directory0, DirData0, ConfigList) ->
- ?hdrt("store directory - entry",
- [{directory, Directory0}, {dir_data, DirData0}]),
Port = proplists:get_value(port, ConfigList),
DirData = case proplists:get_value(bind_address, ConfigList) of
undefined ->
@@ -522,9 +642,7 @@ store_directory(Directory0, DirData0, ConfigList) ->
dets -> mod_auth_dets;
plain -> mod_auth_plain;
_ -> no_module_at_all
- end,
- ?hdrt("store directory",
- [{directory, Directory}, {dir_data, DirData}, {auth_mod, AuthMod}]),
+ end,
case AuthMod of
no_module_at_all ->
{ok, {directory, {Directory, DirData}}};
@@ -560,204 +678,10 @@ store_directory(Directory0, DirData0, ConfigList) ->
add_auth_password(Dir, Pwd0, ConfigList) ->
Addr = proplists:get_value(bind_address, ConfigList),
Port = proplists:get_value(port, ConfigList),
- mod_auth_server:start(Addr, Port),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
+ mod_auth_server:start(Addr, Port, Profile),
mod_auth_server:add_password(Addr, Port, Dir, Pwd0).
-%% remove
-
-
-remove(ConfigDB) ->
- lists:foreach(fun({directory, {_Dir, DirData}}) ->
- AuthMod = auth_mod_name(DirData),
- (catch apply(AuthMod, remove, [DirData]))
- end,
- ets:match_object(ConfigDB,{directory,{'_','_'}})),
- Addr = case lookup(ConfigDB, bind_address) of
- [] ->
- undefined;
- [{bind_address, Address}] ->
- Address
- end,
- [{port, Port}] = lookup(ConfigDB, port),
- mod_auth_server:stop(Addr, Port),
- ok.
-
-%% --------------------------------------------------------------------
-
-%% update_password
-
-update_password(Port, Dir, Old, New, New)->
- update_password(undefined, Port, Dir, Old, New, New).
-
-update_password(Addr, Port, Dir, Old, New, New) when is_list(New) ->
- mod_auth_server:update_password(Addr, Port, Dir, Old, New);
-
-update_password(_Addr, _Port, _Dir, _Old, _New, _New) ->
- {error, badtype};
-update_password(_Addr, _Port, _Dir, _Old, _New, _New1) ->
- {error, notqeual}.
-
-
-%% add_user
-
-add_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- case get_options(Opt, userData) of
- {error, Reason}->
- {error, Reason};
- {UserData, Password}->
- User = [#httpd_user{username = UserName,
- password = Password,
- user_data = UserData}],
- mod_auth_server:add_user(Addr, Port, Dir, User, AuthPwd)
- end
- end.
-
-
-add_user(UserName, Password, UserData, Port, Dir) ->
- add_user(UserName, Password, UserData, undefined, Port, Dir).
-add_user(UserName, Password, UserData, Addr, Port, Dir) ->
- User = [#httpd_user{username = UserName,
- password = Password,
- user_data = UserData}],
- mod_auth_server:add_user(Addr, Port, Dir, User, ?NOPASSWORD).
-
-
-%% get_user
-
-get_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:get_user(Addr, Port, Dir, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-get_user(UserName, Port, Dir) ->
- get_user(UserName, undefined, Port, Dir).
-get_user(UserName, Addr, Port, Dir) ->
- mod_auth_server:get_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
-
-
-%% add_group_member
-
-add_group_member(GroupName, UserName, Opt)->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- mod_auth_server:add_group_member(Addr, Port, Dir,
- GroupName, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-add_group_member(GroupName, UserName, Port, Dir) ->
- add_group_member(GroupName, UserName, undefined, Port, Dir).
-
-add_group_member(GroupName, UserName, Addr, Port, Dir) ->
- mod_auth_server:add_group_member(Addr, Port, Dir,
- GroupName, UserName, ?NOPASSWORD).
-
-
-%% delete_group_member
-
-delete_group_member(GroupName, UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:delete_group_member(Addr, Port, Dir,
- GroupName, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_group_member(GroupName, UserName, Port, Dir) ->
- delete_group_member(GroupName, UserName, undefined, Port, Dir).
-delete_group_member(GroupName, UserName, Addr, Port, Dir) ->
- mod_auth_server:delete_group_member(Addr, Port, Dir,
- GroupName, UserName, ?NOPASSWORD).
-
-
-%% list_users
-
-list_users(Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:list_users(Addr, Port, Dir, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_users(Port, Dir) ->
- list_users(undefined, Port, Dir).
-list_users(Addr, Port, Dir) ->
- mod_auth_server:list_users(Addr, Port, Dir, ?NOPASSWORD).
-
-
-%% delete_user
-
-delete_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:delete_user(Addr, Port, Dir, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_user(UserName, Port, Dir) ->
- delete_user(UserName, undefined, Port, Dir).
-delete_user(UserName, Addr, Port, Dir) ->
- mod_auth_server:delete_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
-
-
-%% delete_group
-
-delete_group(GroupName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:delete_group(Addr, Port, Dir, GroupName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_group(GroupName, Port, Dir) ->
- delete_group(GroupName, undefined, Port, Dir).
-delete_group(GroupName, Addr, Port, Dir) ->
- mod_auth_server:delete_group(Addr, Port, Dir, GroupName, ?NOPASSWORD).
-
-
-%% list_groups
-
-list_groups(Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:list_groups(Addr, Port, Dir, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_groups(Port, Dir) ->
- list_groups(undefined, Port, Dir).
-list_groups(Addr, Port, Dir) ->
- mod_auth_server:list_groups(Addr, Port, Dir, ?NOPASSWORD).
-
-
-%% list_group_members
-
-list_group_members(GroupName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:list_group_members(Addr, Port, Dir, GroupName,
- AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_group_members(GroupName, Port, Dir) ->
- list_group_members(GroupName, undefined, Port, Dir).
-list_group_members(GroupName, Addr, Port, Dir) ->
- mod_auth_server:list_group_members(Addr, Port, Dir,
- GroupName, ?NOPASSWORD).
-
%% Opt = [{port, Port},
%% {addr, Addr},
%% {dir, Dir},
@@ -792,7 +716,3 @@ get_options(Opt, userData)->
{UserData, Pwd}
end
end.
-
-
-lookup(Db, Key) ->
- ets:lookup(Db, Key).
diff --git a/lib/inets/src/http_server/mod_auth_dets.erl b/lib/inets/src/http_server/mod_auth_dets.erl
index a48725d5d9..4220f46166 100644
--- a/lib/inets/src/http_server/mod_auth_dets.erl
+++ b/lib/inets/src/http_server/mod_auth_dets.erl
@@ -38,23 +38,23 @@
-include("httpd_internal.hrl").
-include("mod_auth.hrl").
-store_directory_data(_Directory, DirData, Server_root) ->
- ?CDEBUG("store_directory_data -> ~n"
- " Directory: ~p~n"
- " DirData: ~p",
- [_Directory, DirData]),
+%%====================================================================
+%% Internal application API
+%%====================================================================
+store_directory_data(_Directory, DirData, Server_root) ->
{PWFile, Absolute_pwdfile} = absolute_file_name(auth_user_file, DirData,
Server_root),
{GroupFile, Absolute_groupfile} = absolute_file_name(auth_group_file,
DirData, Server_root),
Addr = proplists:get_value(bind_address, DirData),
Port = proplists:get_value(port, DirData),
+ Profile = proplists:get_value(profile, DirData, ?DEFAULT_PROFILE),
- PWName = httpd_util:make_name("httpd_dets_pwdb",Addr,Port),
+ PWName = httpd_util:make_name("httpd_dets_pwdb", Addr, Port, Profile),
case dets:open_file(PWName,[{type,set},{file,Absolute_pwdfile},{repair,true}]) of
{ok, PWDB} ->
- GDBName = httpd_util:make_name("httpd_dets_groupdb",Addr,Port),
+ GDBName = httpd_util:make_name("httpd_dets_groupdb", Addr, Port, Profile),
case dets:open_file(GDBName,[{type,set},{file,Absolute_groupfile},{repair,true}]) of
{ok, GDB} ->
NDD1 = lists:keyreplace(auth_user_file, 1, DirData,
@@ -69,11 +69,8 @@ store_directory_data(_Directory, DirData, Server_root) ->
{error, {{file, PWFile},Err2}}
end.
-%%
%% Storage format of users in the dets table:
%% {{UserName, Addr, Port, Dir}, Password, UserData}
-%%
-
add_user(DirData, UStruct) ->
{Addr, Port, Dir} = lookup_common(DirData),
PWDB = proplists:get_value(auth_user_file, DirData),
@@ -99,21 +96,15 @@ get_user(DirData, UserName) ->
end.
list_users(DirData) ->
- ?DEBUG("list_users -> ~n"
- " DirData: ~p", [DirData]),
{Addr, Port, Dir} = lookup_common(DirData),
PWDB = proplists:get_value(auth_user_file, DirData),
- case dets:traverse(PWDB, fun(X) -> {continue, X} end) of %% SOOOO Ugly !
+ case dets:traverse(PWDB, fun(X) -> {continue, X} end) of
Records when is_list(Records) ->
- ?DEBUG("list_users -> ~n"
- " Records: ~p", [Records]),
{ok, [UserName || {{UserName, AnyAddr, AnyPort, AnyDir},
_Password, _Data} <- Records,
AnyAddr == Addr, AnyPort == Port,
AnyDir == Dir]};
_O ->
- ?DEBUG("list_users -> ~n"
- " O: ~p", [_O]),
{ok, []}
end.
@@ -134,10 +125,8 @@ delete_user(DirData, UserName) ->
{error, no_such_user}
end.
-%%
%% Storage of groups in the dets table:
%% {Group, UserList} where UserList is a list of strings.
-%%
add_group_member(DirData, GroupName, UserName) ->
{Addr, Port, Dir} = lookup_common(DirData),
GDB = proplists:get_value(auth_group_file, DirData),
@@ -215,16 +204,7 @@ delete_group(DirData, GroupName) ->
{error, no_such_group}
end.
-lookup_common(DirData) ->
- Dir = proplists:get_value(path, DirData),
- Port = proplists:get_value(port, DirData),
- Addr = proplists:get_value(bind_address, DirData),
- {Addr, Port, Dir}.
-
-%% remove/1
-%%
%% Closes dets tables used by this auth mod.
-%%
remove(DirData) ->
PWDB = proplists:get_value(auth_user_file, DirData),
GDB = proplists:get_value(auth_group_file, DirData),
@@ -232,8 +212,9 @@ remove(DirData) ->
dets:close(PWDB),
ok.
-%% absolute_file_name/2
-%%
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
%% Return the absolute path name of File_type.
absolute_file_name(File_type, DirData, Server_root) ->
Path = proplists:get_value(File_type, DirData),
@@ -253,3 +234,8 @@ absolute_file_name(File_type, DirData, Server_root) ->
end,
{Path, Absolute_path}.
+lookup_common(DirData) ->
+ Dir = proplists:get_value(path, DirData),
+ Port = proplists:get_value(port, DirData),
+ Addr = proplists:get_value(bind_address, DirData),
+ {Addr, Port, Dir}.
diff --git a/lib/inets/src/http_server/mod_auth_plain.erl b/lib/inets/src/http_server/mod_auth_plain.erl
index c0a83711ba..b411202efc 100644
--- a/lib/inets/src/http_server/mod_auth_plain.erl
+++ b/lib/inets/src/http_server/mod_auth_plain.erl
@@ -22,15 +22,11 @@
-include("httpd.hrl").
-include("mod_auth.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-
-define(VMODULE,"AUTH_PLAIN").
%% Internal API
-export([store_directory_data/3]).
-
-
-export([get_user/2,
list_group_members/2,
add_user/2,
@@ -42,17 +38,13 @@
delete_group/2,
remove/1]).
-%%
-%% API
-%%
+%%====================================================================
+%% Internal application API
+%%====================================================================
-%%
%% Storage format of users in the ets table:
%% {UserName, Password, UserData}
-%%
-
add_user(DirData, #httpd_user{username = User} = UStruct) ->
- ?hdrt("add user", [{user, UStruct}]),
PWDB = proplists:get_value(auth_user_file, DirData),
Record = {User,
UStruct#httpd_user.password,
@@ -66,7 +58,6 @@ add_user(DirData, #httpd_user{username = User} = UStruct) ->
end.
get_user(DirData, User) ->
- ?hdrt("get user", [{dir_data, DirData}, {user, User}]),
PWDB = proplists:get_value(auth_user_file, DirData),
case ets:lookup(PWDB, User) of
[{User, PassWd, Data}] ->
@@ -84,7 +75,6 @@ list_users(DirData) ->
[], lists:flatten(Records))}.
delete_user(DirData, UserName) ->
- ?hdrt("delete user", [{dir_data, DirData}, {user, UserName}]),
PWDB = proplists:get_value(auth_user_file, DirData),
case ets:lookup(PWDB, UserName) of
[{UserName, _SomePassword, _SomeData}] ->
@@ -98,11 +88,8 @@ delete_user(DirData, UserName) ->
{error, no_such_user}
end.
-%%
%% Storage of groups in the ets table:
%% {Group, UserList} where UserList is a list of strings.
-%%
-
add_group_member(DirData, Group, UserName) ->
GDB = proplists:get_value(auth_group_file, DirData),
case ets:lookup(GDB, Group) of
@@ -163,17 +150,12 @@ delete_group(DirData, Group) ->
end.
store_directory_data(_Directory, DirData, Server_root) ->
- ?hdrt("store directory data",
- [{dir_data, DirData}, {server_root, Server_root}]),
PWFile = absolute_file_name(auth_user_file, DirData, Server_root),
GroupFile = absolute_file_name(auth_group_file, DirData, Server_root),
case load_passwd(PWFile) of
{ok, PWDB} ->
- ?hdrt("password file loaded", [{file, PWFile}, {pwdb, PWDB}]),
case load_group(GroupFile) of
{ok, GRDB} ->
- ?hdrt("group file loaded",
- [{file, GroupFile}, {grdb, GRDB}]),
%% Address and port is included in the file names...
Addr = proplists:get_value(bind_address, DirData),
Port = proplists:get_value(port, DirData),
@@ -191,9 +173,83 @@ store_directory_data(_Directory, DirData, Server_root) ->
{error, Err2}
end.
+%% Deletes ets tables used by this auth mod.
+remove(DirData) ->
+ PWDB = proplists:get_value(auth_user_file, DirData),
+ GDB = proplists:get_value(auth_group_file, DirData),
+ ets:delete(PWDB),
+ ets:delete(GDB).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+%% Return the absolute path name of File_type.
+absolute_file_name(File_type, DirData, Server_root) ->
+ Path = proplists:get_value(File_type, DirData),
+ case filename:pathtype(Path) of
+ relative ->
+ case Server_root of
+ undefined ->
+ {error,
+ ?NICE(Path++
+ " is an invalid file name because "
+ "ServerRoot is not defined")};
+ _ ->
+ filename:join(Server_root,Path)
+ end;
+ _ ->
+ Path
+ end.
+
+store_group(Addr,Port,GroupList) ->
+ %% Not a named table so not importante to add Profile to name
+ Name = httpd_util:make_name("httpd_group",Addr,Port),
+ GroupDB = ets:new(Name, [set, public]),
+ store_group(GroupDB, GroupList).
+
+store_group(GroupDB,[]) ->
+ {ok, GroupDB};
+store_group(GroupDB, [User|Rest]) ->
+ ets:insert(GroupDB, User),
+ store_group(GroupDB, Rest).
+
+store_passwd(Addr,Port,PasswdList) ->
+ %% Not a named table so not importante to add Profile to name
+ Name = httpd_util:make_name("httpd_passwd",Addr,Port),
+ PasswdDB = ets:new(Name, [set, public]),
+ store_passwd(PasswdDB, PasswdList).
+store_passwd(PasswdDB, []) ->
+ {ok, PasswdDB};
+store_passwd(PasswdDB, [User|Rest]) ->
+ ets:insert(PasswdDB, User),
+ store_passwd(PasswdDB, Rest).
-%% load_passwd
+parse_group(Stream, GroupList) ->
+ Line =
+ case io:get_line(Stream,'') of
+ eof ->
+ eof;
+ String ->
+ httpd_conf:white_space_clean(String)
+ end,
+ parse_group(Stream, GroupList, Line).
+
+parse_group(Stream, GroupList, eof) ->
+ file:close(Stream),
+ {ok, GroupList};
+parse_group(Stream, GroupList, "") ->
+ parse_group(Stream, GroupList);
+parse_group(Stream, GroupList, [$#|_]) ->
+ parse_group(Stream, GroupList);
+parse_group(Stream, GroupList, Line) ->
+ case inets_regexp:split(Line, ":") of
+ {ok, [Group,Users]} ->
+ {ok, UserList} = inets_regexp:split(Users," "),
+ parse_group(Stream, [{Group,UserList}|GroupList]);
+ {ok, _} ->
+ {error, ?NICE(Line)}
+ end.
load_passwd(AuthUserFile) ->
case file:open(AuthUserFile, [read]) of
@@ -209,7 +265,7 @@ parse_passwd(Stream, PasswdList) ->
eof ->
eof;
String ->
- httpd_conf:clean(String)
+ httpd_conf:white_space_clean(String)
end,
parse_passwd(Stream, PasswdList, Line).
@@ -228,8 +284,6 @@ parse_passwd(Stream, PasswdList, Line) ->
{error, ?NICE(Line)}
end.
-%% load_group
-
load_group(AuthGroupFile) ->
case file:open(AuthGroupFile, [read]) of
{ok, Stream} ->
@@ -237,91 +291,3 @@ load_group(AuthGroupFile) ->
{error, _} ->
{error, ?NICE("Can't open " ++ AuthGroupFile)}
end.
-
-parse_group(Stream, GroupList) ->
- Line =
- case io:get_line(Stream,'') of
- eof ->
- eof;
- String ->
- httpd_conf:clean(String)
- end,
- parse_group(Stream, GroupList, Line).
-
-parse_group(Stream, GroupList, eof) ->
- file:close(Stream),
- {ok, GroupList};
-parse_group(Stream, GroupList, "") ->
- parse_group(Stream, GroupList);
-parse_group(Stream, GroupList, [$#|_]) ->
- parse_group(Stream, GroupList);
-parse_group(Stream, GroupList, Line) ->
- case inets_regexp:split(Line, ":") of
- {ok, [Group,Users]} ->
- {ok, UserList} = inets_regexp:split(Users," "),
- parse_group(Stream, [{Group,UserList}|GroupList]);
- {ok, _} ->
- {error, ?NICE(Line)}
- end.
-
-
-%% store_passwd
-
-store_passwd(Addr,Port,PasswdList) ->
- Name = httpd_util:make_name("httpd_passwd",Addr,Port),
- PasswdDB = ets:new(Name, [set, public]),
- store_passwd(PasswdDB, PasswdList).
-
-store_passwd(PasswdDB, []) ->
- {ok, PasswdDB};
-store_passwd(PasswdDB, [User|Rest]) ->
- ets:insert(PasswdDB, User),
- store_passwd(PasswdDB, Rest).
-
-%% store_group
-
-store_group(Addr,Port,GroupList) ->
- Name = httpd_util:make_name("httpd_group",Addr,Port),
- GroupDB = ets:new(Name, [set, public]),
- store_group(GroupDB, GroupList).
-
-
-store_group(GroupDB,[]) ->
- {ok, GroupDB};
-store_group(GroupDB, [User|Rest]) ->
- ets:insert(GroupDB, User),
- store_group(GroupDB, Rest).
-
-
-%% remove/1
-%%
-%% Deletes ets tables used by this auth mod.
-%%
-remove(DirData) ->
- PWDB = proplists:get_value(auth_user_file, DirData),
- GDB = proplists:get_value(auth_group_file, DirData),
- ets:delete(PWDB),
- ets:delete(GDB).
-
-
-
-%% absolute_file_name/2
-%%
-%% Return the absolute path name of File_type.
-absolute_file_name(File_type, DirData, Server_root) ->
- Path = proplists:get_value(File_type, DirData),
- case filename:pathtype(Path) of
- relative ->
- case Server_root of
- undefined ->
- {error,
- ?NICE(Path++
- " is an invalid file name because "
- "ServerRoot is not defined")};
- _ ->
- filename:join(Server_root,Path)
- end;
- _ ->
- Path
- end.
-
diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl
index 947273bd9e..2a45f402d7 100644
--- a/lib/inets/src/http_server/mod_auth_server.erl
+++ b/lib/inets/src/http_server/mod_auth_server.erl
@@ -22,246 +22,184 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-behaviour(gen_server).
-
%% mod_auth exports
--export([start/2, stop/2,
+-export([start/3, stop/3,
add_password/4, update_password/5,
add_user/5, delete_user/5, get_user/5, list_users/4,
add_group_member/6, delete_group_member/6, list_group_members/5,
delete_group/5, list_groups/4]).
%% gen_server exports
--export([start_link/2, init/1,
+-export([start_link/3, init/1,
handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {tab}).
+%%====================================================================
+%% Internal application API
+%%====================================================================
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% External API %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% start_link/3
-%%
%% NOTE: This is called by httpd_misc_sup when the process is started
%%
-start_link(Addr, Port) ->
- ?hdrt("start_link", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+start_link(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
gen_server:start_link({local, Name}, ?MODULE, [], [{timeout, infinity}]).
-
-%% start/2
-
-start(Addr, Port) ->
- ?hdrd("start", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+start(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
undefined ->
- httpd_misc_sup:start_auth_server(Addr, Port);
+ httpd_misc_sup:start_auth_server(Addr, Port, Profile);
_ -> %% Already started...
ok
end.
-
-%% stop/2
-
-stop(Addr, Port) ->
- ?hdrd("stop", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+stop(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
undefined -> %% Already stopped
ok;
_ ->
- (catch httpd_misc_sup:stop_auth_server(Addr, Port))
+ (catch httpd_misc_sup:stop_auth_server(Addr, Port, Profile))
end.
-%% add_password/4
-
add_password(Addr, Port, Dir, Password) ->
- ?hdrt("add password", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+ add_password(Addr, Port, ?DEFAULT_PROFILE, Dir, Password).
+add_password(Addr, Port, Profile, Dir, Password) ->
+ Name = make_name(Addr, Port, Profile),
Req = {add_password, Dir, Password},
call(Name, Req).
-
-%% update_password/6
-
-update_password(Addr, Port, Dir, Old, New) when is_list(New) ->
- ?hdrt("update password",
- [{address, Addr}, {port, Port}, {dir, Dir}, {old, Old}, {new, New}]),
- Name = make_name(Addr, Port),
+update_password(Addr, Port, Dir, Old, New) ->
+ update_password(Addr, Port, ?DEFAULT_PROFILE, Dir, Old, New).
+update_password(Addr, Port, Profile, Dir, Old, New) when is_list(New) ->
+ Name = make_name(Addr, Port, Profile),
Req = {update_password, Dir, Old, New},
call(Name, Req).
-
-
-%% add_user/5
add_user(Addr, Port, Dir, User, Password) ->
- ?hdrt("add user",
- [{address, Addr}, {port, Port},
- {dir, Dir}, {user, User}, {passwd, Password}]),
- Name = make_name(Addr, Port),
- Req = {add_user, Addr, Port, Dir, User, Password},
+ add_user(Addr, Port, ?DEFAULT_PROFILE, Dir, User, Password).
+add_user(Addr, Port, Profile, Dir, User, Password) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {add_user, Addr, Port, Profile, Dir, User, Password},
call(Name, Req).
-
-%% delete_user/5
-
delete_user(Addr, Port, Dir, UserName, Password) ->
- ?hdrt("delete user",
- [{address, Addr}, {port, Port},
- {dir, Dir}, {user, UserName}, {passwd, Password}]),
- Name = make_name(Addr, Port),
- Req = {delete_user, Addr, Port, Dir, UserName, Password},
+ delete_user(Addr, Port, ?DEFAULT_PROFILE, Dir, UserName, Password).
+delete_user(Addr, Port, Profile, Dir, UserName, Password) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {delete_user, Addr, Port, Profile, Dir, UserName, Password},
call(Name, Req).
-
-%% get_user/5
-
get_user(Addr, Port, Dir, UserName, Password) ->
- ?hdrt("get user",
- [{address, Addr}, {port, Port},
- {dir, Dir}, {user, UserName}, {passwd, Password}]),
- Name = make_name(Addr, Port),
- Req = {get_user, Addr, Port, Dir, UserName, Password},
+ get_user(Addr, Port, ?DEFAULT_PROFILE, Dir, UserName, Password).
+get_user(Addr, Port, Profile,Dir, UserName, Password) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {get_user, Addr, Port, Profile, Dir, UserName, Password},
call(Name, Req).
-
-%% list_users/4
-
list_users(Addr, Port, Dir, Password) ->
- ?hdrt("list users",
- [{address, Addr}, {port, Port}, {dir, Dir}, {passwd, Password}]),
- Name = make_name(Addr,Port),
- Req = {list_users, Addr, Port, Dir, Password},
+ list_users(Addr, Port, ?DEFAULT_PROFILE, Dir, Password).
+list_users(Addr, Port, Profile, Dir, Password) ->
+ Name = make_name(Addr,Port, Profile),
+ Req = {list_users, Addr, Port, Profile, Dir, Password},
call(Name, Req).
-
-%% add_group_member/6
-
add_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
- ?hdrt("add group member",
- [{address, Addr}, {port, Port}, {dir, Dir},
- {group, GroupName}, {user, UserName}, {passwd, Password}]),
- Name = make_name(Addr,Port),
- Req = {add_group_member, Addr, Port, Dir, GroupName, UserName, Password},
+ add_group_member(Addr, Port, ?DEFAULT_PROFILE, Dir, GroupName, UserName, Password).
+add_group_member(Addr, Port, Profile, Dir, GroupName, UserName, Password) ->
+ Name = make_name(Addr,Port, Profile),
+ Req = {add_group_member, Addr, Port, Profile, Dir, GroupName, UserName, Password},
call(Name, Req).
-
-%% delete_group_member/6
-
delete_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
- ?hdrt("delete group member",
- [{address, Addr}, {port, Port}, {dir, Dir},
- {group, GroupName}, {user, UserName}, {passwd, Password}]),
- Name = make_name(Addr,Port),
- Req = {delete_group_member, Addr, Port, Dir, GroupName, UserName, Password},
+ delete_group_member(Addr, Port, ?DEFAULT_PROFILE, Dir, GroupName, UserName, Password).
+delete_group_member(Addr, Port, Profile, Dir, GroupName, UserName, Password) ->
+ Name = make_name(Addr,Port,Profile),
+ Req = {delete_group_member, Addr, Port, Profile, Dir, GroupName, UserName, Password},
call(Name, Req).
-
-%% list_group_members/4
-
list_group_members(Addr, Port, Dir, Group, Password) ->
- ?hdrt("list group members",
- [{address, Addr}, {port, Port}, {dir, Dir},
- {group, Group}, {passwd, Password}]),
- Name = make_name(Addr, Port),
+ 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},
call(Name, Req).
-
-%% delete_group/5
-
delete_group(Addr, Port, Dir, GroupName, Password) ->
- ?hdrt("delete group",
- [{address, Addr}, {port, Port}, {dir, Dir},
- {group, GroupName}, {passwd, Password}]),
- Name = make_name(Addr, Port),
- Req = {delete_group, Addr, Port, Dir, GroupName, Password},
+ delete_group(Addr, Port, ?DEFAULT_PROFILE, Dir, GroupName, Password).
+delete_group(Addr, Port, Profile, Dir, GroupName, Password) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {delete_group, Addr, Port, Profile, Dir, GroupName, Password},
call(Name, Req).
-
-%% list_groups/4
-
list_groups(Addr, Port, Dir, Password) ->
- ?hdrt("list groups",
- [{address, Addr}, {port, Port}, {dir, Dir}, {passwd, Password}]),
- Name = make_name(Addr, Port),
- Req = {list_groups, Addr, Port, Dir, Password},
+ list_groups(Addr, Port, ?DEFAULT_PROFILE, Dir, Password).
+list_groups(Addr, Port, Profile, Dir, Password) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {list_groups, Addr, Port,Profile, Dir, Password},
call(Name, Req).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Server call-back functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% init
-
+%%====================================================================
+%% Behavior call backs
+%%====================================================================
init(_) ->
- ?hdrv("initiating", []),
{ok,#state{tab = ets:new(auth_pwd,[set,protected])}}.
%% handle_call
%% Add a user
-handle_call({add_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, add_user, User, AuthPwd, State),
- ?hdrt("add user", [{reply, Reply}]),
+handle_call({add_user, Addr, Port, Profile, Dir, User, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, add_user, User, AuthPwd, State),
{reply, Reply, State};
%% Get data about a user
-handle_call({get_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, get_user, [User], AuthPwd, State),
+handle_call({get_user, Addr, Port, Profile, Dir, User, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, get_user, [User], AuthPwd, State),
{reply, Reply, State};
%% Add a group member
-handle_call({add_group_member, Addr, Port, Dir, Group, User, AuthPwd},
+handle_call({add_group_member, Addr, Port, Profile, Dir, Group, User, AuthPwd},
_From, State) ->
- Reply = api_call(Addr, Port, Dir, add_group_member, [Group, User],
+ Reply = api_call(Addr, Port, Profile, Dir, add_group_member, [Group, User],
AuthPwd, State),
{reply, Reply, State};
%% delete a group
-handle_call({delete_group_member, Addr, Port, Dir, Group, User, AuthPwd},
+handle_call({delete_group_member, Addr, Port, Profile, Dir, Group, User, AuthPwd},
_From, State) ->
- Reply = api_call(Addr, Port, Dir, delete_group_member, [Group, User],
+ Reply = api_call(Addr, Port, Profile, Dir, delete_group_member, [Group, User],
AuthPwd, State),
{reply, Reply, State};
%% List all users thats standalone users
-handle_call({list_users, Addr, Port, Dir, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, list_users, [], AuthPwd, State),
+handle_call({list_users, Addr, Port, Profile, Dir, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, list_users, [], AuthPwd, State),
{reply, Reply, State};
%% Delete a user
-handle_call({delete_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, delete_user, [User], AuthPwd, State),
+handle_call({delete_user, Addr, Port, Profile, Dir, User, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, delete_user, [User], AuthPwd, State),
{reply, Reply, State};
%% Delete a group
-handle_call({delete_group, Addr, Port, Dir, Group, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, delete_group, [Group], AuthPwd, State),
+handle_call({delete_group, Addr, Port, Profile, Dir, Group, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, delete_group, [Group], AuthPwd, State),
{reply, Reply, State};
%% List the current groups
-handle_call({list_groups, Addr, Port, Dir, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, list_groups, [], AuthPwd, State),
+handle_call({list_groups, Addr, Port, Profile, Dir, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Profile, Dir, list_groups, [], AuthPwd, State),
{reply, Reply, State};
%% List the members of the given group
-handle_call({list_group_members, Addr, Port, Dir, Group, AuthPwd},
+handle_call({list_group_members, Addr, Port, Profile, Dir, Group, AuthPwd},
_From, State) ->
- Reply = api_call(Addr, Port, Dir, list_group_members, [Group],
+ Reply = api_call(Addr, Port, Profile, Dir, list_group_members, [Group],
AuthPwd, State),
{reply, Reply, State};
@@ -306,26 +244,16 @@ terminate(_Reason,State) ->
ets:delete(State#state.tab),
ok.
-
-%% code_change(Vsn, State, Extra)
-%%
code_change(_Vsn, State, _Extra) ->
{ok, State}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that really changes the data in the database %%
-%% of users to different directories %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% API gateway
-
-api_call(Addr, Port, Dir, Func, Args,Password,State) ->
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+api_call(Addr, Port, Profile, Dir, Func, Args,Password,State) ->
case controlPassword(Password, State, Dir) of
ok->
- ConfigName = httpd_util:make_name("httpd_conf", Addr, Port),
+ ConfigName = httpd_util:make_name("httpd_conf", Addr, Port, Profile),
case ets:match_object(ConfigName, {directory, {Dir, '$1'}}) of
[{directory, {Dir, DirData}}] ->
AuthMod = auth_mod_name(DirData),
@@ -386,8 +314,8 @@ lookup(Db, Key) ->
ets:lookup(Db, Key).
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_auth",Addr,Port).
+make_name(Addr, Port, Profile) ->
+ httpd_util:make_name(?MODULE, Addr, Port, Profile).
call(Name, Req) ->
@@ -397,5 +325,3 @@ call(Name, Req) ->
Reply ->
Reply
end.
-
-
diff --git a/lib/inets/src/http_server/mod_cgi.erl b/lib/inets/src/http_server/mod_cgi.erl
index d933b0a4ba..fbcfa78e5f 100644
--- a/lib/inets/src/http_server/mod_cgi.erl
+++ b/lib/inets/src/http_server/mod_cgi.erl
@@ -95,24 +95,24 @@ do(ModData) ->
%% or cache
%%
load("ScriptNoCache " ++ CacheArg, [])->
- case catch list_to_atom(httpd_conf:clean(CacheArg)) of
+ case catch list_to_atom(string:strip(CacheArg)) of
true ->
{ok, [], {script_nocache, true}};
false ->
{ok, [], {script_nocache, false}};
_ ->
- {error, ?NICE(httpd_conf:clean(CacheArg)++
+ {error, ?NICE(string:strip(CacheArg)++
" is an invalid ScriptNoCache directive")}
end;
%% ScriptTimeout Seconds, The number of seconds that the server
%% maximum will wait for the script to
%% generate a part of the document
load("ScriptTimeout " ++ Timeout, [])->
- case catch list_to_integer(httpd_conf:clean(Timeout)) of
+ case catch list_to_integer(string:strip(Timeout)) of
TimeoutSec when is_integer(TimeoutSec) ->
{ok, [], {script_timeout,TimeoutSec*1000}};
_ ->
- {error, ?NICE(httpd_conf:clean(Timeout)++
+ {error, ?NICE(string:strip(Timeout)++
" is an invalid ScriptTimeout")}
end.
diff --git a/lib/inets/src/http_server/mod_disk_log.erl b/lib/inets/src/http_server/mod_disk_log.erl
index 5a3766de66..89a3193aa3 100644
--- a/lib/inets/src/http_server/mod_disk_log.erl
+++ b/lib/inets/src/http_server/mod_disk_log.erl
@@ -139,70 +139,70 @@ do(Info) ->
load("TransferDiskLogSize " ++ TransferDiskLogSize, []) ->
case inets_regexp:split(TransferDiskLogSize," ") of
{ok,[MaxBytes,MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
+ case make_integer(MaxBytes) of
{ok,MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
+ case make_integer(MaxFiles) of
{ok,MaxFilesInteger} ->
{ok,[],{transfer_disk_log_size,
{MaxBytesInteger,MaxFilesInteger}}};
{error,_} ->
{error,
- ?NICE(httpd_conf:clean(TransferDiskLogSize)++
+ ?NICE(string:strip(TransferDiskLogSize)++
" is an invalid TransferDiskLogSize")}
end;
{error,_} ->
- {error,?NICE(httpd_conf:clean(TransferDiskLogSize)++
+ {error,?NICE(string:strip(TransferDiskLogSize)++
" is an invalid TransferDiskLogSize")}
end
end;
load("TransferDiskLog " ++ TransferDiskLog,[]) ->
- {ok,[],{transfer_disk_log,httpd_conf:clean(TransferDiskLog)}};
+ {ok,[],{transfer_disk_log,string:strip(TransferDiskLog)}};
load("ErrorDiskLogSize " ++ ErrorDiskLogSize, []) ->
case inets_regexp:split(ErrorDiskLogSize," ") of
{ok,[MaxBytes,MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
+ case make_integer(MaxBytes) of
{ok,MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
+ case make_integer(MaxFiles) of
{ok,MaxFilesInteger} ->
{ok,[],{error_disk_log_size,
{MaxBytesInteger,MaxFilesInteger}}};
{error,_} ->
- {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
+ {error,?NICE(string:strip(ErrorDiskLogSize)++
" is an invalid ErrorDiskLogSize")}
end;
{error,_} ->
- {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
+ {error,?NICE(string:strip(ErrorDiskLogSize)++
" is an invalid ErrorDiskLogSize")}
end
end;
load("ErrorDiskLog " ++ ErrorDiskLog, []) ->
- {ok, [], {error_disk_log, httpd_conf:clean(ErrorDiskLog)}};
+ {ok, [], {error_disk_log, string:strip(ErrorDiskLog)}};
load("SecurityDiskLogSize " ++ SecurityDiskLogSize, []) ->
case inets_regexp:split(SecurityDiskLogSize, " ") of
{ok, [MaxBytes, MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
+ case make_integer(MaxBytes) of
{ok, MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
+ case make_integer(MaxFiles) of
{ok, MaxFilesInteger} ->
{ok, [], {security_disk_log_size,
{MaxBytesInteger, MaxFilesInteger}}};
{error,_} ->
{error,
- ?NICE(httpd_conf:clean(SecurityDiskLogSize) ++
+ ?NICE(string:strip(SecurityDiskLogSize) ++
" is an invalid SecurityDiskLogSize")}
end;
{error, _} ->
- {error, ?NICE(httpd_conf:clean(SecurityDiskLogSize) ++
+ {error, ?NICE(string:strip(SecurityDiskLogSize) ++
" is an invalid SecurityDiskLogSize")}
end
end;
load("SecurityDiskLog " ++ SecurityDiskLog, []) ->
- {ok, [], {security_disk_log, httpd_conf:clean(SecurityDiskLog)}};
+ {ok, [], {security_disk_log, string:strip(SecurityDiskLog)}};
load("DiskLogFormat " ++ Format, []) ->
- case httpd_conf:clean(Format) of
+ case string:strip(Format) of
"internal" ->
{ok, [], {disk_log_format,internal}};
"external" ->
@@ -314,7 +314,7 @@ log_size(ConfigList, Tag) ->
proplists:get_value(Tag, ConfigList, {500*1024,8}).
create_disk_log(LogFile, SizeTag, ConfigList) ->
- Filename = httpd_conf:clean(LogFile),
+ Filename = string:strip(LogFile),
{MaxBytes, MaxFiles} = log_size(ConfigList, SizeTag),
case filename:pathtype(Filename) of
absolute ->
@@ -413,3 +413,11 @@ log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
log_internal_info(Info,Date,[_|Rest]) ->
log_internal_info(Info,Date,Rest).
+make_integer(List) ->
+ try list_to_integer(List) of
+ N ->
+ {ok, N}
+ catch
+ _:_ ->
+ {error, {badarg, list_to_integer, List}}
+ end.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index b11df34f9e..d385afbd70 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -98,40 +98,40 @@ load("ErlScriptAlias " ++ ErlScriptAlias, []) ->
case inets_regexp:split(ErlScriptAlias," ") of
{ok, [ErlName | StrModules]} ->
Modules = lists:map(fun(Str) ->
- list_to_atom(httpd_conf:clean(Str))
+ list_to_atom(string:strip(Str))
end, StrModules),
{ok, [], {erl_script_alias, {ErlName, Modules}}};
{ok, _} ->
- {error, ?NICE(httpd_conf:clean(ErlScriptAlias) ++
+ {error, ?NICE(string:strip(ErlScriptAlias) ++
" is an invalid ErlScriptAlias")}
end;
load("EvalScriptAlias " ++ EvalScriptAlias, []) ->
case inets_regexp:split(EvalScriptAlias, " ") of
{ok, [EvalName | StrModules]} ->
Modules = lists:map(fun(Str) ->
- list_to_atom(httpd_conf:clean(Str))
+ list_to_atom(string:strip(Str))
end, StrModules),
{ok, [], {eval_script_alias, {EvalName, Modules}}};
{ok, _} ->
- {error, ?NICE(httpd_conf:clean(EvalScriptAlias) ++
+ {error, ?NICE(string:strip(EvalScriptAlias) ++
" is an invalid EvalScriptAlias")}
end;
load("ErlScriptTimeout " ++ Timeout, [])->
- case catch list_to_integer(httpd_conf:clean(Timeout)) of
+ case catch list_to_integer(string:strip(Timeout)) of
TimeoutSec when is_integer(TimeoutSec) ->
{ok, [], {erl_script_timeout, TimeoutSec * 1000}};
_ ->
- {error, ?NICE(httpd_conf:clean(Timeout) ++
+ {error, ?NICE(string:strip(Timeout) ++
" is an invalid ErlScriptTimeout")}
end;
load("ErlScriptNoCache " ++ CacheArg, [])->
- case catch list_to_atom(httpd_conf:clean(CacheArg)) of
+ case catch list_to_atom(string:strip(CacheArg)) of
true ->
{ok, [], {erl_script_nocache, true}};
false ->
{ok, [], {erl_script_nocache, false}};
_ ->
- {error, ?NICE(httpd_conf:clean(CacheArg)++
+ {error, ?NICE(string:strip(CacheArg)++
" is an invalid ErlScriptNoCache directive")}
end.
diff --git a/lib/inets/src/http_server/mod_htaccess.erl b/lib/inets/src/http_server/mod_htaccess.erl
index e1f66d01c8..d526fbe156 100644
--- a/lib/inets/src/http_server/mod_htaccess.erl
+++ b/lib/inets/src/http_server/mod_htaccess.erl
@@ -34,7 +34,7 @@
% Names on accessfiles
%----------------------------------------------------------------------
load("AccessFileName" ++ FileNames, _Context)->
- CleanFileNames=httpd_conf:clean(FileNames),
+ CleanFileNames=string:strip(FileNames),
{ok,[],{access_files,string:tokens(CleanFileNames," ")}}.
store({access_files, Files} = Conf, _) when is_list(Files)->
diff --git a/lib/inets/src/http_server/mod_include.erl b/lib/inets/src/http_server/mod_include.erl
deleted file mode 100644
index 35f45bdd33..0000000000
--- a/lib/inets/src/http_server/mod_include.erl
+++ /dev/null
@@ -1,598 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(mod_include).
--export([do/1,parse/2,config/6,include/6,echo/6,fsize/6,flastmod/6,exec/6]).
-
--include("httpd.hrl").
--include("httpd_internal.hrl").
-
--define(VMODULE,"INCLUDE").
-
-%% do
-
-do(Info) ->
- case Info#mod.method of
- "GET" ->
- case proplists:get_value(status, Info#mod.data) of
- %% A status code has been generated!
- {_StatusCode, _PhraseArgs, _Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case proplists:get_value(response, Info#mod.data) of
- %% No response has been generated!
- undefined ->
- do_include(Info);
- %% A response has been generated or sent!
- _Response ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a GET method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-do_include(Info) ->
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- Suffix = httpd_util:suffix(Path),
- case httpd_util:lookup_mime_default(Info#mod.config_db,Suffix) of
- "text/x-server-parsed-html" ->
- HeaderStart = [{content_type, "text/html"}],
- case send_in(Info, Path, HeaderStart, file:read_file_info(Path)) of
- {ok, ErrorLog, Size} ->
- {proceed, [{response, {already_sent, 200, Size}},
- {mime_type, "text/html"} |
- lists:append(ErrorLog, Info#mod.data)]};
- {error, Reason} ->
- {proceed,
- [{status,send_error(Reason,Info,Path)}|Info#mod.data]}
- end;
- _ -> %% Unknown mime type, ignore
- {proceed,Info#mod.data}
- end.
-
-
-%%
-%% config directive
-%%
-
-config(_Info, Context, ErrorLog, TagList, ValueList, R) ->
- case verify_tags("config",[errmsg,timefmt,sizefmt],
- TagList,ValueList) of
- ok ->
- {ok,update_context(TagList,ValueList,Context),ErrorLog,"",R};
- {error,Reason} ->
- {ok,Context,[{internal_info,Reason}|ErrorLog],
- proplists:get_value(errmsg,Context,""),R}
- end.
-
-update_context([],[],Context) ->
- Context;
-update_context([Tag|R1],[Value|R2],Context) ->
- update_context(R1,R2,[{Tag,Value}|Context]).
-
-verify_tags(Command,ValidTags,TagList,ValueList)
- when length(TagList) =:= length(ValueList) ->
- verify_tags(Command, ValidTags, TagList);
-verify_tags(Command, _ValidTags, _TagList, _ValueList) ->
- {error, ?NICE(Command ++ " directive has spurious tags")}.
-
-verify_tags(_Command, _ValidTags, []) ->
- ok;
-verify_tags(Command, ValidTags, [Tag|Rest]) ->
- case lists:member(Tag, ValidTags) of
- true ->
- verify_tags(Command, ValidTags, Rest);
- false ->
- {error, ?NICE(Command++" directive has a spurious tag ("++
- atom_to_list(Tag)++")")}
- end.
-
-%%
-%% include directive
-%%
-
-include(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
- Aliases = httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_, Path, _AfterPath} =
- mod_alias:real_name(Info#mod.config_db, VirtualPath, Aliases),
- include(Info,Context,ErrorLog,R,Path);
-include(Info, Context, ErrorLog, [file], [FileName], R) ->
- Path = file(Info#mod.config_db, Info#mod.request_uri, FileName),
- include(Info, Context, ErrorLog, R, Path);
-include(_Info, Context, ErrorLog, _TagList, _ValueList, R) ->
- {ok, Context,
- [{internal_info,?NICE("include directive has a spurious tag")}|
- ErrorLog], proplists:get_value(errmsg, Context, ""), R}.
-
-include(Info, Context, ErrorLog, R, Path) ->
- case file:read_file(Path) of
- {ok, Body} ->
- {ok, NewContext, NewErrorLog, Result} =
- parse(Info, binary_to_list(Body), Context, ErrorLog, []),
- {ok, NewContext, NewErrorLog, Result, R};
- {error, _Reason} ->
- {ok, Context,
- [{internal_info, ?NICE("Can't open "++Path)}|ErrorLog],
- proplists:get_value(errmsg, Context, ""), R}
- end.
-
-file(ConfigDB, RequestURI, FileName) ->
- Aliases = httpd_util:multi_lookup(ConfigDB, alias),
- {_, Path, _AfterPath}
- = mod_alias:real_name(ConfigDB, RequestURI, Aliases),
- Pwd = filename:dirname(Path),
- filename:join(Pwd, FileName).
-
-%%
-%% echo directive
-%%
-
-echo(Info,Context,ErrorLog,[var],["DOCUMENT_NAME"],R) ->
- {ok,Context,ErrorLog,document_name(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,[var],["DOCUMENT_URI"],R) ->
- {ok,Context,ErrorLog,document_uri(Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,[var],["QUERY_STRING_UNESCAPED"],R) ->
- {ok,Context,ErrorLog,query_string_unescaped(Info#mod.request_uri),R};
-echo(_Info,Context,ErrorLog,[var],["DATE_LOCAL"],R) ->
- {ok,Context,ErrorLog,date_local(),R};
-echo(_Info,Context,ErrorLog,[var],["DATE_GMT"],R) ->
- {ok,Context,ErrorLog,date_gmt(),R};
-echo(Info,Context,ErrorLog,[var],["LAST_MODIFIED"],R) ->
- {ok,Context,ErrorLog,last_modified(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(_Info, Context, ErrorLog, _TagList, _ValueList, R) ->
- {ok,Context,
- [{internal_info,?NICE("echo directive has a spurious tag")}|
- ErrorLog],"(none)",R}.
-
-document_name(Data,ConfigDB,RequestURI) ->
- Path = mod_alias:path(Data,ConfigDB,RequestURI),
- case inets_regexp:match(Path,"[^/]*\$") of
- {match,Start,Length} ->
- string:substr(Path,Start,Length);
- nomatch ->
- "(none)"
- end.
-
-document_uri(ConfigDB, RequestURI) ->
- Aliases = httpd_util:multi_lookup(ConfigDB, alias),
-
- {_, Path, AfterPath} = mod_alias:real_name(ConfigDB, RequestURI, Aliases),
-
- VirtualPath = string:substr(RequestURI, 1,
- length(RequestURI)-length(AfterPath)),
- {match, Start, Length} = inets_regexp:match(Path,"[^/]*\$"),
- FileName = string:substr(Path,Start,Length),
- case inets_regexp:match(VirtualPath, FileName++"\$") of
- {match, _, _} ->
- http_uri:decode(VirtualPath)++AfterPath;
- nomatch ->
- string:strip(http_uri:decode(VirtualPath),right,$/)++
- "/"++FileName++AfterPath
- end.
-
-query_string_unescaped(RequestURI) ->
- case inets_regexp:match(RequestURI,"[\?].*\$") of
- {match,Start,Length} ->
- %% Escape all shell-special variables with \
- escape(string:substr(RequestURI,Start+1,Length-1));
- nomatch ->
- "(none)"
- end.
-
-escape([]) -> [];
-escape([$;|R]) -> [$\\,$;|escape(R)];
-escape([$&|R]) -> [$\\,$&|escape(R)];
-escape([$(|R]) -> [$\\,$(|escape(R)];
-escape([$)|R]) -> [$\\,$)|escape(R)];
-escape([$||R]) -> [$\\,$||escape(R)];
-escape([$^|R]) -> [$\\,$^|escape(R)];
-escape([$<|R]) -> [$\\,$<|escape(R)];
-escape([$>|R]) -> [$\\,$>|escape(R)];
-escape([$\n|R]) -> [$\\,$\n|escape(R)];
-escape([$ |R]) -> [$\\,$ |escape(R)];
-escape([$\t|R]) -> [$\\,$\t|escape(R)];
-escape([C|R]) -> [C|escape(R)].
-
-date_local() ->
- {{Year,Month,Day},{Hour,Minute,Second}}=calendar:local_time(),
- %% Time format hard-wired to: "%a %b %e %T %Y" according to strftime(3)
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-date_gmt() ->
- {{Year,Month,Day},{Hour,Minute,Second}}=calendar:universal_time(),
- %% Time format hard-wired to: "%a %b %e %T %Z %Y" according to strftime(3)
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w GMT ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-last_modified(Data,ConfigDB,RequestURI) ->
- {ok,FileInfo}=file:read_file_info(mod_alias:path(Data,ConfigDB,RequestURI)),
- {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-%%
-%% fsize directive
-%%
-
-fsize(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
- Aliases = httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_,Path, _AfterPath}=
- mod_alias:real_name(Info#mod.config_db,VirtualPath,Aliases),
- fsize(Info, Context, ErrorLog, R, Path);
-fsize(Info,Context,ErrorLog,[file],[FileName],R) ->
- Path = file(Info#mod.config_db,Info#mod.request_uri,FileName),
- fsize(Info,Context,ErrorLog,R,Path);
-fsize(_Info, Context, ErrorLog, _TagList, _ValueList, R) ->
- {ok,Context,[{internal_info,?NICE("fsize directive has a spurious tag")}|
- ErrorLog],proplists:get_value(errmsg,Context,""),R}.
-
-fsize(_Info, Context, ErrorLog, R, Path) ->
- case file:read_file_info(Path) of
- {ok,FileInfo} ->
- case proplists:get_value(sizefmt,Context) of
- "bytes" ->
- {ok,Context,ErrorLog,
- integer_to_list(FileInfo#file_info.size),R};
- "abbrev" ->
- Size = integer_to_list(trunc(FileInfo#file_info.size/1024+1))++"k",
- {ok,Context,ErrorLog,Size,R};
- Value->
- {ok,Context,
- [{internal_info,
- ?NICE("fsize directive has a spurious tag value ("++
- Value++")")}|
- ErrorLog],
- proplists:get_value(errmsg, Context, ""), R}
- end;
- {error, _Reason} ->
- {ok,Context,[{internal_info,?NICE("Can't open "++Path)}|ErrorLog],
- proplists:get_value(errmsg,Context,""),R}
- end.
-
-%%
-%% flastmod directive
-%%
-
-flastmod(#mod{config_db = Db} = Info,
- Context, ErrorLog, [virtual], [VirtualPath],R) ->
- Aliases = httpd_util:multi_lookup(Db,alias),
- {_,Path, _AfterPath} = mod_alias:real_name(Db, VirtualPath, Aliases),
- flastmod(Info,Context,ErrorLog,R,Path);
-flastmod(#mod{config_db = Db, request_uri = RequestUri} = Info,
- Context, ErrorLog, [file], [FileName], R) ->
- Path = file(Db, RequestUri, FileName),
- flastmod(Info, Context, ErrorLog, R, Path);
-flastmod(_Info, Context, ErrorLog, _TagList, _ValueList, R) ->
- {ok,Context,
- [{internal_info,?NICE("flastmod directive has a spurious tag")}|
- ErrorLog],proplists:get_value(errmsg,Context,""),R}.
-
-flastmod(_Info, Context, ErrorLog, R, File) ->
- case file:read_file_info(File) of
- {ok, FileInfo} ->
- {{Yr,Mon,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- Result =
- io_lib:format("~s ~s ~2w ~w:~w:~w ~w",
- [httpd_util:day(
- calendar:day_of_the_week(Yr,Mon, Day)),
- httpd_util:month(Mon),Day,Hour,Minute,Second, Yr]),
- {ok, Context, ErrorLog, Result, R};
- {error, _Reason} ->
- {ok,Context,[{internal_info,?NICE("Can't open "++File)}|ErrorLog],
- proplists:get_value(errmsg,Context,""),R}
- end.
-
-%%
-%% exec directive
-%%
-
-exec(Info,Context,ErrorLog,[cmd],[Command],R) ->
- cmd(Info,Context,ErrorLog,R,Command);
-exec(Info,Context,ErrorLog,[cgi],[RequestURI],R) ->
- cgi(Info,Context,ErrorLog,R,RequestURI);
-exec(_Info, Context, ErrorLog, _TagList, _ValueList, R) ->
- {ok, Context,
- [{internal_info,?NICE("exec directive has a spurious tag")}|
- ErrorLog], proplists:get_value(errmsg,Context,""),R}.
-
-%% cmd
-
-cmd(Info, Context, ErrorLog, R, Command) ->
- process_flag(trap_exit,true),
- Env = env(Info),
- Dir = filename:dirname(Command),
- Port = (catch open_port({spawn,Command},[stream,{cd,Dir},{env,Env}])),
- case Port of
- P when is_port(P) ->
- {NewErrorLog, Result} = proxy(Port, ErrorLog),
- {ok, Context, NewErrorLog, Result, R};
- {'EXIT', Reason} ->
- exit({open_port_failed,Reason,
- [{uri,Info#mod.request_uri},{script,Command},
- {env,Env},{dir,Dir}]});
- O ->
- exit({open_port_failed,O,
- [{uri,Info#mod.request_uri},{script,Command},
- {env,Env},{dir,Dir}]})
- end.
-
-env(Info) ->
- [{"DOCUMENT_NAME",document_name(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri)},
- {"DOCUMENT_URI", document_uri(Info#mod.config_db, Info#mod.request_uri)},
- {"QUERY_STRING_UNESCAPED", query_string_unescaped(Info#mod.request_uri)},
- {"DATE_LOCAL", date_local()},
- {"DATE_GMT", date_gmt()},
- {"LAST_MODIFIED", last_modified(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri)}
- ].
-
-%% cgi
-
-cgi(Info, Context, ErrorLog, R, RequestURI) ->
- ScriptAliases = httpd_util:multi_lookup(Info#mod.config_db, script_alias),
- case mod_alias:real_script_name(Info#mod.config_db, RequestURI,
- ScriptAliases) of
- {Script, AfterScript} ->
- exec_script(Info,Script,AfterScript,ErrorLog,Context,R);
- not_a_script ->
- {ok, Context,
- [{internal_info, ?NICE(RequestURI++" is not a script")}|
- ErrorLog], proplists:get_value(errmsg, Context, ""),R}
- end.
-
-remove_header([]) ->
- [];
-remove_header([$\n,$\n|Rest]) ->
- Rest;
-remove_header([_C|Rest]) ->
- remove_header(Rest).
-
-
-exec_script(#mod{config_db = Db, request_uri = RequestUri} = Info,
- Script, _AfterScript, ErrorLog, Context, R) ->
- process_flag(trap_exit,true),
- Aliases = httpd_util:multi_lookup(Db, alias),
- {_, Path, AfterPath} = mod_alias:real_name(Db, RequestUri, Aliases),
- Env = env(Info) ++ mod_cgi:env(Info, Path, AfterPath),
- Dir = filename:dirname(Path),
- Port = (catch open_port({spawn,Script},[stream,{env, Env},{cd, Dir}])),
- case Port of
- P when is_port(P) ->
- %% Send entity body to port.
- Res = case Info#mod.entity_body of
- [] ->
- true;
- EntityBody ->
- (catch port_command(Port, EntityBody))
- end,
- case Res of
- {'EXIT', Reason} ->
- exit({open_cmd_failed,Reason,
- [{mod,?MODULE},{port,Port},
- {uri,RequestUri},
- {script,Script},{env,Env},{dir,Dir},
- {ebody_size,sz(Info#mod.entity_body)}]});
- true ->
- {NewErrorLog, Result} = proxy(Port, ErrorLog),
- {ok, Context, NewErrorLog, remove_header(Result), R}
- end;
- {'EXIT', Reason} ->
- exit({open_port_failed,Reason,
- [{mod,?MODULE},{uri,RequestUri},{script,Script},
- {env,Env},{dir,Dir}]});
- O ->
- exit({open_port_failed,O,
- [{mod,?MODULE},{uri,RequestUri},{script,Script},
- {env,Env},{dir,Dir}]})
- end.
-
-
-%%
-%% Port communication
-%%
-
-proxy(Port, ErrorLog) ->
- process_flag(trap_exit, true),
- proxy(Port, ErrorLog, []).
-
-proxy(Port, ErrorLog, Result) ->
- receive
- {Port, {data, Response}} ->
- proxy(Port, ErrorLog, lists:append(Result,Response));
- {'EXIT', Port, normal} when is_port(Port) ->
- process_flag(trap_exit, false),
- {ErrorLog, Result};
- {'EXIT', Port, _Reason} when is_port(Port) ->
- process_flag(trap_exit, false),
- {[{internal_info,
- ?NICE("Scrambled output from CGI-script")}|ErrorLog],
- Result};
- {'EXIT', Pid, Reason} when is_pid(Pid) ->
- process_flag(trap_exit, false),
- {'EXIT', Pid, Reason};
- %% This should not happen!
- _WhatEver ->
- process_flag(trap_exit, false),
- {ErrorLog, Result}
- end.
-
-
-%% ------
-%% Temporary until I figure out a way to fix send_in_chunks
-%% (comments and directives that start in one chunk but end
-%% in another is not handled).
-%%
-
-send_in(Info, Path, Head, {ok,FileInfo}) ->
- case file:read_file(Path) of
- {ok, Bin} ->
- send_in1(Info, binary_to_list(Bin), Head, FileInfo);
- {error, Reason} ->
- {error, {read,Reason}}
- end;
-send_in(_Info , _Path, _Head,{error,Reason}) ->
- {error, {open,Reason}}.
-
-send_in1(Info, Data, Head, FileInfo) ->
- {ok, _Context, Err, ParsedBody} = parse(Info,Data,?DEFAULT_CONTEXT,[],[]),
- Size = length(ParsedBody),
- LastModified = case catch httpd_util:rfc1123_date(FileInfo#file_info.mtime) of
- Date when is_list(Date) -> [{last_modified,Date}];
- _ -> []
- end,
- Head1 = case Info#mod.http_version of
- "HTTP/1.1"->
- Head ++ [{content_length, integer_to_list(Size)},
- {etag, httpd_util:create_etag(FileInfo,Size)}|
- LastModified];
- _->
- %% i.e http/1.0 and http/0.9
- Head ++ [{content_length, integer_to_list(Size)}|
- LastModified]
- end,
- httpd_response:send_header(Info, 200, Head1),
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket, ParsedBody),
- {ok, Err, Size}.
-
-
-parse(Info,Body) ->
- parse(Info, Body, ?DEFAULT_CONTEXT, [], []).
-
-parse(_Info, [], Context, ErrorLog, Result) ->
- {ok, Context, lists:reverse(ErrorLog), lists:reverse(Result)};
-parse(Info,[$<,$!,$-,$-,$#|R1],Context,ErrorLog,Result) ->
- case catch parse0(R1,Context) of
- {parse_error,Reason} ->
- parse(Info,R1,Context,[{internal_info,?NICE(Reason)}|ErrorLog],
- [$#,$-,$-,$!,$<|Result]);
- {ok,Context,Command,TagList,ValueList,R2} ->
- {ok,NewContext,NewErrorLog,MoreResult,R3}=
- handle(Info,Context,ErrorLog,Command,TagList,ValueList,R2),
- parse(Info,R3,NewContext,NewErrorLog,
- lists:reverse(MoreResult)++Result)
- end;
-parse(Info,[$<,$!,$-,$-|R1],Context,ErrorLog,Result) ->
- case catch parse5(R1,[],0) of
- {parse_error,Reason} ->
- parse(Info,R1,Context,
- [{internal_info,?NICE(Reason)}|ErrorLog],Result);
- {Comment,R2} ->
- parse(Info,R2,Context,ErrorLog,Comment++Result)
- end;
-parse(Info,[C|R],Context,ErrorLog,Result) ->
- parse(Info,R,Context,ErrorLog,[C|Result]).
-
-handle(Info,Context,ErrorLog,Command,TagList,ValueList,R) ->
- case catch apply(?MODULE,Command,[Info,Context,ErrorLog,TagList,ValueList,
- R]) of
- {'EXIT',{undef,_}} ->
- throw({parse_error,"Unknown command "++atom_to_list(Command)++
- " in parsed doc"});
- Result ->
- Result
- end.
-
-parse0([], _Context) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse0([$-,$-,$>|_R], _Context) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse0([$ |R], Context) ->
- parse0(R,Context);
-parse0(String, Context) ->
- parse1(String, Context,"").
-
-parse1([], _Context, _Command) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse1([$-,$-,$>|_R], _Context, _Command) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse1([$ |R], Context, Command) ->
- parse2(R,Context,list_to_atom(lists:reverse(Command)),[],[],"");
-parse1([C|R], Context, Command) ->
- parse1(R,Context,[C|Command]).
-
-parse2([], _Context, _Command, _TagList, _ValueList, _Tag) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse2([$-,$-,$>|R], Context, Command, TagList, ValueList, _Tag) ->
- {ok,Context,Command,TagList,ValueList,R};
-parse2([$ |R],Context,Command,TagList,ValueList,Tag) ->
- parse2(R,Context,Command,TagList,ValueList,Tag);
-parse2([$=|R],Context,Command,TagList,ValueList,Tag) ->
- parse3(R,Context,Command,[list_to_atom(lists:reverse(Tag))|TagList],
- ValueList);
-parse2([C|R],Context,Command,TagList,ValueList,Tag) ->
- parse2(R,Context,Command,TagList,ValueList,[C|Tag]).
-
-parse3([], _Context, _Command, _TagList, _ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse3([$-,$-,$>|_R], _Context, _Command, _TagList, _ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse3([$ |R], Context, Command, TagList, ValueList) ->
- parse3(R, Context, Command, TagList, ValueList);
-parse3([$"|R], Context, Command, TagList, ValueList) ->
- parse4(R,Context,Command,TagList,ValueList,"");
-parse3(_String, _Context, _Command, _TagList, _ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"}).
-
-parse4([], _Context, _Command, _TagList, _ValueList, _Value) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse4([$-,$-,$>|_R], _Context, _Command, _TagList, _ValueList, _Value) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse4([$"|R],Context,Command,TagList,ValueList,Value) ->
- parse2(R,Context,Command,TagList,[lists:reverse(Value)|ValueList],"");
-parse4([C|R],Context,Command,TagList,ValueList,Value) ->
- parse4(R,Context,Command,TagList,ValueList,[C|Value]).
-
-parse5([], _Comment, _Depth) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse5([$<,$!,$-,$-|R],Comment,Depth) ->
- parse5(R,[$-,$-,$!,$<|Comment],Depth+1);
-parse5([$-,$-,$>|R],Comment,0) ->
- {">--"++Comment++"--!<",R};
-parse5([$-,$-,$>|R],Comment,Depth) ->
- parse5(R,[$>,$-,$-|Comment],Depth-1);
-parse5([C|R],Comment,Depth) ->
- parse5(R,[C|Comment],Depth).
-
-
-sz(B) when is_binary(B) -> {binary,size(B)};
-sz(L) when is_list(L) -> {list,length(L)};
-sz(_) -> undefined.
-
-%% send_error - Handle failure to send the file
-%%
-send_error({open,Reason},Info,Path) ->
- httpd_file:handle_error(Reason, "open", Info, Path);
-send_error({read,Reason},Info,Path) ->
- httpd_file:handle_error(Reason, "read", Info, Path).
-
-
-
-
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
index a912f5616c..2367d9cfeb 100644
--- a/lib/inets/src/http_server/mod_log.erl
+++ b/lib/inets/src/http_server/mod_log.erl
@@ -127,11 +127,11 @@ do(Info) ->
%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
%%-------------------------------------------------------------------------
load("TransferLog " ++ TransferLog, []) ->
- {ok,[],{transfer_log,httpd_conf:clean(TransferLog)}};
+ {ok,[],{transfer_log,string:strip(TransferLog)}};
load("ErrorLog " ++ ErrorLog, []) ->
- {ok,[],{error_log,httpd_conf:clean(ErrorLog)}};
+ {ok,[],{error_log,string:strip(ErrorLog)}};
load("SecurityLog " ++ SecurityLog, []) ->
- {ok, [], {security_log, httpd_conf:clean(SecurityLog)}}.
+ {ok, [], {security_log, string:strip(SecurityLog)}}.
%%--------------------------------------------------------------------------
%% store(Directive, DirectiveList) -> {ok, NewDirective} |
@@ -200,7 +200,7 @@ transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes) ->
end.
create_log(LogFile, ConfigList) ->
- Filename = httpd_conf:clean(LogFile),
+ Filename = string:strip(LogFile),
case filename:pathtype(Filename) of
absolute ->
case file:open(Filename, [read, write]) of
diff --git a/lib/inets/src/http_server/mod_security.erl b/lib/inets/src/http_server/mod_security.erl
index 41988732ad..b09bd5e008 100644
--- a/lib/inets/src/http_server/mod_security.erl
+++ b/lib/inets/src/http_server/mod_security.erl
@@ -32,14 +32,13 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-define(VMODULE,"SEC").
-
-%% do/1
+%%====================================================================
+%% Internal application API
+%%====================================================================
do(Info) ->
- ?hdrt("do", [{info, Info}]),
%% Check and see if any user has been authorized.
case proplists:get_value(remote_user, Info#mod.data,not_defined_user) of
not_defined_user ->
@@ -84,151 +83,66 @@ do(Info) ->
{_Dir, SDirData} = secretp(Path, Info#mod.config_db),
Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
Port = httpd_util:lookup(Info#mod.config_db, port),
+ Profile = httpd_util:lookup(Info#mod.config_db, profile, ?DEFAULT_PROFILE),
case mod_security_server:check_blocked_user(Info, User,
SDirData,
- Addr, Port) of
+ Addr, Port, Profile) of
true ->
report_failed(Info, User ,"User Blocked"),
{proceed, [{status, {403, Info#mod.request_uri, ""}} |
Info#mod.data]};
false ->
report_failed(Info, User,"Authentication Succedded"),
- mod_security_server:store_successful_auth(Addr, Port,
+ mod_security_server:store_successful_auth(Addr, Port, Profile,
User,
SDirData),
{proceed, Info#mod.data}
end
end.
-report_failed(Info, Auth, Event) ->
- Request = Info#mod.request_line,
- {_PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- String = RemoteHost ++ " : " ++ Event ++ " : " ++ Request ++
- " : " ++ Auth,
- mod_disk_log:security_log(Info,String),
- mod_log:security_log(Info, String).
-
-take_failed_action(Info, Auth) ->
- ?hdrd("take failed action", [{auth, Auth}]),
- Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri),
- {_Dir, SDirData} = secretp(Path, Info#mod.config_db),
- Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
- Port = httpd_util:lookup(Info#mod.config_db, port),
- mod_security_server:store_failed_auth(Info, Addr, Port,
- Auth, SDirData).
-
-secretp(Path, ConfigDB) ->
- Directories = ets:match(ConfigDB,{directory,{'$1','_'}}),
- case secret_path(Path, Directories) of
- {yes, Directory} ->
- ?hdrd("secretp - yes", [{dir, Directory}]),
- SDirs0 = httpd_util:multi_lookup(ConfigDB, security_directory),
- [SDir] = lists:filter(fun({Directory0, _})
- when Directory0 == Directory ->
- true;
- (_) ->
- false
- end, SDirs0),
- SDir;
- no ->
- {[], []}
- end.
-
-secret_path(Path,Directories) ->
- secret_path(Path, httpd_util:uniq(lists:sort(Directories)), to_be_found).
-
-secret_path(_Path, [], to_be_found) ->
- no;
-secret_path(_Path, [], Dir) ->
- {yes, Dir};
-secret_path(Path, [[NewDir]|Rest], Dir) ->
- case inets_regexp:match(Path, NewDir) of
- {match, _, _} when Dir =:= to_be_found ->
- secret_path(Path, Rest, NewDir);
- {match, _, Length} when Length > length(Dir) ->
- secret_path(Path, Rest, NewDir);
- {match, _, _} ->
- secret_path(Path, Rest, Dir);
- nomatch ->
- secret_path(Path, Rest, Dir)
- end.
-
-
load("<Directory " ++ Directory, []) ->
- ?hdrt("load security directory - begin", [{directory, Directory}]),
- Dir = httpd_conf:custom_clean(Directory,"",">"),
+ Dir = string:strip(string:strip(Directory),right, $>),
{ok, [{security_directory, {Dir, [{path, Dir}]}}]};
load(eof,[{security_directory, {Directory, _DirData}}|_]) ->
{error, ?NICE("Premature end-of-file in "++Directory)};
load("SecurityDataFile " ++ FileName,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{file, FileName}, {dir, Dir}, {dir_data, DirData}]),
- File = httpd_conf:clean(FileName),
+ File = string:strip(FileName),
{ok, [{security_directory, {Dir, [{data_file, File}|DirData]}}]};
load("SecurityCallbackModule " ++ ModuleName,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{module, ModuleName}, {dir, Dir}, {dir_data, DirData}]),
- Mod = list_to_atom(httpd_conf:clean(ModuleName)),
+ Mod = list_to_atom(string:strip(ModuleName)),
{ok, [{security_directory, {Dir, [{callback_module, Mod}|DirData]}}]};
load("SecurityMaxRetries " ++ Retries,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{max_retries, Retries}, {dir, Dir}, {dir_data, DirData}]),
load_return_int_tag("SecurityMaxRetries", max_retries,
- httpd_conf:clean(Retries), Dir, DirData);
+ string:strip(Retries), Dir, DirData);
load("SecurityBlockTime " ++ Time,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{block_time, Time}, {dir, Dir}, {dir_data, DirData}]),
load_return_int_tag("SecurityBlockTime", block_time,
- httpd_conf:clean(Time), Dir, DirData);
+ string:strip(Time), Dir, DirData);
load("SecurityFailExpireTime " ++ Time,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{expire_time, Time}, {dir, Dir}, {dir_data, DirData}]),
load_return_int_tag("SecurityFailExpireTime", fail_expire_time,
- httpd_conf:clean(Time), Dir, DirData);
+ string:strip(Time), Dir, DirData);
load("SecurityAuthTimeout " ++ Time0,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{auth_timeout, Time0}, {dir, Dir}, {dir_data, DirData}]),
- Time = httpd_conf:clean(Time0),
+ Time = string:strip(Time0),
load_return_int_tag("SecurityAuthTimeout", auth_timeout,
- httpd_conf:clean(Time), Dir, DirData);
+ string:strip(Time), Dir, DirData);
load("AuthName " ++ Name0,
[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory",
- [{name, Name0}, {dir, Dir}, {dir_data, DirData}]),
- Name = httpd_conf:clean(Name0),
+ Name = string:strip(Name0),
{ok, [{security_directory, {Dir, [{auth_name, Name}|DirData]}}]};
load("</Directory>",[{security_directory, {Dir, DirData}}]) ->
- ?hdrt("load security directory - end",
- [{dir, Dir}, {dir_data, DirData}]),
{ok, [], {security_directory, {Dir, DirData}}}.
-load_return_int_tag(Name, Atom, Time, Dir, DirData) ->
- case Time of
- "infinity" ->
- {ok, [{security_directory, {Dir,
- [{Atom, 99999999999999999999999999999} | DirData]}}]};
- _Int ->
- case catch list_to_integer(Time) of
- {'EXIT', _} ->
- {error, Time++" is an invalid "++Name};
- Val ->
- {ok, [{security_directory, {Dir, [{Atom, Val}|DirData]}}]}
- end
- end.
-
store({security_directory, {Dir, DirData}}, ConfigList)
when is_list(Dir) andalso is_list(DirData) ->
- ?hdrt("store security directory", [{dir, Dir}, {dir_data, DirData}]),
Addr = proplists:get_value(bind_address, ConfigList),
Port = proplists:get_value(port, ConfigList),
- mod_security_server:start(Addr, Port),
+ Profile = proplists:get_value(profile, ConfigList, ?DEFAULT_PROFILE),
+ mod_security_server:start(Addr, Port, Profile),
SR = proplists:get_value(server_root, ConfigList),
case proplists:get_value(data_file, DirData, no_data_file) of
no_data_file ->
@@ -241,7 +155,7 @@ store({security_directory, {Dir, DirData}}, ConfigList)
_ ->
DataFile0
end,
- case mod_security_server:new_table(Addr, Port, DataFile) of
+ case mod_security_server:new_table(Addr, Port, Profile, DataFile) of
{ok, TwoTables} ->
NewDirData0 = lists:keyreplace(data_file, 1, DirData,
{data_file, TwoTables}),
@@ -261,45 +175,35 @@ store({directory, {Directory, DirData}}, _) ->
{error, {wrong_type, {security_directory, {Directory, DirData}}}}.
remove(ConfigDB) ->
- Addr = case ets:lookup(ConfigDB, bind_address) of
- [] ->
- undefined;
- [{bind_address, Address}] ->
- Address
- end,
- [{port, Port}] = ets:lookup(ConfigDB, port),
- mod_security_server:delete_tables(Addr, Port),
- mod_security_server:stop(Addr, Port).
+ Addr = httpd_util:lookup(ConfigDB, bind_address, undefined),
+ Port = httpd_util:lookup(ConfigDB, port),
+ Profile = httpd_util:lookup(ConfigDB, profile, ?DEFAULT_PROFILE),
+ mod_security_server:delete_tables(Addr, Port, Profile),
+ mod_security_server:stop(Addr, Port, Profile).
-%%
-%% User API
-%%
-
-%% list_blocked_users
-
list_blocked_users(Port) ->
list_blocked_users(undefined, Port).
list_blocked_users(Port, Dir) when is_integer(Port) ->
list_blocked_users(undefined,Port,Dir);
list_blocked_users(Addr, Port) when is_integer(Port) ->
- mod_security_server:list_blocked_users(Addr, Port).
+ lists:map(fun({User, Addr0, Port0, ?DEFAULT_PROFILE, Dir0, Time}) ->
+ {User, Addr0, Port0, Dir0,Time}
+ end,
+ mod_security_server:list_blocked_users(Addr, Port)).
list_blocked_users(Addr, Port, Dir) ->
- mod_security_server:list_blocked_users(Addr, Port, Dir).
-
-
-%% block_user
+ lists:map(fun({User, Addr0, Port0, ?DEFAULT_PROFILE, Dir0, Time}) ->
+ {User, Addr0, Port0, Dir0,Time}
+ end,
+ mod_security_server:list_blocked_users(Addr, Port, Dir)).
block_user(User, Port, Dir, Time) ->
block_user(User, undefined, Port, Dir, Time).
block_user(User, Addr, Port, Dir, Time) ->
mod_security_server:block_user(User, Addr, Port, Dir, Time).
-
-%% unblock_user
-
unblock_user(User, Port) ->
unblock_user(User, undefined, Port).
@@ -311,9 +215,6 @@ unblock_user(User, Addr, Port) when is_integer(Port) ->
unblock_user(User, Addr, Port, Dir) ->
mod_security_server:unblock_user(User, Addr, Port, Dir).
-
-%% list_auth_users
-
list_auth_users(Port) ->
list_auth_users(undefined,Port).
@@ -324,3 +225,76 @@ list_auth_users(Addr, Port) when is_integer(Port) ->
list_auth_users(Addr, Port, Dir) ->
mod_security_server:list_auth_users(Addr, Port, Dir).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+report_failed(Info, Auth, Event) ->
+ Request = Info#mod.request_line,
+ {_PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ String = RemoteHost ++ " : " ++ Event ++ " : " ++ Request ++
+ " : " ++ Auth,
+ mod_disk_log:security_log(Info,String),
+ mod_log:security_log(Info, String).
+
+take_failed_action(Info, Auth) ->
+ Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
+ Info#mod.request_uri),
+ {_Dir, SDirData} = secretp(Path, Info#mod.config_db),
+ Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
+ Port = httpd_util:lookup(Info#mod.config_db, port),
+ Profile = httpd_util:lookup(Info#mod.config_db, profile, ?DEFAULT_PROFILE),
+ mod_security_server:store_failed_auth(Info, Addr, Port, Profile,
+ Auth, SDirData).
+
+secretp(Path, ConfigDB) ->
+ Directories = ets:match(ConfigDB,{directory,{'$1','_'}}),
+ case secret_path(Path, Directories) of
+ {yes, Directory} ->
+ SDirs0 = httpd_util:multi_lookup(ConfigDB, security_directory),
+ [SDir] = lists:filter(fun({Directory0, _})
+ when Directory0 == Directory ->
+ true;
+ (_) ->
+ false
+ end, SDirs0),
+ SDir;
+ no ->
+ {[], []}
+ end.
+
+secret_path(Path,Directories) ->
+ secret_path(Path, httpd_util:uniq(lists:sort(Directories)), to_be_found).
+
+secret_path(_Path, [], to_be_found) ->
+ no;
+secret_path(_Path, [], Dir) ->
+ {yes, Dir};
+secret_path(Path, [[NewDir]|Rest], Dir) ->
+ case inets_regexp:match(Path, NewDir) of
+ {match, _, _} when Dir =:= to_be_found ->
+ secret_path(Path, Rest, NewDir);
+ {match, _, Length} when Length > length(Dir) ->
+ secret_path(Path, Rest, NewDir);
+ {match, _, _} ->
+ secret_path(Path, Rest, Dir);
+ nomatch ->
+ secret_path(Path, Rest, Dir)
+ end.
+
+
+
+load_return_int_tag(Name, Atom, Time, Dir, DirData) ->
+ case Time of
+ "infinity" ->
+ {ok, [{security_directory, {Dir,
+ [{Atom, 99999999999999999999999999999} | DirData]}}]};
+ _Int ->
+ case catch list_to_integer(Time) of
+ {'EXIT', _} ->
+ {error, Time++" is an invalid "++Name};
+ Val ->
+ {ok, [{security_directory, {Dir, [{Atom, Val}|DirData]}}]}
+ end
+ end.
diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl
index 784b3eba70..4f37dff18c 100644
--- a/lib/inets/src/http_server/mod_security_server.erl
+++ b/lib/inets/src/http_server/mod_security_server.erl
@@ -45,7 +45,6 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-behaviour(gen_server).
@@ -57,129 +56,105 @@
list_auth_users/2, list_auth_users/3]).
%% Internal exports (for mod_security only)
--export([start/2, stop/1, stop/2,
- new_table/3, delete_tables/2,
- store_failed_auth/5, store_successful_auth/4,
- check_blocked_user/5]).
+-export([start/3, stop/2, stop/3,
+ new_table/4, delete_tables/3,
+ store_failed_auth/6, store_successful_auth/5,
+ check_blocked_user/6]).
%% gen_server exports
--export([start_link/2, init/1,
+-export([start_link/3, init/1,
handle_info/2, handle_call/3, handle_cast/2,
terminate/2,
code_change/3]).
+%%====================================================================
+%% Internal application API
+%%====================================================================
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% External API %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% start_link/3
-%%
%% NOTE: This is called by httpd_misc_sup when the process is started
-%%
-
-start_link(Addr, Port) ->
- ?hdrt("start_link", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+start_link(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
gen_server:start_link({local, Name}, ?MODULE, [], [{timeout, infinity}]).
-
-%% start/2
%% Called by the mod_security module.
-
-start(Addr, Port) ->
- ?hdrt("start", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+start(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
undefined ->
- httpd_misc_sup:start_sec_server(Addr, Port);
+ httpd_misc_sup:start_sec_server(Addr, Port, Profile);
_ -> %% Already started...
ok
end.
-
-%% stop
-
-stop(Port) ->
- stop(undefined, Port).
-stop(Addr, Port) ->
- ?hdrt("stop", [{address, Addr}, {port, Port}]),
- Name = make_name(Addr, Port),
+stop(Port, Profile) ->
+ stop(undefined, Port, Profile).
+stop(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
undefined ->
ok;
_ ->
- httpd_misc_sup:stop_sec_server(Addr, Port)
+ httpd_misc_sup:stop_sec_server(Addr, Port, Profile)
end.
-
addr(undefined) ->
any;
addr(Addr) ->
Addr.
-
-%% list_blocked_users
-
list_blocked_users(Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {list_blocked_users, addr(Addr), Port, '_'},
- call(Name, Req).
-
+ list_blocked_users(Addr, Port, ?DEFAULT_PROFILE).
+list_blocked_users(Addr, Port, Profile) when is_atom(Profile)->
+ Name = make_name(Addr, Port, Profile),
+ Req = {list_blocked_users, addr(Addr), Port, Profile,'_'},
+ call(Name, Req);
list_blocked_users(Addr, Port, Dir) ->
- Name = make_name(Addr, Port),
- Req = {list_blocked_users, addr(Addr), Port, Dir},
+ list_blocked_users(Addr, Port, ?DEFAULT_PROFILE, Dir).
+list_blocked_users(Addr, Port, Profile, Dir) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {list_blocked_users, addr(Addr), Port, Profile, Dir},
call(Name, Req).
-
-%% block_user
-
block_user(User, Addr, Port, Dir, Time) ->
- Name = make_name(Addr, Port),
- Req = {block_user, User, addr(Addr), Port, Dir, Time},
+ block_user(User, Addr, Port, ?DEFAULT_PROFILE, Dir, Time).
+block_user(User, Addr, Port, Profile, Dir, Time) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {block_user, User, addr(Addr), Port, Profile, Dir, Time},
call(Name, Req).
-
-%% unblock_user
-
unblock_user(User, Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {unblock_user, User, addr(Addr), Port, '_'},
- call(Name, Req).
-
+ unblock_user(User, Addr, Port, ?DEFAULT_PROFILE).
+unblock_user(User, Addr, Port, Profile) when is_atom(Profile)->
+ Name = make_name(Addr, Port, Profile),
+ Req = {unblock_user, User, addr(Addr), Port, Profile, '_'},
+ call(Name, Req);
unblock_user(User, Addr, Port, Dir) ->
- Name = make_name(Addr, Port),
- Req = {unblock_user, User, addr(Addr), Port, Dir},
+ unblock_user(User, Addr, Port, ?DEFAULT_PROFILE, Dir).
+unblock_user(User, Addr, Port, Profile, Dir) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {unblock_user, User, addr(Addr), Port, Profile, Dir},
call(Name, Req).
-
-%% list_auth_users
-
list_auth_users(Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {list_auth_users, addr(Addr), Port, '_'},
- call(Name, Req).
-
+ list_auth_users(Addr, Port, ?DEFAULT_PROFILE).
+list_auth_users(Addr, Port, Profile) when is_atom(Profile) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {list_auth_users, addr(Addr), Port, Profile, '_'},
+ call(Name, Req);
list_auth_users(Addr, Port, Dir) ->
- Name = make_name(Addr,Port),
- Req = {list_auth_users, addr(Addr), Port, Dir},
+ list_auth_users(Addr, Port, ?DEFAULT_PROFILE, Dir).
+list_auth_users(Addr, Port, Profile, Dir) ->
+ Name = make_name(Addr,Port, Profile),
+ Req = {list_auth_users, addr(Addr), Port, Profile, Dir},
call(Name, Req).
-
-%% new_table
-
-new_table(Addr, Port, TabName) ->
- Name = make_name(Addr,Port),
- Req = {new_table, addr(Addr), Port, TabName},
+new_table(Addr, Port, Profile, TabName) ->
+ Name = make_name(Addr,Port, Profile),
+ Req = {new_table, addr(Addr), Port, Profile, TabName},
call(Name, Req).
-
-%% delete_tables
-
-delete_tables(Addr, Port) ->
- Name = make_name(Addr, Port),
+delete_tables(Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
case whereis(Name) of
undefined ->
ok;
@@ -187,79 +162,53 @@ delete_tables(Addr, Port) ->
call(Name, delete_tables)
end.
-
-%% store_failed_auth
-
-store_failed_auth(Info, Addr, Port, DecodedString, SDirData) ->
- ?hdrv("store failed auth",
- [{addr, Addr}, {port, Port},
- {decoded_string, DecodedString}, {sdir_data, SDirData}]),
- Name = make_name(Addr,Port),
- Msg = {store_failed_auth,[Info,DecodedString,SDirData]},
+store_failed_auth(Info, Addr, Port, Profile, DecodedString, SDirData) ->
+ Name = make_name(Addr, Port, Profile),
+ Msg = {store_failed_auth, Profile, [Info,DecodedString,SDirData]},
cast(Name, Msg).
-
-%% store_successful_auth
-
-store_successful_auth(Addr, Port, User, SDirData) ->
- Name = make_name(Addr,Port),
- Msg = {store_successful_auth, [User,Addr,Port,SDirData]},
+store_successful_auth(Addr, Port, Profile, User, SDirData) ->
+ Name = make_name(Addr,Port, Profile),
+ Msg = {store_successful_auth, [User,Addr,Port, Profile, SDirData]},
cast(Name, Msg).
-
-
-%% check_blocked_user
-
-check_blocked_user(Info, User, SDirData, Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {check_blocked_user, [Info, User, SDirData]},
+
+check_blocked_user(Info, User, SDirData, Addr, Port, Profile) ->
+ Name = make_name(Addr, Port, Profile),
+ Req = {check_blocked_user, Profile, [Info, User, SDirData]},
call(Name, Req).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Server call-back functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+%%====================================================================
+%% Behavior call backs
+%%====================================================================
init(_) ->
- ?hdrv("initiating", []),
process_flag(trap_exit, true),
{ok, []}.
handle_call(stop, _From, _Tables) ->
{stop, normal, ok, []};
-handle_call({block_user, User, Addr, Port, Dir, Time}, _From, Tables) ->
- ?hdrv("block user",
- [{user, User}, {addr, Addr}, {port, Port}, {dir, Dir},
- {time, Time}]),
- Ret = block_user_int(User, Addr, Port, Dir, Time),
+handle_call({block_user, User, Addr, Port, Profile, Dir, Time}, _From, Tables) ->
+ Ret = block_user_int(User, Addr, Port, Profile, Dir, Time),
{reply, Ret, Tables};
-handle_call({list_blocked_users, Addr, Port, Dir}, _From, Tables) ->
- ?hdrv("list blocked users",
- [{addr, Addr}, {port, Port}, {dir, Dir}]),
- Blocked = list_blocked(Tables, Addr, Port, Dir, []),
+handle_call({list_blocked_users, Addr, Port, Profile, Dir}, _From, Tables) ->
+ Blocked = list_blocked(Tables, Addr, Port, Profile, Dir, []),
{reply, Blocked, Tables};
-handle_call({unblock_user, User, Addr, Port, Dir}, _From, Tables) ->
- ?hdrv("block user",
- [{user, User}, {addr, Addr}, {port, Port}, {dir, Dir}]),
- Ret = unblock_user_int(User, Addr, Port, Dir),
+handle_call({unblock_user, User, Addr, Port, Profile, Dir}, _From, Tables) ->
+ Ret = unblock_user_int(User, Addr, Port, Profile,Dir),
{reply, Ret, Tables};
-handle_call({list_auth_users, Addr, Port, Dir}, _From, Tables) ->
- ?hdrv("list auth users",
- [{addr, Addr}, {port, Port}, {dir, Dir}]),
- Auth = list_auth(Tables, Addr, Port, Dir, []),
+handle_call({list_auth_users, Addr, Port, Profile, Dir}, _From, Tables) ->
+ Auth = list_auth(Tables, Addr, Port, Profile, Dir, []),
{reply, Auth, Tables};
-handle_call({new_table, Addr, Port, Name}, _From, Tables) ->
+handle_call({new_table, Addr, Port, Profile, Name}, _From, Tables) ->
case lists:keysearch(Name, 1, Tables) of
{value, {Name, {Ets, Dets}}} ->
{reply, {ok, {Ets, Dets}}, Tables};
false ->
- TName = make_name(Addr,Port,length(Tables)),
+ TName = make_name(Addr,Port, Profile, length(Tables)),
case dets:open_file(TName, [{type, bag}, {file, Name},
{repair, true},
{access, read_write}]) of
@@ -280,7 +229,7 @@ handle_call(delete_tables, _From, Tables) ->
end, Tables),
{reply, ok, []};
-handle_call({check_blocked_user, [Info, User, SDirData]}, _From, Tables) ->
+handle_call({check_blocked_user, Profile, [Info, User, SDirData]}, _From, Tables) ->
{ETS, DETS} = proplists:get_value(data_file, SDirData),
Dir = proplists:get_value(path, SDirData),
Addr = proplists:get_value(bind_address, SDirData),
@@ -288,27 +237,24 @@ handle_call({check_blocked_user, [Info, User, SDirData]}, _From, Tables) ->
CBModule =
proplists:get_value(callback_module, SDirData, no_module_at_all),
Ret =
- check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
+ check_blocked_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule),
{reply, Ret, Tables};
handle_call(_Request,_From,Tables) ->
{reply,ok,Tables}.
-
-%% handle_cast
-
-handle_cast({store_failed_auth, [_, _, []]}, Tables) ->
+handle_cast({store_failed_auth, _,[_, _, []]}, Tables) ->
%% Some other authentication scheme than mod_auth (example mod_htacess)
%% was the source for the authentication failure so we should ignor it!
{noreply, Tables};
-handle_cast({store_failed_auth, [Info, DecodedString, SDirData]}, Tables) ->
+handle_cast({store_failed_auth, Profile, [Info, DecodedString, SDirData]}, Tables) ->
{ETS, DETS} = proplists:get_value(data_file, SDirData),
Dir = proplists:get_value(path, SDirData),
Addr = proplists:get_value(bind_address, SDirData),
Port = proplists:get_value(port, SDirData),
{ok, [User,Password]} = httpd_util:split(DecodedString,":",2),
Seconds = universal_time(),
- Key = {User, Dir, Addr, Port},
+ Key = {User, Dir, Addr, Port, Profile},
%% Event
CBModule = proplists:get_value(callback_module,
SDirData, no_module_at_all),
@@ -363,7 +309,7 @@ handle_cast({store_failed_auth, [Info, DecodedString, SDirData]}, Tables) ->
dets:match_delete(DETS, {blocked_user,
{User, Addr, Port, Dir, '$1'}}),
BlockRecord = {blocked_user,
- {User, Addr, Port, Dir, Future}},
+ {User, Addr, Port, Profile, Dir, Future}},
ets:insert(ETS, BlockRecord),
dets:insert(DETS, BlockRecord),
%% Remove previous failed requests.
@@ -374,11 +320,11 @@ handle_cast({store_failed_auth, [Info, DecodedString, SDirData]}, Tables) ->
end,
{noreply, Tables};
-handle_cast({store_successful_auth, [User, Addr, Port, SDirData]}, Tables) ->
+handle_cast({store_successful_auth, [User, Addr, Port, Profile, SDirData]}, Tables) ->
{ETS, DETS} = proplists:get_value(data_file, SDirData),
AuthTimeOut = proplists:get_value(auth_timeout, SDirData, 30),
Dir = proplists:get_value(path, SDirData),
- Key = {User, Dir, Addr, Port},
+ Key = {User, Dir, Addr, Port, Profile},
%% Remove failed entries for this Key
dets:match_delete(DETS, {failed, {Key, '_', '_'}}),
@@ -396,33 +342,22 @@ handle_cast(Req, Tables) ->
error_msg("security server got unknown cast: ~p",[Req]),
{noreply, Tables}.
-
-%% handle_info
-
handle_info(_Info, State) ->
{noreply, State}.
-
-%% terminate
-
terminate(_Reason, _Tables) ->
ok.
-
-%% code_change({down, ToVsn}, State, Extra)
-%%
-code_change({down, _}, State, _Extra) ->
- {ok, State};
-
-
-%% code_change(FromVsn, State, Extra)
-%%
code_change(_, State, _Extra) ->
{ok, State}.
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
%% block_user_int/5
-block_user_int(User, Addr, Port, Dir, Time) ->
- Dirs = httpd_manager:config_match(Addr, Port,
+block_user_int(User, Addr, Port, Profile, Dir, Time) ->
+ Dirs = httpd_manager:config_match(Addr, Port, Profile,
{security_directory, {'_', '_'}}),
case find_dirdata(Dirs, Dir) of
{ok, DirData, {ETS, DETS}} ->
@@ -434,11 +369,11 @@ block_user_int(User, Addr, Port, Dir, Time) ->
Time
end,
Future = universal_time()+Time1,
- ets:match_delete(ETS, {blocked_user, {User,Addr,Port,Dir,'_'}}),
+ ets:match_delete(ETS, {blocked_user, {User,Addr,Port,Profile, Dir,'_'}}),
dets:match_delete(DETS, {blocked_user,
- {User,Addr,Port,Dir,'_'}}),
- ets:insert(ETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
- dets:insert(DETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
+ {User,Addr,Port,Profile, Dir,'_'}}),
+ ets:insert(ETS, {blocked_user, {User,Addr,Port, Profile, Dir,Future}}),
+ dets:insert(DETS, {blocked_user, {User,Addr,Port,Profile, Dir,Future}}),
CBModule = proplists:get_value(callback_module, DirData,
no_module_at_all),
user_block_event(CBModule,Addr,Port,Dir,User),
@@ -447,7 +382,6 @@ block_user_int(User, Addr, Port, Dir, Time) ->
{error, no_such_directory}
end.
-
find_dirdata([], _Dir) ->
false;
find_dirdata([{security_directory, {_, DirData}}|SDirs], Dir) ->
@@ -460,21 +394,20 @@ find_dirdata([{security_directory, {_, DirData}}|SDirs], Dir) ->
find_dirdata(SDirs, Dir)
end.
-%% unblock_user_int/4
-unblock_user_int(User, Addr, Port, Dir) ->
- Dirs = httpd_manager:config_match(Addr, Port,
+unblock_user_int(User, Addr, Port, Profile, Dir) ->
+ Dirs = httpd_manager:config_match(Addr, Port, Profile,
{security_directory, {'_', '_'}}),
case find_dirdata(Dirs, Dir) of
{ok, DirData, {ETS, DETS}} ->
case ets:match_object(ETS,
- {blocked_user,{User,Addr,Port,Dir,'_'}}) of
+ {blocked_user,{User,Addr,Port,Profile,Dir,'_'}}) of
[] ->
{error, not_blocked};
_Objects ->
ets:match_delete(ETS, {blocked_user,
- {User, Addr, Port, Dir, '_'}}),
+ {User, Addr, Port, Profile, Dir, '_'}}),
dets:match_delete(DETS, {blocked_user,
- {User, Addr, Port, Dir, '_'}}),
+ {User, Addr, Port, Profile, Dir, '_'}}),
CBModule = proplists:get_value(callback_module,
DirData,
no_module_at_all),
@@ -485,63 +418,51 @@ unblock_user_int(User, Addr, Port, Dir) ->
{error, no_such_directory}
end.
-
-
-%% list_auth/2
-
-list_auth([], _Addr, _Port, _Dir, Acc) ->
+list_auth([], _, _, _, _, Acc) ->
Acc;
-list_auth([{_Name, {ETS, DETS}}|Tables], Addr, Port, Dir, Acc) ->
- case ets:match_object(ETS, {success, {{'_', Dir, Addr, Port}, '_'}}) of
+list_auth([{_Name, {ETS, DETS}}|Tables], Addr, Port, Profile, Dir, Acc) ->
+ case ets:match_object(ETS, {success, {{'_', Dir, Addr, Port, Profile}, '_'}}) of
[] ->
- list_auth(Tables, Addr, Port, Dir, Acc);
+ list_auth(Tables, Addr, Port, Profile, Dir, Acc);
List ->
TN = universal_time(),
- NewAcc = lists:foldr(fun({success,{{U,Ad,P,D},T}},Ac) ->
+ NewAcc = lists:foldr(fun({success,{{U,Ad,P, Pr,D},T}},Ac) ->
if
T-TN > 0 ->
[U|Ac];
true ->
Rec = {success,
- {{U,Ad,P,D},T}},
+ {{U,Ad,P,Pr,D},T}},
ets:match_delete(ETS,Rec),
dets:match_delete(DETS,Rec),
Ac
end
end,
Acc, List),
- list_auth(Tables, Addr, Port, Dir, NewAcc)
+ list_auth(Tables, Addr, Port, Profile, Dir, NewAcc)
end.
-
-%% list_blocked/2
-
-list_blocked([], _Addr, _Port, _Dir, Acc) ->
- ?hdrv("list blocked", [{acc, Acc}]),
+list_blocked([], _, _, _, _, Acc) ->
TN = universal_time(),
- lists:foldl(fun({U,Ad,P,D,T}, Ac) ->
+ lists:foldl(fun({U,Ad,P,Pr,D,T}, Ac) ->
if
T-TN > 0 ->
- [{U,Ad,P,D,local_time(T)}|Ac];
+ [{U,Ad,P, Pr,D,local_time(T)}|Ac];
true ->
Ac
end
end,
[], Acc);
-list_blocked([{_Name, {ETS, _DETS}}|Tables], Addr, Port, Dir, Acc) ->
- ?hdrv("list blocked", [{ets, ETS}, {tab2list, ets:tab2list(ETS)}]),
+list_blocked([{_Name, {ETS, _DETS}}|Tables], Addr, Port, Profile, Dir, Acc) ->
List = ets:match_object(ETS, {blocked_user,
- {'_',Addr,Port,Dir,'_'}}),
+ {'_',Addr,Port,Profile, Dir,'_'}}),
NewBlocked = lists:foldl(fun({blocked_user, X}, A) ->
[X|A] end, Acc, List),
- list_blocked(Tables, Addr, Port, Dir, NewBlocked).
+ list_blocked(Tables, Addr, Port, Profile, Dir, NewBlocked).
-%%
-%% sync_dets_to_ets/2
-%%
%% Reads dets-table DETS and syncronizes it with the ets-table ETS.
%%
sync_dets_to_ets(DETS, ETS) ->
@@ -550,68 +471,62 @@ sync_dets_to_ets(DETS, ETS) ->
continue
end).
-%%
-%% check_blocked_user/7 -> true | false
-%%
%% Check if a specific user is blocked from access.
%%
%% The sideeffect of this routine is that it unblocks also other users
%% whos blocking time has expired. This to keep the tables as small
%% as possible.
%%
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
+check_blocked_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule) ->
TN = universal_time(),
- BlockList = ets:match_object(ETS, {blocked_user, {User, '_', '_', '_', '_'}}),
+ BlockList = ets:match_object(ETS, {blocked_user, {User, '_', '_', '_', '_', '_'}}),
Blocked = lists:foldl(fun({blocked_user, X}, A) ->
[X|A] end, [], BlockList),
check_blocked_user(Info,User,Dir,
- Addr,Port,ETS,DETS,TN,Blocked,CBModule).
+ Addr,Port, Profile, ETS,DETS,TN,Blocked,CBModule).
-check_blocked_user(_Info, _User, _Dir, _Addr, _Port, _ETS, _DETS, _TN,
- [], _CBModule) ->
+check_blocked_user(_Info, _, _, _, _, _, _, _, _,[], _CBModule) ->
false;
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
- [{User,Addr,Port,Dir,T}| _], CBModule) ->
+check_blocked_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, TN,
+ [{User,Addr,Port,Profile, Dir,T}| _], CBModule) ->
TD = T-TN,
if
TD =< 0 ->
%% Blocking has expired, remove and grant access.
- unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
+ unblock_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule),
false;
true ->
true
end;
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
- [{OUser,ODir,OAddr,OPort,T}|Ls], CBModule) ->
+check_blocked_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, TN,
+ [{OUser,ODir,OAddr,OPort, OProfile, T}|Ls], CBModule) ->
TD = T-TN,
if
TD =< 0 ->
%% Blocking has expired, remove.
- unblock_user(Info, OUser, ODir, OAddr, OPort,
+ unblock_user(Info, OUser, ODir, OAddr, OPort, OProfile,
ETS, DETS, CBModule);
true ->
true
end,
- check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS,
+ check_blocked_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS,
TN, Ls, CBModule).
-unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
+unblock_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule) ->
Reason =
io_lib:format("User ~s was removed from the block list for dir ~s",
[User, Dir]),
mod_log:security_log(Info, lists:flatten(Reason)),
user_unblock_event(CBModule,Addr,Port,Dir,User),
- dets:match_delete(DETS, {blocked_user, {User, Addr, Port, Dir, '_'}}),
- ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Dir, '_'}}).
+ dets:match_delete(DETS, {blocked_user, {User, Addr, Port, Profile, Dir, '_'}}),
+ ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Profile, Dir, '_'}}).
+make_name(Addr,Port, Profile) ->
+ httpd_util:make_name(?MODULE,Addr,Port, Profile).
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_security",Addr,Port).
-
-make_name(Addr,Port,Num) ->
- httpd_util:make_name("httpd_security",Addr,Port,
- "__" ++ integer_to_list(Num)).
-
+make_name(Addr,Port, Profile, Num) ->
+ httpd_util:make_name(?MODULE,Addr,Port,
+ atom_to_list(Profile) ++ "__" ++ integer_to_list(Num)).
auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) ->
event(auth_fail,Mod,Addr,Port,Dir,[{user,User},{password,Passwd}]).
@@ -623,17 +538,10 @@ user_unblock_event(Mod,Addr,Port,Dir,User) ->
event(user_unblock,Mod,Addr,Port,Dir,[{user,User}]).
event(Event, Mod, undefined, Port, Dir, Info) ->
- ?hdrt("event",
- [{event, Event}, {mod, Mod}, {port, Port}, {dir, Dir}]),
(catch Mod:event(Event,Port,Dir,Info));
event(Event, Mod, any, Port, Dir, Info) ->
- ?hdrt("event",
- [{event, Event}, {mod, Mod}, {port, Port}, {dir, Dir}]),
(catch Mod:event(Event,Port,Dir,Info));
event(Event, Mod, Addr, Port, Dir, Info) ->
- ?hdrt("event",
- [{event, Event}, {mod, Mod},
- {addr, Addr}, {port, Port}, {dir, Dir}]),
(catch Mod:event(Event,Addr,Port,Dir,Info)).
universal_time() ->
@@ -643,11 +551,9 @@ local_time(T) ->
calendar:universal_time_to_local_time(
calendar:gregorian_seconds_to_datetime(T)).
-
error_msg(F, A) ->
error_logger:error_msg(F, A).
-
call(Name, Req) ->
case (catch gen_server:call(Name, Req)) of
{'EXIT', Reason} ->
@@ -656,7 +562,6 @@ call(Name, Req) ->
Reply
end.
-
cast(Name, Msg) ->
case (catch gen_server:cast(Name, Msg)) of
{'EXIT', Reason} ->
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 22426eee79..926585f198 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2015. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -47,7 +47,9 @@ MODULES = \
inets_app \
inets_sup \
inets_regexp \
- inets_trace
+ inets_trace \
+ inets_lib \
+ inets_time_compat
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 9eae962d03..6ba9795d9e 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-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,7 +26,9 @@
inets_app,
inets_service,
inets_regexp,
- inets_trace,
+ inets_trace,
+ inets_lib,
+ inets_time_compat,
%% FTP
ftp,
@@ -61,6 +63,7 @@
httpd_cgi,
httpd_connection_sup,
httpd_conf,
+ httpd_custom,
httpd_esi,
httpd_example,
httpd_file,
@@ -90,7 +93,6 @@
mod_get,
mod_head,
mod_htaccess,
- mod_include,
mod_log,
mod_range,
mod_responsecontrol,
diff --git a/lib/inets/src/inets_app/inets_lib.erl b/lib/inets/src/inets_app/inets_lib.erl
new file mode 100644
index 0000000000..fa6adaebd0
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_lib.erl
@@ -0,0 +1,49 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(inets_lib).
+
+-export([millisec_passed/1, formated_timestamp/0, format_timestamp/1]).
+
+
+
+%% Help function, elapsed milliseconds since T0
+millisec_passed({_,_,_} = T0 ) ->
+ %% OTP 17 and earlier
+ timer:now_diff(inets_time_compat:timestamp(), T0) div 1000;
+
+millisec_passed(T0) ->
+ %% OTP 18
+ erlang:convert_time_unit(erlang:monotonic_time() - T0,
+ native,
+ micro_seconds) div 1000.
+
+%% Return formated time stamp (e.g. 2015:03:16 10:05:23 1234)
+formated_timestamp() ->
+ format_timestamp( os:timestamp() ).
+
+%% Return formated time stamp (e.g. 2015:03:16 10:05:23 1234)
+format_timestamp({_N1, _N2, N3} = Tme) ->
+ {Date, Time} = calendar:now_to_datetime(Tme),
+ {YYYY,MM,DD} = Date,
+ {Hour,Min,Sec} = Time,
+ FormatDate =
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
+ [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
+ lists:flatten(FormatDate).
diff --git a/lib/inets/src/inets_app/inets_time_compat.erl b/lib/inets/src/inets_app/inets_time_compat.erl
new file mode 100644
index 0000000000..d6297d9caf
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_time_compat.erl
@@ -0,0 +1,71 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% 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/inets_app/inets_trace.erl b/lib/inets/src/inets_app/inets_trace.erl
index 8911f65897..cb6d6d8bdb 100644
--- a/lib/inets/src/inets_app/inets_trace.erl
+++ b/lib/inets/src/inets_app/inets_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -228,21 +228,24 @@ handle_trace({trace_ts, _Who, call,
[_Sev, "stop trace", stop_trace, [stop_trace]]},
Timestamp},
{_, standard_io} = Fd) ->
- (catch io:format(standard_io, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch io:format(standard_io, "stop trace at ~s~n",
+ [inets_lib:format_timestamp(Timestamp)])),
Fd;
handle_trace({trace_ts, _Who, call,
{?MODULE, report_event,
[_Sev, "stop trace", stop_trace, [stop_trace]]},
Timestamp},
standard_io = Fd) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch io:format(Fd, "stop trace at ~s~n",
+ [inets_lib:format_timestamp(Timestamp)])),
Fd;
handle_trace({trace_ts, _Who, call,
{?MODULE, report_event,
[_Sev, "stop trace", stop_trace, [stop_trace]]},
Timestamp},
{_Service, Fd}) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch io:format(Fd, "stop trace at ~s~n",
+ [inets_lib:format_timestamp(Timestamp)])),
(catch file:close(Fd)),
closed_file;
handle_trace({trace_ts, _Who, call,
@@ -250,7 +253,8 @@ handle_trace({trace_ts, _Who, call,
[_Sev, "stop trace", stop_trace, [stop_trace]]},
Timestamp},
Fd) ->
- (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])),
+ (catch io:format(Fd, "stop trace at ~s~n",
+ [inets_lib:format_timestamp(Timestamp)])),
(catch file:close(Fd)),
closed_file;
handle_trace({trace_ts, Who, call,
@@ -280,7 +284,7 @@ print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content).
do_print_inets_trace(Fd, Sev, Timestamp, Who, Label, Service, Content) ->
- Ts = format_timestamp(Timestamp),
+ Ts = inets_lib:format_timestamp(Timestamp),
io:format(Fd, "[inets ~w trace ~w ~w ~s] ~s "
"~n Content: ~p"
"~n",
@@ -307,7 +311,7 @@ do_print_trace(Fd, {trace, Who, What, Where, Extra}) ->
"~n", [Who, What, Where, Extra]);
do_print_trace(Fd, {trace_ts, Who, What, Where, When}) ->
- Ts = format_timestamp(When),
+ Ts = inets_lib:format_timestamp(When),
io:format(Fd, "[trace ~s]"
"~n Who: ~p"
"~n What: ~p"
@@ -315,7 +319,7 @@ do_print_trace(Fd, {trace_ts, Who, What, Where, When}) ->
"~n", [Ts, Who, What, Where]);
do_print_trace(Fd, {trace_ts, Who, What, Where, Extra, When}) ->
- Ts = format_timestamp(When),
+ Ts = inets_lib:format_timestamp(When),
io:format(Fd, "[trace ~s]"
"~n Who: ~p"
"~n What: ~p"
@@ -330,7 +334,7 @@ do_print_trace(Fd, {seq_trace, What, Where}) ->
"~n", [What, Where]);
do_print_trace(Fd, {seq_trace, What, Where, When}) ->
- Ts = format_timestamp(When),
+ Ts = inets_lib:format_timestamp(When),
io:format(Fd, "[seq trace ~s]"
"~n What: ~p"
"~n Where: ~p"
@@ -345,13 +349,3 @@ do_print_trace(Fd, Trace) ->
"~n", [Trace]).
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
-
diff --git a/lib/inets/src/tftp/tftp_logger.erl b/lib/inets/src/tftp/tftp_logger.erl
index 0c3620e665..231a705371 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-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -84,8 +84,8 @@ info_msg(Format, Data) ->
%%-------------------------------------------------------------------
add_timestamp(Format, Data) ->
- Now = {_MegaSecs, _Secs, _MicroSecs} = erlang:now(),
- {{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Now),
+ Time = inets_time_compat: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]}.
{"~s:~s:~s tftp: " ++ Format, [t(H), t(Mi), t(S) | Data]}.
diff --git a/lib/inets/src/tftp/tftp_sup.erl b/lib/inets/src/tftp/tftp_sup.erl
index 1cafcc1069..7a0dcffc90 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-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ unique_name(Options) ->
{value, {_, Port}} when is_integer(Port), Port > 0 ->
{tftpd, Port};
_ ->
- {tftpd, erlang:now()}
+ {tftpd, inets_time_compat:unique_integer([positive])}
end.
default_kill_after() ->
diff --git a/lib/inets/test/erl_make_certs.erl b/lib/inets/test/erl_make_certs.erl
index 22dc951ac1..6c168a5704 100644
--- a/lib/inets/test/erl_make_certs.erl
+++ b/lib/inets/test/erl_make_certs.erl
@@ -204,7 +204,7 @@ issuer_der(Issuer) ->
Subject.
subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> user() end,
+ User = if IsRootCA -> "RootCA"; true -> os:getenv("USER", "test_user") end,
Opts = [{email, User ++ "@erlang.org"},
{name, User},
{city, "Stockholm"},
@@ -215,14 +215,6 @@ subject(undefined, IsRootCA) ->
subject(Opts, _) ->
subject(Opts).
-user() ->
- case os:getenv("USER") of
- false ->
- "test_user";
- User ->
- User
- end.
-
subject(SubjectOpts) when is_list(SubjectOpts) ->
Encode = fun(Opt) ->
{Type,Value} = subject_enc(Opt),
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index daee1bdcdc..b637832101 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1352,9 +1352,9 @@ do_delete(Pid, Config) ->
ok.
do_mkdir(Pid) ->
- {A, B, C} = erlang:now(),
- NewDir = "nisse_" ++ integer_to_list(A) ++ "_" ++
- integer_to_list(B) ++ "_" ++ integer_to_list(C),
+ 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 ."),
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 21be7862cb..ab7ffadf75 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -28,6 +28,7 @@
-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
-include("http_internal.hrl").
+-include("httpc_internal.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -106,6 +107,7 @@ only_simulated() ->
empty_response_header,
remote_socket_close,
remote_socket_close_async,
+ process_leak_on_keepalive,
transfer_encoding,
transfer_encoding_identity,
redirect_loop,
@@ -913,6 +915,33 @@ remote_socket_close_async(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+process_leak_on_keepalive(Config) ->
+ {ok, ClosedSocket} = gen_tcp:listen(6666, [{active, false}]),
+ ok = gen_tcp:close(ClosedSocket),
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ HttpcHandlers0 = supervisor:which_children(httpc_handler_sup),
+ {ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
+ HttpcHandlers1 = supervisor:which_children(httpc_handler_sup),
+ ChildrenCount = supervisor:count_children(httpc_handler_sup),
+ %% Assuming that the new handler will be selected for keep_alive
+ %% which could not be the case if other handlers existed
+ [{undefined, Pid, worker, [httpc_handler]}] =
+ ordsets:to_list(
+ ordsets:subtract(ordsets:from_list(HttpcHandlers1),
+ ordsets:from_list(HttpcHandlers0))),
+ sys:replace_state(
+ Pid, fun (State) ->
+ Session = element(3, State),
+ setelement(3, State, Session#session{socket=ClosedSocket})
+ end),
+ {ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
+ %% bad handler with the closed socket should get replaced by
+ %% the new one, so children count should stay the same
+ ChildrenCount = supervisor:count_children(httpc_handler_sup),
+ ok.
+
+%%-------------------------------------------------------------------------
+
stream_to_pid(Config) when is_list(Config) ->
ReceiverPid = create_receiver(pid),
Receiver = ReceiverPid,
@@ -1260,7 +1289,9 @@ dummy_server_init(Caller, ip_comm, Inet, _) ->
{max_header, ?HTTP_MAX_HEADER_SIZE},
{max_version,?HTTP_MAX_VERSION_STRING},
{max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, ?HTTP_MAX_CONTENT_LENGTH}]]},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
[], ListenSocket);
dummy_server_init(Caller, ssl, Inet, SSLOptions) ->
@@ -1276,7 +1307,8 @@ dummy_ssl_server_init(Caller, BaseOpts, Inet) ->
{max_method, ?HTTP_MAX_METHOD_STRING},
{max_version,?HTTP_MAX_VERSION_STRING},
{max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, ?HTTP_MAX_CONTENT_LENGTH}
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
]]},
[], ListenSocket).
@@ -1355,18 +1387,20 @@ handle_request(Module, Function, Args, Socket) ->
stop;
<<>> ->
{httpd_request, parse, [[{max_uri,?HTTP_MAX_URI_SIZE},
- {max_header, ?HTTP_MAX_HEADER_SIZE},
- {max_version,?HTTP_MAX_VERSION_STRING},
- {max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, ?HTTP_MAX_CONTENT_LENGTH}
- ]]};
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]};
Data ->
handle_request(httpd_request, parse,
[Data, [{max_uri, ?HTTP_MAX_URI_SIZE},
- {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
{max_version,?HTTP_MAX_VERSION_STRING},
{max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, ?HTTP_MAX_CONTENT_LENGTH}
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
]], Socket)
end;
NewMFA ->
@@ -1904,12 +1938,13 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
wait4clients([], _Timeout) ->
ok;
wait4clients(Clients, Timeout) when Timeout > 0 ->
- Time = now_ms(),
+ Time = inets_time_compat:monotonic_time(),
+
receive
{'DOWN', _MRef, process, Pid, normal} ->
{value, {Id, _, _}} = lists:keysearch(Pid, 2, Clients),
NewClients = lists:keydelete(Id, 1, Clients),
- wait4clients(NewClients, Timeout - (now_ms() - Time));
+ wait4clients(NewClients, Timeout - inets_lib:millisec_passed(Time));
{'DOWN', _MRef, process, Pid, Reason} ->
{value, {Id, _, _}} = lists:keysearch(Pid, 2, Clients),
ct:fail({bad_client_termination, Id, Reason})
@@ -2002,14 +2037,10 @@ parse_connection_type(Request) ->
"keep-alive" -> keep_alive
end.
-%% Time in milli seconds
-now_ms() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
set_random_seed() ->
- {_, _, Micros} = now(),
- A = erlang:phash2([make_ref(), self(), Micros]),
+ Unique = inets_time_compat:unique_integer(),
+
+ A = erlang:phash2([make_ref(), self(), Unique]),
random:seed(A, A, A).
diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
index ddd23d0c65..fbd85e9e42 100644
--- a/lib/inets/test/httpc_proxy_SUITE.erl
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -79,7 +79,7 @@ local_proxy_cases() ->
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
- case init_apps([crypto,public_key], Config0) of
+ case init_apps(suite_apps(), Config0) of
Config when is_list(Config) ->
make_cert_files(dsa, "server-", Config),
Config;
@@ -94,7 +94,7 @@ end_per_suite(_Config) ->
%% internal functions
suite_apps() ->
- [crypto,public_key].
+ [asn1,crypto,public_key].
%%--------------------------------------------------------------------
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 342004f19b..c90887bcf3 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -53,6 +53,8 @@ all() ->
{group, https_basic},
{group, http_limit},
{group, https_limit},
+ {group, http_custom},
+ {group, https_custom},
{group, http_basic_auth},
{group, https_basic_auth},
{group, http_auth_api},
@@ -66,7 +68,8 @@ all() ->
{group, http_security},
{group, https_security},
{group, http_reload},
- {group, https_reload}
+ {group, https_reload},
+ {group, http_mime_types}
].
groups() ->
@@ -75,6 +78,8 @@ groups() ->
{https_basic, [], basic_groups()},
{http_limit, [], [{group, limit}]},
{https_limit, [], [{group, limit}]},
+ {http_custom, [], [{group, custom}]},
+ {https_custom, [], [{group, custom}]},
{http_basic_auth, [], [{group, basic_auth}]},
{https_basic_auth, [], [{group, basic_auth}]},
{http_auth_api, [], [{group, auth_api}]},
@@ -89,7 +94,9 @@ groups() ->
{https_security, [], [{group, security}]},
{http_reload, [], [{group, reload}]},
{https_reload, [], [{group, reload}]},
+ {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
{limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
+ {custom, [], [customize]},
{reload, [], [non_disturbing_reconfiger_dies,
disturbing_reconfiger_dies,
non_disturbing_1_1,
@@ -127,7 +134,6 @@ http_get() ->
get,
%%actions, Add configuration so that this test mod_action
esi,
- ssi,
content_length,
bad_hex,
missing_CR,
@@ -177,6 +183,7 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_group(Group, Config0) when Group == https_basic;
Group == https_limit;
+ Group == https_custom;
Group == https_basic_auth;
Group == https_auth_api;
Group == https_auth_api_dets;
@@ -187,12 +194,14 @@ init_per_group(Group, Config0) when Group == https_basic;
init_ssl(Group, Config0);
init_per_group(Group, Config0) when Group == http_basic;
Group == http_limit;
+ Group == http_custom;
Group == http_basic_auth;
Group == http_auth_api;
Group == http_auth_api_dets;
Group == http_auth_api_mnesia;
Group == http_security;
- Group == http_reload
+ Group == http_reload;
+ Group == http_mime_types
->
ok = start_apps(Group),
init_httpd(Group, [{type, ip_comm} | Config0]);
@@ -236,7 +245,8 @@ end_per_group(Group, _Config) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_htaccess;
Group == http_security;
- Group == http_reload
+ Group == http_reload;
+ Group == http_mime_types
->
inets:stop();
end_per_group(Group, _Config) when Group == https_basic;
@@ -552,22 +562,6 @@ ipv6(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
-ssi() ->
- [{doc, "HTTP GET server side include test"}].
-ssi(Config) when is_list(Config) ->
- Version = ?config(http_version, Config),
- Host = ?config(host, Config),
- Type = ?config(type, Config),
- ok = httpd_test_lib:verify_request(?config(type, Config), Host, ?config(port, Config),
- transport_opts(Type, Config),
- ?config(node, Config),
- http_request("GET /fsize.shtml ", Version, Host),
- [{statuscode, 200},
- {header, "Content-Type", "text/html"},
- {header, "Date"},
- {header, "Server"},
- {version, Version}]).
-%%-------------------------------------------------------------------------
htaccess_1_1(Config) when is_list(Config) ->
htaccess([{http_version, "HTTP/1.1"} | Config]).
@@ -857,6 +851,24 @@ cgi_chunked_encoding_test(Config) when is_list(Config) ->
?config(node, Config),
Requests).
%%-------------------------------------------------------------------------
+alias_1_1() ->
+ [{doc, "Test mod_alias"}].
+
+alias_1_1(Config) when is_list(Config) ->
+ alias([{http_version, "HTTP/1.1"} | Config]).
+
+alias_1_0() ->
+ [{doc, "Test mod_alias"}].
+
+alias_1_0(Config) when is_list(Config) ->
+ alias([{http_version, "HTTP/1.0"} | Config]).
+
+alias_0_9() ->
+ [{doc, "Test mod_alias"}].
+
+alias_0_9(Config) when is_list(Config) ->
+ alias([{http_version, "HTTP/0.9"} | Config]).
+
alias() ->
[{doc, "Test mod_alias"}].
@@ -915,7 +927,6 @@ trace(Config) when is_list(Config) ->
Cb = ?config(version_cb, Config),
Cb:trace(?config(type, Config), ?config(port, Config),
?config(host, Config), ?config(node, Config)).
-
%%-------------------------------------------------------------------------
light() ->
["Test light load"].
@@ -973,6 +984,30 @@ missing_CR(Config) ->
{version, Version}]).
%%-------------------------------------------------------------------------
+customize() ->
+ [{doc, "Test filtering of headers with custom callback"}].
+
+customize(Config) when is_list(Config) ->
+ Version = "HTTP/1.1",
+ Host = ?config(host, Config),
+ Type = ?config(type, Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config),
+ transport_opts(Type, Config),
+ ?config(node, Config),
+ http_request("GET /index.html ", Version, Host),
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {no_header, "Server"},
+ {version, Version}]).
+
+response_header({"server", _}) ->
+ false;
+response_header(Header) ->
+ {true, Header}.
+
+%%-------------------------------------------------------------------------
max_header() ->
["Denial Of Service (DOS) attack, prevented by max_header"].
max_header(Config) when is_list(Config) ->
@@ -1276,22 +1311,26 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
CgiDir = filename:join(ServerRoot, "cgi-bin"),
AuthDir = filename:join(ServerRoot, "auth"),
PicsDir = filename:join(ServerRoot, "icons"),
+ ConfigDir = filename:join(ServerRoot, "config"),
ok = file:make_dir(ServerRoot),
ok = file:make_dir(DocRoot),
ok = file:make_dir(CgiDir),
ok = file:make_dir(AuthDir),
ok = file:make_dir(PicsDir),
+ ok = file:make_dir(ConfigDir),
DocSrc = filename:join(DataDir, "server_root/htdocs"),
AuthSrc = filename:join(DataDir, "server_root/auth"),
CgiSrc = filename:join(DataDir, "server_root/cgi-bin"),
PicsSrc = filename:join(DataDir, "server_root/icons"),
+ ConfigSrc = filename:join(DataDir, "server_root/config"),
inets_test_lib:copy_dirs(DocSrc, DocRoot),
inets_test_lib:copy_dirs(AuthSrc, AuthDir),
inets_test_lib:copy_dirs(CgiSrc, CgiDir),
inets_test_lib:copy_dirs(PicsSrc, PicsDir),
+ inets_test_lib:copy_dirs(ConfigSrc, ConfigDir),
Cgi = case test_server:os_type() of
{win32, _} ->
@@ -1312,24 +1351,27 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
start_apps(Group) when Group == https_basic;
Group == https_limit;
+ Group == https_custom;
Group == https_basic_auth;
Group == https_auth_api;
Group == https_auth_api_dets;
Group == https_auth_api_mnesia;
- Group == http_htaccess;
- Group == http_security;
- Group == http_reload
+ Group == https_htaccess;
+ Group == https_security;
+ Group == https_reload
->
inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]);
start_apps(Group) when Group == http_basic;
Group == http_limit;
+ Group == http_custom;
Group == http_basic_auth;
Group == http_auth_api;
Group == http_auth_api_dets;
Group == http_auth_api_mnesia;
- Group == https_htaccess;
- Group == https_security;
- Group == https_reload->
+ Group == http_htaccess;
+ Group == http_security;
+ Group == http_reload;
+ Group == http_mime_types->
inets_test_lib:start_apps([inets]).
server_start(_, HttpdConfig) ->
@@ -1381,6 +1423,10 @@ server_config(http_limit, Config) ->
[{max_clients, 1},
%% Make sure option checking code is run
{max_content_length, 100000002}] ++ server_config(http, Config);
+server_config(http_custom, Config) ->
+ [{custom, ?MODULE}] ++ server_config(http, Config);
+server_config(https_custom, Config) ->
+ [{custom, ?MODULE}] ++ server_config(https, Config);
server_config(https_limit, Config) ->
[{max_clients, 1}] ++ server_config(https, Config);
server_config(http_basic_auth, Config) ->
@@ -1417,6 +1463,11 @@ server_config(http_security, Config) ->
server_config(https_security, Config) ->
ServerRoot = ?config(server_root, Config),
tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(https, Config);
+server_config(http_mime_types, Config0) ->
+ Config1 = basic_conf() ++ server_config(http, Config0),
+ ServerRoot = ?config(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),
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/config/mime.types b/lib/inets/test/httpd_SUITE_data/server_root/config/mime.types
new file mode 100644
index 0000000000..b68cff21a6
--- /dev/null
+++ b/lib/inets/test/httpd_SUITE_data/server_root/config/mime.types
@@ -0,0 +1,4 @@
+text/html html
+text/html htm
+text/html shtml
+image/gif gif
diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl
index 9790623b6f..a95a5ee62d 100644
--- a/lib/inets/test/httpd_block.erl
+++ b/lib/inets/test/httpd_block.erl
@@ -292,7 +292,7 @@ httpd_restart(Addr, Port) ->
end.
make_name(Addr, Port) ->
- httpd_util:make_name("httpd", Addr, Port).
+ httpd_util:make_name("httpd", Addr, Port, default).
get_admin_state(_, _Host, Port) ->
Name = make_name(undefined, Port),
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index 0bb457f9b9..7dd61a5517 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -116,13 +116,14 @@ main(N, SocketType, Host, Port, Time)
loop(Pollers, Timeout) ->
d("loop -> entry when"
"~n Timeout: ~p", [Timeout]),
- Start = t(),
+ Start = inets_time_compat:monotonic_time(),
+
receive
{'EXIT', Pid, {poller_stat_failure, SocketType, Host, Port, Time, Reason}} ->
case is_poller(Pid, Pollers) of
true ->
error_msg("received unexpected exit from poller ~p~n"
- "befor completion of test "
+ "before completion of test "
"after ~p micro sec"
"~n SocketType: ~p"
"~n Host: ~p"
@@ -133,7 +134,7 @@ loop(Pollers, Timeout) ->
false ->
error_msg("received unexpected ~p from ~p"
"befor completion of test", [Reason, Pid]),
- loop(Pollers, to(Timeout, Start))
+ loop(Pollers, Timeout - inets_lib:millisec_passed(Start))
end;
{poller_stat_failure, Pid, {SocketType, Host, Port, Time, Reason}} ->
@@ -412,35 +413,6 @@ validate(ExpStatusCode, _SocketType, _Socket, Response) ->
end.
-trash_the_rest(Socket, N) ->
- receive
- {ssl, Socket, Trash} ->
- trash_the_rest(Socket, add(N,sz(Trash)));
- {ssl_closed, Socket} ->
- N;
- {ssl_error, Socket, Error} ->
- exit({connection_error, Error});
-
- {tcp, Socket, Trash} ->
- trash_the_rest(Socket, add(N,sz(Trash)));
- {tcp_closed, Socket} ->
- N;
- {tcp_error, Socket, Error} ->
- exit({connection_error, Error})
-
- after 10000 ->
- exit({connection_timed_out, N})
- end.
-
-
-add(N1,N2) when is_integer(N1) andalso is_integer(N2) ->
- N1 + N2;
-add(N1,_) when is_integer(N1) ->
- N1;
-add(_,N2) when is_integer(N2) ->
- N2.
-
-
sz(L) when is_list(L) ->
length(lists:flatten(L));
sz(B) when is_binary(B) ->
@@ -505,17 +477,6 @@ status_to_message(Code) -> io_lib:format("Unknown status code: ~p",[Code]).
%% ----------------------------------------------------------------
-to(To, Start) ->
- To - (t() - Start).
-
-%% Time in milli seconds
-t() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
-
-%% ----------------------------------------------------------------
-
% close(Socket) ->
diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl
index 6510c70d08..a07dc79c02 100644
--- a/lib/inets/test/inets_SUITE.erl
+++ b/lib/inets/test/inets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -549,25 +549,12 @@ tsf(Reason) ->
tsp(F) ->
tsp(F, []).
tsp(F, A) ->
- Timestamp = formated_timestamp(),
+ Timestamp = inets_lib:formated_timestamp(),
test_server:format("** ~s ** ~p ~p:" ++ F ++ "~n", [Timestamp, self(), ?MODULE | A]).
i(F) ->
i(F, []).
i(F, A) ->
- Timestamp = formated_timestamp(),
+ Timestamp = inets_lib:formated_timestamp(),
io:format("*** ~s ~w:" ++ F ++ "~n", [Timestamp, ?MODULE | A]).
-
-formated_timestamp() ->
- format_timestamp( os:timestamp() ).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
diff --git a/lib/inets/test/inets_app_test.erl b/lib/inets/test/inets_app_test.erl
index eabfa69f7c..22d6e25c87 100644
--- a/lib/inets/test/inets_app_test.erl
+++ b/lib/inets/test/inets_app_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,19 +32,6 @@
%% Test server callbacks
-init_per_testcase(undef_funcs, Config) ->
- NewConfig = lists:keydelete(watchdog, 1, Config),
- Dog = test_server:timetrap(inets_test_lib:minutes(10)),
-
- %% We need to check if there is a point to run this test.
- %% On some platforms, crypto will not build, which in turn
- %% causes ssl to not build (at this time, this will
- %% change in the future).
- %% So, we first check if we can start crypto, and if not,
- %% we skip this test case!
- ?ENSURE_STARTED(crypto),
-
- [{watchdog, Dog}| NewConfig];
init_per_testcase(_, Config) ->
Config.
@@ -54,7 +41,7 @@ end_per_testcase(_Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [fields, modules, exportall, app_depend, undef_funcs].
+ [fields, modules, exportall, app_depend].
groups() ->
[].
@@ -244,56 +231,6 @@ check_apps([App|Apps]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-undef_funcs(suite) ->
- [];
-undef_funcs(doc) ->
- [];
-undef_funcs(Config) when is_list(Config) ->
- App = inets,
- AppFile = key1search(app_file, Config),
- Mods = key1search(modules, AppFile),
- Root = code:root_dir(),
- LibDir = code:lib_dir(App),
- EbinDir = filename:join([LibDir,"ebin"]),
- XRefTestName = undef_funcs_make_name(App, xref_test_name),
- {ok, XRef} = xref:start(XRefTestName),
- ok = xref:set_default(XRef,
- [{verbose,false},{warnings,false}]),
- XRefName = undef_funcs_make_name(App, xref_name),
- {ok, XRefName} = xref:add_release(XRef, Root, {name, XRefName}),
- {ok, App} = xref:replace_application(XRef, App, EbinDir),
- {ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
- xref:stop(XRef),
- analyze_undefined_function_calls(Undefs, Mods, []).
-
-analyze_undefined_function_calls([], _, []) ->
- ok;
-analyze_undefined_function_calls([], _, AppUndefs) ->
- exit({suite_failed, {undefined_function_calls, AppUndefs}});
-analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs],
- AppModules, AppUndefs) ->
- %% Check that this module is our's
- case lists:member(Mod,AppModules) of
- true ->
- {Calling,Called} = AppUndef,
- {Mod1,Func1,Ar1} = Calling,
- {Mod2,Func2,Ar2} = Called,
- io:format("undefined function call: "
- "~n ~w:~w/~w calls ~w:~w/~w~n",
- [Mod1,Func1,Ar1,Mod2,Func2,Ar2]),
- analyze_undefined_function_calls(Undefs, AppModules,
- [AppUndef|AppUndefs]);
- false ->
- io:format("dropping ~p~n", [Mod]),
- analyze_undefined_function_calls(Undefs, AppModules, AppUndefs)
- end.
-
-%% This function is used simply to avoid cut-and-paste errors later...
-undef_funcs_make_name(App, PostFix) ->
- list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
fail(Reason) ->
exit({suite_failed, Reason}).
diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl
index 60979278fc..1479681e30 100644
--- a/lib/inets/test/inets_sup_SUITE.erl
+++ b/lib/inets/test/inets_sup_SUITE.erl
@@ -22,14 +22,14 @@
-include_lib("common_test/include/ct.hrl").
-
%% Note: This directive should only be used in test suites.
-compile(export_all).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [default_tree, ftpc_worker, tftpd_worker, httpd_subtree,
+ [default_tree, ftpc_worker, tftpd_worker,
+ httpd_subtree, httpd_subtree_profile,
httpc_subtree].
groups() ->
@@ -41,54 +41,29 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
init_per_suite(Config) ->
Config.
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
end_per_suite(_) ->
inets:stop(),
ok.
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(Case, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
init_per_testcase(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"),
+ ok = file:make_dir(Dir),
+
SimpleConfig = [{port, 0},
{server_name,"www.test"},
{modules, [mod_get]},
- {server_root, PrivDir},
- {document_root, PrivDir},
+ {server_root, Dir},
+ {document_root, Dir},
{bind_address, any},
{ipfamily, inet}],
try
+ inets:stop(),
inets:start(),
inets:start(httpd, SimpleConfig),
[{watchdog, Dog} | NewConfig]
@@ -97,7 +72,33 @@ init_per_testcase(httpd_subtree, Config) ->
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"),
+ ok = file:make_dir(Dir),
+
+ SimpleConfig = [{port, 0},
+ {server_name,"www.test"},
+ {modules, [mod_get]},
+ {server_root, Dir},
+ {document_root, Dir},
+ {bind_address, any},
+ {profile, test_profile},
+ {ipfamily, inet}],
+ try
+ inets:stop(),
+ inets:start(),
+ {ok, _} = inets:start(httpd, SimpleConfig),
+ [{watchdog, Dog} | NewConfig]
+ catch
+ _:Reason ->
+ inets:stop(),
+ exit({failed_starting_inets, Reason})
+ end;
+
init_per_testcase(_Case, Config) ->
Dog = test_server:timetrap(?t:minutes(5)),
@@ -106,20 +107,13 @@ init_per_testcase(_Case, Config) ->
ok = inets:start(),
[{watchdog, Dog} | NewConfig].
-
-%%--------------------------------------------------------------------
-%% 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(httpd_subtree, 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),
- inets_test_lib:del_dirs(PrivDir),
+ PrivDir = ?config(priv_dir, Config),
+ Dir = filename:join(PrivDir, "root"),
+ inets_test_lib:del_dirs(Dir),
ok;
end_per_testcase(_, Config) ->
@@ -131,16 +125,9 @@ end_per_testcase(_, Config) ->
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
-
-
-%%-------------------------------------------------------------------------
-%% default_tree
-%%-------------------------------------------------------------------------
-default_tree(doc) ->
- ["Makes sure the correct processes are started and linked,"
- "in the default case."];
-default_tree(suite) ->
- [];
+default_tree() ->
+ [{doc, "Makes sure the correct processes are started and linked,"
+ "in the default case."}].
default_tree(Config) when is_list(Config) ->
TopSupChildren = supervisor:which_children(inets_sup),
4 = length(TopSupChildren),
@@ -173,15 +160,9 @@ default_tree(Config) when is_list(Config) ->
ok.
-
-%%-------------------------------------------------------------------------
-%% ftpc_worker
-%%-------------------------------------------------------------------------
-ftpc_worker(doc) ->
- ["Makes sure the ftp worker processes are added and removed "
- "appropriatly to/from the supervison tree."];
-ftpc_worker(suite) ->
- [];
+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) ->
[] = supervisor:which_children(ftp_sup),
try
@@ -207,14 +188,8 @@ ftpc_worker(Config) when is_list(Config) ->
{skip, "No available FTP servers"}
end.
-
-%%-------------------------------------------------------------------------
-%% tftpd_worker
-%%-------------------------------------------------------------------------
-tftpd_worker(doc) ->
- ["Makes sure the tftp sub tree is correct."];
-tftpd_worker(suite) ->
- [];
+tftpd_worker() ->
+ [{doc, "Makes sure the tftp sub tree is correct."}].
tftpd_worker(Config) when is_list(Config) ->
[] = supervisor:which_children(tftp_sup),
{ok, Pid0} = inets:start(tftpd, [{host, inets_test_lib:hostname()},
@@ -228,22 +203,63 @@ tftpd_worker(Config) when is_list(Config) ->
[] = supervisor:which_children(tftp_sup),
ok.
+httpd_subtree() ->
+ [{doc, "Makes sure the httpd sub tree is correct."}].
+httpd_subtree(Config) when is_list(Config) ->
+ do_httpd_subtree(Config, default).
+
+httpd_subtree_profile(doc) ->
+ ["Makes sure the httpd sub tree is correct when using a profile"];
+httpd_subtree_profile(Config) when is_list(Config) ->
+ do_httpd_subtree(Config, test_profile).
+
+httpc_subtree() ->
+ [{doc, "Makes sure the httpd sub tree is correct."}].
+httpc_subtree(Config) when is_list(Config) ->
+ {ok, Foo} = inets:start(httpc, [{profile, foo}]),
+
+ {ok, Bar} = inets:start(httpc, [{profile, bar}], stand_alone),
+
+ HttpcChildren = supervisor:which_children(httpc_profile_sup),
+
+ {value, {httpc_manager, _, worker, [httpc_manager]}} =
+ lists:keysearch(httpc_manager, 1, HttpcChildren),
+
+ {value,{{httpc,foo}, _Pid, worker, [httpc_manager]}} =
+ lists:keysearch({httpc, foo}, 1, HttpcChildren),
+ false = lists:keysearch({httpc, bar}, 1, HttpcChildren),
+
+ inets:stop(httpc, Foo),
+ exit(Bar, normal).
%%-------------------------------------------------------------------------
-%% httpd_subtree
+%% Internal functions
%%-------------------------------------------------------------------------
-httpd_subtree(doc) ->
- ["Makes sure the httpd sub tree is correct."];
-httpd_subtree(suite) ->
- [];
-httpd_subtree(Config) when is_list(Config) ->
- %% Check that we have the httpd top supervisor
+
+verify_child(Parent, Child, Type) ->
+ Children = supervisor:which_children(Parent),
+ verify_child(Children, Parent, Child, Type).
+
+verify_child([], Parent, Child, _Type) ->
+ {error, {child_not_found, Child, Parent}};
+verify_child([{Id, _Pid, Type2, Mods}|Children], Parent, Child, Type) ->
+ case lists:member(Child, Mods) of
+ true when (Type2 =:= Type) ->
+ {ok, Id};
+ true when (Type2 =/= Type) ->
+ {error, {wrong_type, Type2, Child, Parent}};
+ false ->
+ verify_child(Children, Parent, Child, Type)
+ end.
+
+do_httpd_subtree(_Config, Profile) ->
+ %% Check that we have the httpd top supervisor
{ok, _} = verify_child(inets_sup, httpd_sup, supervisor),
%% Check that we have the httpd instance supervisor
{ok, Id} = verify_child(httpd_sup, httpd_instance_sup, supervisor),
- {httpd_instance_sup, Addr, Port} = Id,
- Instance = httpd_util:make_name("httpd_instance_sup", Addr, Port),
+ {httpd_instance_sup, Addr, Port, Profile} = Id,
+ Instance = httpd_util:make_name("httpd_instance_sup", Addr, Port, Profile),
%% Check that we have the expected httpd instance children
{ok, _} = verify_child(Instance, httpd_connection_sup, supervisor),
@@ -252,7 +268,7 @@ httpd_subtree(Config) when is_list(Config) ->
{ok, _} = verify_child(Instance, httpd_manager, worker),
%% Check that the httpd instance acc supervisor has children
- InstanceAcc = httpd_util:make_name("httpd_acceptor_sup", Addr, Port),
+ InstanceAcc = httpd_util:make_name("httpd_acceptor_sup", Addr, Port, Profile),
case supervisor:which_children(InstanceAcc) of
[_ | _] ->
ok;
@@ -263,7 +279,7 @@ httpd_subtree(Config) when is_list(Config) ->
%% Check that the httpd instance misc supervisor has no children
io:format("httpd_subtree -> verify misc~n", []),
- InstanceMisc = httpd_util:make_name("httpd_misc_sup", Addr, Port),
+ InstanceMisc = httpd_util:make_name("httpd_misc_sup", Addr, Port, Profile),
case supervisor:which_children(InstanceMisc) of
[] ->
ok;
@@ -273,45 +289,3 @@ httpd_subtree(Config) when is_list(Config) ->
end,
io:format("httpd_subtree -> done~n", []),
ok.
-
-
-verify_child(Parent, Child, Type) ->
- Children = supervisor:which_children(Parent),
- verify_child(Children, Parent, Child, Type).
-
-verify_child([], Parent, Child, _Type) ->
- {error, {child_not_found, Child, Parent}};
-verify_child([{Id, _Pid, Type2, Mods}|Children], Parent, Child, Type) ->
- case lists:member(Child, Mods) of
- true when (Type2 =:= Type) ->
- {ok, Id};
- true when (Type2 =/= Type) ->
- {error, {wrong_type, Type2, Child, Parent}};
- false ->
- verify_child(Children, Parent, Child, Type)
- end.
-
-%%-------------------------------------------------------------------------
-%% httpc_subtree
-%%-------------------------------------------------------------------------
-httpc_subtree(doc) ->
- ["Makes sure the httpc sub tree is correct."];
-httpc_subtree(suite) ->
- [];
-httpc_subtree(Config) when is_list(Config) ->
- {ok, Foo} = inets:start(httpc, [{profile, foo}]),
-
- {ok, Bar} = inets:start(httpc, [{profile, bar}], stand_alone),
-
- HttpcChildren = supervisor:which_children(httpc_profile_sup),
-
- {value, {httpc_manager, _, worker, [httpc_manager]}} =
- lists:keysearch(httpc_manager, 1, HttpcChildren),
-
- {value,{{httpc,foo}, _Pid, worker, [httpc_manager]}} =
- lists:keysearch({httpc, foo}, 1, HttpcChildren),
- false = lists:keysearch({httpc, bar}, 1, HttpcChildren),
-
- inets:stop(httpc, Foo),
- exit(Bar, normal).
-
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index 4be9d9c8b3..7485971d3e 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -498,13 +498,6 @@ close(essl,Socket) ->
close(ip_comm,Socket) ->
catch gen_tcp:close(Socket).
-millis() ->
- erlang:now().
-
-millis_diff(A,B) ->
- T1 = (element(1,A)*1000000) + element(2,A) + (element(3,A)/1000000),
- T2 = (element(1,B)*1000000) + element(2,B) + (element(3,B)/1000000),
- T1 - T2.
hours(N) -> trunc(N * 1000 * 60 * 60).
minutes(N) -> trunc(N * 1000 * 60).
@@ -546,7 +539,7 @@ flush() ->
tsp(F) ->
tsp(F, []).
tsp(F, A) ->
- Timestamp = formated_timestamp(),
+ Timestamp = inets_lib:formated_timestamp(),
ct:pal("*** ~s ~p ~p " ++ F ++ "~n",
[Timestamp, node(), self() | A]).
@@ -559,18 +552,6 @@ tss(Time) ->
timestamp() ->
http_util:timestamp().
-formated_timestamp() ->
- format_timestamp( os:timestamp() ).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
start_apps(Apps) ->
lists:foreach(fun(App) ->
application:stop(App),
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
index 74c11f71ba..39b0b08645 100644
--- a/lib/inets/test/old_httpd_SUITE.erl
+++ b/lib/inets/test/old_httpd_SUITE.erl
@@ -2072,13 +2072,13 @@ create_config(Config, Access, FileName) ->
"Modules mod_alias mod_htaccess mod_auth "
"mod_security "
"mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
+ "mod_actions mod_cgi mod_dir "
"mod_range mod_get "
"mod_head mod_log mod_disk_log";
_ ->
"Modules mod_alias mod_auth mod_security "
"mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
+ "mod_actions mod_cgi mod_dir "
"mod_range mod_get "
"mod_head mod_log mod_disk_log"
end,
@@ -2436,7 +2436,7 @@ create_ipv6_config(Config, FileName, Ipv6Address) ->
MaxHdrAct = io_lib:format("~p", [close]),
Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
- " mod_include mod_dir mod_get mod_head"
+ " mod_dir mod_get mod_head"
" mod_log mod_disk_log mod_trace",
SSL =
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index ecb84e447c..f52347e39e 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2014. All Rights Reserved.
+# Copyright Ericsson AB 2001-2015. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 5.10.8
+INETS_VSN = 6.0
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"