diff options
Diffstat (limited to 'lib/inets')
25 files changed, 251 insertions, 2282 deletions
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> - <!--#command tag1="value1" tag2="value2" --> - </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/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..f4f0c37570 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}) @@ -1329,7 +1330,7 @@ handle_keep_alive_queue(#state{status = keep_alive, 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 +1345,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, @@ -1850,6 +1851,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 +1875,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 636d580e28..00bad51ff9 100644 --- a/lib/inets/src/http_server/Makefile +++ b/lib/inets/src/http_server/Makefile @@ -76,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_conf.erl b/lib/inets/src/http_server/httpd_conf.erl index dbdc1be272..a21eb915d4 100644 --- a/lib/inets/src/http_server/httpd_conf.erl +++ b/lib/inets/src/http_server/httpd_conf.erl @@ -785,8 +785,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) -> 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/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 48660bec62..6ba9795d9e 100644 --- a/lib/inets/src/inets_app/inets.app.src +++ b/lib/inets/src/inets_app/inets.app.src @@ -26,7 +26,9 @@ inets_app, inets_service, inets_regexp, - inets_trace, + inets_trace, + inets_lib, + inets_time_compat, %% FTP ftp, @@ -91,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 4b1c6931d2..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, @@ -1909,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}) @@ -2007,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/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index 1457f735ad..854ffa8981 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -68,7 +68,8 @@ all() -> {group, http_security}, {group, https_security}, {group, http_reload}, - {group, https_reload} + {group, https_reload}, + {group, http_mime_types} ]. groups() -> @@ -93,1276 +94,9 @@ groups() -> {https_security, [], [{group, security}]}, {http_reload, [], [{group, reload}]}, {https_reload, [], [{group, reload}]}, - {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, + {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]}, + {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, {custom, [], [customize]}, - {reload, [], [non_disturbing_reconfiger_dies, - disturbing_reconfiger_dies, - non_disturbing_1_1, - non_disturbing_1_0, - non_disturbing_0_9, - disturbing_1_1, - disturbing_1_0, - disturbing_0_9 - ]}, - {basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]}, - {auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 - ]}, - {auth_api_dets, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 - ]}, - {auth_api_mnesia, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9 - ]}, - {htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]}, - {security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code - {http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test, - trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()}, - {http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()}, - {http_0_9, [], http_head() ++ http_get() ++ load()} - ]. - -basic_groups ()-> - [{group, http_1_1}, - {group, http_1_0}, - {group, http_0_9} - ]. - -http_head() -> - [head]. -http_get() -> - [alias, - get, - %%actions, Add configuration so that this test mod_action - esi, - ssi, - content_length, - bad_hex, - missing_CR, - max_header, - max_content_length, - ipv6 - ]. - -load() -> - [light, medium - %%,heavy - ]. - -init_per_suite(Config) -> - PrivDir = ?config(priv_dir, Config), - DataDir = ?config(data_dir, Config), - inets_test_lib:stop_apps([inets]), - ServerRoot = filename:join(PrivDir, "server_root"), - inets_test_lib:del_dirs(ServerRoot), - DocRoot = filename:join(ServerRoot, "htdocs"), - setup_server_dirs(ServerRoot, DocRoot, DataDir), - {ok, Hostname0} = inet:gethostname(), - Inet = - case (catch ct:get_config(ipv6_hosts)) of - undefined -> - inet; - Hosts when is_list(Hosts) -> - case lists:member(list_to_atom(Hostname0), Hosts) of - true -> - inet6; - false -> - inet - end; - _ -> - inet - end, - [{server_root, ServerRoot}, - {doc_root, DocRoot}, - {ipfamily, Inet}, - {node, node()}, - {host, inets_test_lib:hostname()}, - {address, getaddr()} | Config]. - -end_per_suite(_Config) -> - ok. - -%%-------------------------------------------------------------------- -init_per_group(Group, Config0) when Group == https_basic; - Group == https_limit; - Group == https_custom; - Group == https_basic_auth; - Group == https_auth_api; - Group == https_auth_api_dets; - Group == https_auth_api_mnesia; - Group == https_security; - Group == https_reload - -> - init_ssl(Group, Config0); -init_per_group(Group, Config0) when Group == http_basic; - Group == http_limit; - Group == http_custom; - Group == http_basic_auth; - Group == http_auth_api; - Group == http_auth_api_dets; - Group == http_auth_api_mnesia; - Group == http_security; - Group == http_reload - -> - ok = start_apps(Group), - init_httpd(Group, [{type, ip_comm} | Config0]); -init_per_group(http_1_1, Config) -> - [{http_version, "HTTP/1.1"} | Config]; -init_per_group(http_1_0, Config) -> - [{http_version, "HTTP/1.0"} | Config]; -init_per_group(http_0_9, Config) -> - case {os:type(), os:version()} of - {{win32, _}, {5,1,2600}} -> - {skip, "eaddrinuse XP problem"}; - _ -> - [{http_version, "HTTP/0.9"} | Config] - end; -init_per_group(http_htaccess = Group, Config) -> - Path = ?config(doc_root, Config), - catch remove_htaccess(Path), - create_htaccess_data(Path, ?config(address, Config)), - ok = start_apps(Group), - init_httpd(Group, [{type, ip_comm} | Config]); -init_per_group(https_htaccess = Group, Config) -> - Path = ?config(doc_root, Config), - catch remove_htaccess(Path), - create_htaccess_data(Path, ?config(address, Config)), - init_ssl(Group, Config); -init_per_group(auth_api, Config) -> - [{auth_prefix, ""} | Config]; -init_per_group(auth_api_dets, Config) -> - [{auth_prefix, "dets_"} | Config]; -init_per_group(auth_api_mnesia, Config) -> - start_mnesia(?config(node, Config)), - [{auth_prefix, "mnesia_"} | Config]; -init_per_group(_, Config) -> - Config. - -end_per_group(Group, _Config) when Group == http_basic; - Group == http_limit; - Group == http_basic_auth; - Group == http_auth_api; - Group == http_auth_api_dets; - Group == http_auth_api_mnesia; - Group == http_htaccess; - Group == http_security; - Group == http_reload - -> - inets:stop(); -end_per_group(Group, _Config) when Group == https_basic; - Group == https_limit; - Group == https_basic_auth; - Group == https_auth_api; - Group == https_auth_api_dets; - Group == https_auth_api_mnesia; - Group == https_htaccess; - Group == https_security; - Group == https_reload - -> - ssl:stop(), - inets:stop(); - -end_per_group(auth_api_mnesia, _) -> - cleanup_mnesia(); - -end_per_group(_, _) -> - ok. - -%%-------------------------------------------------------------------- -init_per_testcase(Case, Config) when Case == host; Case == trace -> - Prop = ?config(tc_group_properties, Config), - Name = proplists:get_value(name, Prop), - Cb = case Name of - http_1_0 -> - httpd_1_0; - http_1_1 -> - httpd_1_1 - end, - [{version_cb, Cb} | proplists:delete(version_cb, Config)]; - -init_per_testcase(range, Config) -> - DocRoot = ?config(doc_root, Config), - create_range_data(DocRoot), - Config; - -init_per_testcase(_, Config) -> - Config. - -end_per_testcase(_Case, _Config) -> - ok. - -%%------------------------------------------------------------------------- -%% Test cases starts here. -%%------------------------------------------------------------------------- - -head() -> - [{doc, "HTTP HEAD request for static page"}]. - -head(Config) when is_list(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), ?config(node, Config), - http_request("HEAD /index.html ", Version, Host), - [{statuscode, head_status(Version)}, - {version, Version}]). - -get() -> - [{doc, "HTTP GET request for static page"}]. - -get(Config) when is_list(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Type = ?config(type, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), - transport_opts(Type, Config), - ?config(node, Config), - http_request("GET /index.html ", Version, Host), - [{statuscode, 200}, - {header, "Content-Type", "text/html"}, - {header, "Date"}, - {header, "Server"}, - {version, Version}]). - -basic_auth_1_1(Config) when is_list(Config) -> - basic_auth([{http_version, "HTTP/1.1"} | Config]). - -basic_auth_1_0(Config) when is_list(Config) -> - basic_auth([{http_version, "HTTP/1.0"} | Config]). - -basic_auth_0_9(Config) when is_list(Config) -> - basic_auth([{http_version, "HTTP/0.9"} | Config]). - -basic_auth() -> - [{doc, "Test Basic authentication with WWW-Authenticate header"}]. - -basic_auth(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - basic_auth_requiered(Config), - %% Authentication OK! ["one:OnePassword" user first in user list] - ok = auth_status(auth_request("/open/dummy.html", "one", "onePassword", Version, Host), Config, - [{statuscode, 200}]), - %% Authentication OK and a directory listing is supplied! - %% ["Aladdin:open sesame" user second in user list] - ok = auth_status(auth_request("/open/", "Aladdin", "AladdinPassword", Version, Host), Config, - [{statuscode, 200}]), - %% User correct but wrong password! ["one:one" user first in user list] - ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config, - [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - %% Make sure Authenticate header is received even the second time - %% we try a incorrect password! Otherwise a browser client will hang! - ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config, - [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - %% Neither user or password correct! ["dummy:dummy"] - ok = auth_status(auth_request("/open/dummy.html", "dummy", "dummy", Version, Host), Config, - [{statuscode, 401}]), - %% Nested secret/top_secret OK! ["Aladdin:open sesame"] - ok = http_status(auth_request("/secret/top_secret/", "Aladdin", "AladdinPassword", Version, Host), - Config, [{statuscode, 200}]), - %% Authentication still required! - basic_auth_requiered(Config). - -auth_api_1_1(Config) when is_list(Config) -> - auth_api([{http_version, "HTTP/1.1"} | Config]). - -auth_api_1_0(Config) when is_list(Config) -> - auth_api([{http_version, "HTTP/1.0"} | Config]). - -auth_api_0_9(Config) when is_list(Config) -> - auth_api([{http_version, "HTTP/0.9"} | Config]). - -auth_api() -> - [{doc, "Test mod_auth API"}]. - -auth_api(Config) when is_list(Config) -> - Prefix = ?config(auth_prefix, Config), - do_auth_api(Prefix, Config). - -do_auth_api(AuthPrefix, Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Node = ?config(node, Config), - ServerRoot = ?config(server_root, Config), - ok = http_status("GET / ", Config, - [{statuscode, 200}]), - ok = auth_status(auth_request("/", "one", "WrongPassword", Version, Host), Config, - [{statuscode, 200}]), - - %% Make sure Authenticate header is received even the second time - %% we try a incorrect password! Otherwise a browser client will hang! - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "dummy", "WrongPassword", Version, Host), Config, - [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", "dummy", "WrongPassword", - Version, Host), Config, [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - - %% Change the password to DummyPassword then try to add a user - %% Get an error and set it to NoPassword - ok = update_password(Node, ServerRoot, Host, Port, AuthPrefix, - "open", "NoPassword", "DummyPassword"), - {error,bad_password} = - add_user(Node, ServerRoot, Port, AuthPrefix, "open", "one", - "onePassword", []), - ok = update_password(Node, ServerRoot, Host, Port, AuthPrefix, "open", - "DummyPassword", "NoPassword"), - - %% Test /*open, require user one Aladdin - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "open"), - - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "one", "onePassword", Version, Host), Config, - [{statuscode, 401}]), - - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "two", "twoPassword", Version, Host), Config, - [{statuscode, 401}]), - - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "Aladdin", "onePassword", Version, Host), - Config, [{statuscode, 401}]), - - true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "one", - "onePassword", []), - true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "two", - "twoPassword", []), - true = add_user(Node, ServerRoot, Port, AuthPrefix, "open", "Aladdin", - "AladdinPassword", []), - {ok, [_|_]} = list_users(Node, ServerRoot, Host, Port, - AuthPrefix, "open"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "one", "WrongPassword", Version, Host), - Config, [{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "one", "onePassword", Version, Host), - Config, [{statuscode, 200}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "two", "twoPassword", Version, Host), - Config,[{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "Aladdin", "WrongPassword", Version, Host), - Config,[{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "open/", - "Aladdin", "AladdinPassword", Version, Host), - Config, [{statuscode, 200}]), - - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "open"), - {ok, []} = list_users(Node, ServerRoot, Host, Port, - AuthPrefix, "open"), - - %% Phase 2 - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), - {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthPrefix, - "secret"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "one", "onePassword", Version, Host), - Config, [{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "two", "twoPassword", Version, Host), - Config, [{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "three", "threePassword", Version, Host), - Config, [{statuscode, 401}]), - add_user(Node, ServerRoot, Port, AuthPrefix, "secret", "one", - "onePassword", - []), - add_user(Node, ServerRoot, Port, AuthPrefix, "secret", - "two", "twoPassword", []), - add_user(Node, ServerRoot, Port, AuthPrefix, "secret", "Aladdin", - "AladdinPassword",[]), - add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret", - "one", "group1"), - add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret", - "two", "group1"), - add_group_member(Node, ServerRoot, Port, AuthPrefix, - "secret", "Aladdin", "group2"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "one", "onePassword", Version, Host), - Config, [{statuscode, 200}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "two", "twoPassword", Version, Host), - Config,[{statuscode, 200}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "Aladdin", "AladdinPassword", Version, Host), - Config, [{statuscode, 200}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ "secret/", - "three", "threePassword", Version, Host), - Config, [{statuscode, 401}]), - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), - {ok, []} = list_users(Node, ServerRoot, Host, Port, - AuthPrefix, "secret"), - remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), - - {ok, []} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret"), - - %% Phase 3 - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), - remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), - - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", - "three", "threePassword", Version, Host), - Config, [{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", "two", "twoPassword", Version, Host), - Config, [{statuscode, 401}]), - add_user(Node, ServerRoot, Port, AuthPrefix, - "secret/top_secret","three", - "threePassword",[]), - add_user(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", - "two","twoPassword", []), - add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", "three", "group3"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", "three", "threePassword", - Version, Host), - Config, [{statuscode, 200}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", "two", "twoPassword", Version, Host), - Config, [{statuscode, 401}]), - add_group_member(Node, ServerRoot, Port, AuthPrefix, "secret/top_secret", "two", "group3"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", - "two", "twoPassword", Version, Host), - Config, [{statuscode, 200}]), - remove_users(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), - {ok, []} = list_users(Node, ServerRoot, Host, Port, - AuthPrefix, "secret/top_secret"), - remove_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), - {ok, []} = list_groups(Node, ServerRoot, Host, Port, AuthPrefix, "secret/top_secret"), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/", "two", "twoPassword", Version, Host), - Config, [{statuscode, 401}]), - ok = auth_status(auth_request("/" ++ AuthPrefix ++ - "secret/top_secret/","three", "threePassword", Version, Host), - Config, [{statuscde, 401}]). -%%------------------------------------------------------------------------- -ipv6() -> - [{require, ipv6_hosts}, - {doc,"Test ipv6."}]. -ipv6(Config) when is_list(Config) -> - {ok, Hostname0} = inet:gethostname(), - case lists:member(list_to_atom(Hostname0), ct:get_config(ipv6_hosts)) of - true -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - URI = http_request("GET / ", Version, Host), - httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), [inet6], - ?config(code, Config), - URI, - [{statuscode, 200}, {version, Version}]); - false -> - {skip, "Host does not support IPv6"} - end. - -%%------------------------------------------------------------------------- -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]). - -htaccess_1_0(Config) when is_list(Config) -> - htaccess([{http_version, "HTTP/1.0"} | Config]). - -htaccess_0_9(Config) when is_list(Config) -> - htaccess([{http_version, "HTTP/0.9"} | Config]). - -htaccess() -> - [{doc, "Test mod_auth API"}]. - -htaccess(Config) when is_list(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Type = ?config(type, Config), - Port = ?config(port, Config), - Node = ?config(node, Config), - %% Control that authentication required! - %% Control that the pages that shall be - %% authenticated really need authenticatin - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/open/ ", Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/secret/ ", Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/secret/top_secret/ ", - Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]), - - %% Make sure Authenticate header is received even the second time - %% we try a incorrect password! Otherwise a browser client will hang! - ok = auth_status(auth_request("/ht/open/", - "dummy", "WrongPassword", Version, Host), Config, - [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - ok = auth_status(auth_request("/ht/open/", - "dummy", "WrongPassword", Version, Host), Config, - [{statuscode, 401}, - {header, "WWW-Authenticate"}]), - - %% Control that not just the first user in the list is valid - %% Control the first user - %% Authennticating ["one:OnePassword" user first in user list] - ok = auth_status(auth_request("/ht/open/dummy.html", "one", "OnePassword", - Version, Host), Config, - [{statuscode, 200}]), - - %% Control the second user - %% Authentication OK and a directory listing is supplied! - %% ["Aladdin:open sesame" user second in user list] - ok = auth_status(auth_request("/ht/open/","Aladdin", - "AladdinPassword", Version, Host), Config, - [{statuscode, 200}]), - - %% Contro that bad passwords and userids get a good denial - %% User correct but wrong password! ["one:one" user first in user list] - ok = auth_status(auth_request("/ht/open/", "one", "one", Version, Host), Config, - [{statuscode, 401}]), - %% Neither user or password correct! ["dummy:dummy"] - ok = auth_status(auth_request("/ht/open/", "dummy", "dummy", Version, Host), Config, - [{statuscode, 401}]), - - %% Control that authetication still works, even if its a member in a group - %% Authentication OK! ["two:TwoPassword" user in first group] - ok = auth_status(auth_request("/ht/secret/dummy.html", "two", - "TwoPassword", Version, Host), Config, - [{statuscode, 200}]), - - %% Authentication OK and a directory listing is supplied! - %% ["three:ThreePassword" user in second group] - ok = auth_status(auth_request("/ht/secret/", "three", - "ThreePassword", Version, Host), Config, - [{statuscode, 200}]), - - %% Deny users with bad passwords even if the user is a group member - %% User correct but wrong password! ["two:two" user in first group] - ok = auth_status(auth_request("/ht/secret/", "two", "two", Version, Host), Config, - [{statuscode, 401}]), - %% Neither user or password correct! ["dummy:dummy"] - ok = auth_status(auth_request("/ht/secret/", "dummy", "dummy", Version, Host), Config, - [{statuscode, 401}]), - - %% control that we deny the users that are in subnet above the allowed - ok = auth_status(auth_request("/ht/blocknet/dummy.html", "four", - "FourPassword", Version, Host), Config, - [{statuscode, 403}]), - %% Control that we only applies the rules to the right methods - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("HEAD /ht/blocknet/dummy.html ", Version, Host), - [{statuscode, head_status(Version)}, - {version, Version}]), - - %% Control that the rerquire directive can be overrideen - ok = auth_status(auth_request("/ht/secret/top_secret/ ", "Aladdin", "AladdinPassword", - Version, Host), Config, - [{statuscode, 401}]), - - %% Authentication still required! - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/open/ ", Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/secret/ ", Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - http_request("GET /ht/secret/top_secret/ ", Version, Host), - [{statuscode, 401}, - {version, Version}, - {header, "WWW-Authenticate"}]). - -%%------------------------------------------------------------------------- -host() -> - [{doc, "Test host header"}]. - -host(Config) when is_list(Config) -> - Cb = ?config(version_cb, Config), - Cb:host(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config)). -%%------------------------------------------------------------------------- -chunked() -> - [{doc, "Check that the server accepts chunked requests."}]. - -chunked(Config) when is_list(Config) -> - httpd_1_1:chunked(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config)). -%%------------------------------------------------------------------------- -expect() -> - ["Check that the server handles request with the expect header " - "field appropiate"]. -expect(Config) when is_list(Config) -> - httpd_1_1:expect(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config)). -%%------------------------------------------------------------------------- -max_clients_1_1() -> - [{doc, "Test max clients limit"}]. - -max_clients_1_1(Config) when is_list(Config) -> - do_max_clients([{http_version, "HTTP/1.1"} | Config]). - -max_clients_1_0() -> - [{doc, "Test max clients limit"}]. - -max_clients_1_0(Config) when is_list(Config) -> - do_max_clients([{http_version, "HTTP/1.0"} | Config]). - -max_clients_0_9() -> - [{doc, "Test max clients limit"}]. - -max_clients_0_9(Config) when is_list(Config) -> - do_max_clients([{http_version, "HTTP/0.9"} | Config]). -%%------------------------------------------------------------------------- -esi() -> - [{doc, "Test mod_esi"}]. - -esi(Config) when is_list(Config) -> - ok = http_status("GET /eval?httpd_example:print(\"Hi!\") ", - Config, [{statuscode, 200}]), - ok = http_status("GET /eval?not_allowed:print(\"Hi!\") ", - Config, [{statuscode, 403}]), - ok = http_status("GET /eval?httpd_example:undef(\"Hi!\") ", - Config, [{statuscode, 500}]), - ok = http_status("GET /cgi-bin/erl/httpd_example ", - Config, [{statuscode, 400}]), - ok = http_status("GET /cgi-bin/erl/httpd_example:get ", - Config, [{statuscode, 200}]), - ok = http_status("GET /cgi-bin/erl/httpd_example:" - "get?input=4711 ", Config, - [{statuscode, 200}]), - ok = http_status("GET /cgi-bin/erl/httpd_example:post ", - Config, [{statuscode, 200}]), - ok = http_status("GET /cgi-bin/erl/not_allowed:post ", - Config, [{statuscode, 403}]), - ok = http_status("GET /cgi-bin/erl/httpd_example:undef ", - Config, [{statuscode, 404}]), - ok = http_status("GET /cgi-bin/erl/httpd_example/yahoo ", - Config, [{statuscode, 302}]), - %% Check "ErlScriptNoCache" directive (default: false) - ok = http_status("GET /cgi-bin/erl/httpd_example:get ", - Config, [{statuscode, 200}, - {no_header, "cache-control"}]). -%%------------------------------------------------------------------------- -cgi() -> - [{doc, "Test mod_cgi"}]. - -cgi(Config) when is_list(Config) -> - {Script, Script2, Script3} = - case test_server:os_type() of - {win32, _} -> - {"printenv.bat", "printenv.sh", "cgi_echo.exe"}; - _ -> - {"printenv.sh", "printenv.bat", "cgi_echo"} - end, - - %%The length (> 100) is intentional - ok = http_status("POST /cgi-bin/" ++ Script3 ++ " ", - {"Content-Length:100 \r\n", - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"}, - Config, - [{statuscode, 200}, - {header, "content-type", "text/plain"}]), - - ok = http_status("GET /cgi-bin/"++ Script ++ " ", Config, [{statuscode, 200}]), - - ok = http_status("GET /cgi-bin/not_there ", Config, - [{statuscode, 404}, {statuscode, 500}]), - - ok = http_status("GET /cgi-bin/"++ Script ++ "?Nisse:kkk?sss/lll ", - Config, - [{statuscode, 200}]), - - ok = http_status("POST /cgi-bin/"++ Script ++ " ", Config, - [{statuscode, 200}]), - - ok = http_status("GET /htbin/"++ Script ++ " ", Config, - [{statuscode, 200}]), - - ok = http_status("GET /htbin/not_there ", Config, - [{statuscode, 404},{statuscode, 500}]), - - ok = http_status("GET /htbin/"++ Script ++ "?Nisse:kkk?sss/lll ", Config, - [{statuscode, 200}]), - - ok = http_status("POST /htbin/"++ Script ++ " ", Config, - [{statuscode, 200}]), - - ok = http_status("POST /htbin/"++ Script ++ " ", Config, - [{statuscode, 200}]), - - %% Execute an existing, but bad CGI script.. - ok = http_status("POST /htbin/"++ Script2 ++ " ", Config, - [{statuscode, 404}]), - - ok = http_status("POST /cgi-bin/"++ Script2 ++ " ", Config, - [{statuscode, 404}]), - - %% Check "ScriptNoCache" directive (default: false) - ok = http_status("GET /cgi-bin/" ++ Script ++ " ", Config, - [{statuscode, 200}, - {no_header, "cache-control"}]). -%%------------------------------------------------------------------------- -cgi_chunked_encoding_test() -> - [{doc, "Test chunked encoding together with mod_cgi "}]. -cgi_chunked_encoding_test(Config) when is_list(Config) -> - Host = ?config(host, Config), - Script = - case test_server:os_type() of - {win32, _} -> - "/cgi-bin/printenv.bat"; - _ -> - "/cgi-bin/printenv.sh" - end, - Requests = - ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n", - "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:" - ++ Host ++"\r\n\r\n"], - httpd_1_1:mod_cgi_chunked_encoding_test(?config(type, Config), ?config(port, Config), - Host, - ?config(node, Config), - Requests). -%%------------------------------------------------------------------------- -alias() -> - [{doc, "Test mod_alias"}]. - -alias(Config) when is_list(Config) -> - ok = http_status("GET /pics/icon.sheet.gif ", Config, - [{statuscode, 200}, - {header, "Content-Type","image/gif"}, - {header, "Server"}, - {header, "Date"}]), - - ok = http_status("GET / ", Config, - [{statuscode, 200}, - {header, "Content-Type","text/html"}, - {header, "Server"}, - {header, "Date"}]), - - ok = http_status("GET /misc/ ", Config, - [{statuscode, 200}, - {header, "Content-Type","text/html"}, - {header, "Server"}, - {header, "Date"}]), - - %% Check redirection if trailing slash is missing. - ok = http_status("GET /misc ", Config, - [{statuscode, 301}, - {header, "Location"}, - {header, "Content-Type","text/html"}]). -%%------------------------------------------------------------------------- -actions() -> - [{doc, "Test mod_actions"}]. - -actions(Config) when is_list(Config) -> - ok = http_status("GET /", Config, [{statuscode, 200}]). - -%%------------------------------------------------------------------------- -range() -> - [{doc, "Test Range header"}]. - -range(Config) when is_list(Config) -> - httpd_1_1:range(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config)). - -%%------------------------------------------------------------------------- -if_modified_since() -> - [{doc, "Test If-Modified-Since header"}]. - -if_modified_since(Config) when is_list(Config) -> - httpd_1_1:if_test(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config), - ?config(doc_root, Config)). -%%------------------------------------------------------------------------- -trace() -> - [{doc, "Test TRACE method"}]. - -trace(Config) when is_list(Config) -> - Cb = ?config(version_cb, Config), - Cb:trace(?config(type, Config), ?config(port, Config), - ?config(host, Config), ?config(node, Config)). - -%%------------------------------------------------------------------------- -light() -> - ["Test light load"]. -light(Config) when is_list(Config) -> - httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), - ?config(node, Config), 10). -%%------------------------------------------------------------------------- -medium() -> - ["Test medium load"]. -medium(Config) when is_list(Config) -> - httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), - ?config(node, Config), 100). -%%------------------------------------------------------------------------- -heavy() -> - ["Test heavy load"]. -heavy(Config) when is_list(Config) -> - httpd_load:load_test(?config(type, Config), ?config(port, Config), ?config(host, Config), - ?config(node, Config), - 1000). -%%------------------------------------------------------------------------- -content_length() -> - ["Tests that content-length is correct OTP-5775"]. -content_length(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), ?config(node, Config), - http_request("GET /cgi-bin/erl/httpd_example:get_bin ", - Version, Host), - [{statuscode, 200}, - {content_length, 274}, - {version, Version}]). -%%------------------------------------------------------------------------- -bad_hex() -> - ["Tests that a URI with a bad hexadecimal code is handled OTP-6003"]. -bad_hex(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), ?config(node, Config), - http_request("GET http://www.erlang.org/%skalle ", - Version, Host), - [{statuscode, 400}, - {version, Version}]). -%%------------------------------------------------------------------------- -missing_CR() -> - ["Tests missing CR in delimiter OTP-7304"]. -missing_CR(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), ?config(node, Config), - http_request_missing_CR("GET /index.html ", Version, Host), - [{statuscode, 200}, - {version, Version}]). - -%%------------------------------------------------------------------------- -customize() -> - [{doc, "Test filtering of headers with custom callback"}]. - -customize(Config) when is_list(Config) -> - Version = "HTTP/1.1", - Host = ?config(host, Config), - Type = ?config(type, Config), - ok = httpd_test_lib:verify_request(?config(type, Config), Host, - ?config(port, Config), - transport_opts(Type, Config), - ?config(node, Config), - http_request("GET /index.html ", Version, Host), - [{statuscode, 200}, - {header, "Content-Type", "text/html"}, - {header, "Date"}, - {no_header, "Server"}, - {version, Version}]). - -response_header({"server", _}) -> - false; -response_header(Header) -> - {true, Header}. - -%%------------------------------------------------------------------------- -max_header() -> - ["Denial Of Service (DOS) attack, prevented by max_header"]. -max_header(Config) when is_list(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - case Version of - "HTTP/0.9" -> - {skip, not_implemented}; - _ -> - dos_hostname(?config(type, Config), ?config(port, Config), Host, - ?config(node, Config), Version, ?MAX_HEADER_SIZE) - end. - -%%------------------------------------------------------------------------- -max_content_length() -> - ["Denial Of Service (DOS) attack, prevented by max_content_length"]. -max_content_length(Config) when is_list(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - garbage_content_length(?config(type, Config), ?config(port, Config), Host, - ?config(node, Config), Version). - -%%------------------------------------------------------------------------- -security_1_1(Config) when is_list(Config) -> - security([{http_version, "HTTP/1.1"} | Config]). - -security_1_0(Config) when is_list(Config) -> - security([{http_version, "HTTP/1.0"} | Config]). - -security() -> - ["Test mod_security"]. -security(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Node = ?config(node, Config), - ServerRoot = ?config(server_root, Config), - - global:register_name(mod_security_test, self()), % Receive events - - test_server:sleep(5000), - - OpenDir = filename:join([ServerRoot, "htdocs", "open"]), - - %% Test blocking / unblocking of users. - - %% /open, require user one Aladdin - remove_users(Node, ServerRoot, Host, Port, "", "open"), - - ok = auth_status(auth_request("/open/", - "one", "onePassword", Version, Host), Config, - [{statuscode, 401}]), - - receive_security_event({event, auth_fail, Port, OpenDir, - [{user, "one"}, {password, "onePassword"}]}, - Node, Port), - - ok = auth_status(auth_request("/open/", - "two", "twoPassword", Version, Host), Config, - [{statuscode, 401}]), - - receive_security_event({event, auth_fail, Port, OpenDir, - [{user, "two"}, {password, "twoPassword"}]}, - Node, Port), - - ok = auth_status(auth_request("/open/", - "Aladdin", "AladdinPassword", Version, Host), - Config, [{statuscode, 401}]), - - receive_security_event({event, auth_fail, Port, OpenDir, - [{user, "Aladdin"}, - {password, "AladdinPassword"}]}, - Node, Port), - - add_user(Node, ServerRoot, Port, "", "open", "one", "onePassword", []), - add_user(Node, ServerRoot, Port, "", "open", "two", "twoPassword", []), - - ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, - [{statuscode, 401}]), - - receive_security_event({event, auth_fail, Port, OpenDir, - [{user, "one"}, {password, "WrongPassword"}]}, - Node, Port), - - ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, - [{statuscode, 401}]), - - receive_security_event({event, auth_fail, Port, OpenDir, - [{user, "one"}, {password, "WrongPassword"}]}, - Node, Port), - receive_security_event({event, user_block, Port, OpenDir, - [{user, "one"}]}, Node, Port), - - global:unregister_name(mod_security_test), % No more events. - - ok = auth_status(auth_request("/open/", "one", "WrongPassword", Version, Host), Config, - [{statuscode, 401}]), - - %% User "one" should be blocked now.. - case list_blocked_users(Node, Port) of - [{"one",_, Port, OpenDir,_}] -> - ok; - Blocked -> - ct:fail({unexpected_blocked, Blocked}) - end, - - [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir), - - true = unblock_user(Node, "one", Port, OpenDir), - %% User "one" should not be blocked any more. - - [] = list_blocked_users(Node, Port), - - ok = auth_status(auth_request("/open/", "one", "onePassword", Version, Host), Config, - [{statuscode, 200}]), - - %% Test list_auth_users & auth_timeout - - ["one"] = list_auth_users(Node, Port), - - ok = auth_status(auth_request("/open/", "two", "onePassword", Version, Host), Config, - [{statuscode, 401}]), - - ["one"] = list_auth_users(Node, Port), - - - ["one"] = list_auth_users(Node, Port, OpenDir), - - - ok = auth_status(auth_request("/open/", "two", "twoPassword", Version, Host), Config, - [{statuscode, 401}]), - - ["one"] = list_auth_users(Node, Port), - - - ["one"] = list_auth_users(Node, Port, OpenDir), - - %% Wait for successful auth to timeout. - test_server:sleep(?AUTH_TIMEOUT*1001), - - [] = list_auth_users(Node, Port), - - [] = list_auth_users(Node, Port, OpenDir), - - %% "two" is blocked. - - true = unblock_user(Node, "two", Port, OpenDir), - - - %% Test explicit blocking. Block user 'two'. - - [] = list_blocked_users(Node,Port,OpenDir), - - true = block_user(Node, "two", Port, OpenDir, 10), - - ok = auth_status(auth_request("/open/", "two", "twoPassword", Version, Host), Config, - [{statuscode, 401}]), - - true = unblock_user(Node, "two", Port, OpenDir). - -%%------------------------------------------------------------------------- -non_disturbing_reconfiger_dies(Config) when is_list(Config) -> - do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], non_disturbing). -disturbing_reconfiger_dies(Config) when is_list(Config) -> - do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], disturbing). - -do_reconfiger_dies(Config, DisturbingType) -> - Server = ?config(server_pid, Config), - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Type = ?config(type, Config), - - HttpdConfig = httpd:info(Server), - BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), - {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), - inets_test_lib:send(Type, Socket, BlockRequest), - ct:sleep(100), %% Avoid possible timing issues - Pid = spawn(fun() -> httpd:reload_config([{server_name, "httpd_kill_" ++ Version}, - {port, Port}| - proplists:delete(server_name, HttpdConfig)], DisturbingType) - end), - - monitor(process, Pid), - exit(Pid, kill), - receive - {'DOWN', _, _, _, _} -> - ok - end, - inets_test_lib:close(Type, Socket), - [{server_name, "httpd_test"}] = httpd:info(Server, [server_name]). -%%------------------------------------------------------------------------- -disturbing_1_1(Config) when is_list(Config) -> - disturbing([{http_version, "HTTP/1.1"} | Config]). - -disturbing_1_0(Config) when is_list(Config) -> - disturbing([{http_version, "HTTP/1.0"} | Config]). - -disturbing_0_9(Config) when is_list(Config) -> - disturbing([{http_version, "HTTP/0.9"} | Config]). - -disturbing(Config) when is_list(Config)-> - Server = ?config(server_pid, Config), - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Type = ?config(type, Config), - HttpdConfig = httpd:info(Server), - BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), - {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), - inets_test_lib:send(Type, Socket, BlockRequest), - ct:sleep(100), %% Avoid possible timing issues - ok = httpd:reload_config([{server_name, "httpd_disturbing_" ++ Version}, {port, Port}| - proplists:delete(server_name, HttpdConfig)], disturbing), - Close = list_to_atom((typestr(Type)) ++ "_closed"), - receive - {Close, Socket} -> - ok; - Msg -> - ct:fail({{expected, {Close, Socket}}, {got, Msg}}) - end, - inets_test_lib:close(Type, Socket), - [{server_name, "httpd_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). -%%------------------------------------------------------------------------- -non_disturbing_1_1(Config) when is_list(Config) -> - non_disturbing([{http_version, "HTTP/1.1"} | Config]). - -non_disturbing_1_0(Config) when is_list(Config) -> - non_disturbing([{http_version, "HTTP/1.0"} | Config]). - -non_disturbing_0_9(Config) when is_list(Config) -> - non_disturbing([{http_version, "HTTP/0.9"} | Config]). - -non_disturbing(Config) when is_list(Config)-> - Server = ?config(server_pid, Config), - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Type = ?config(type, Config), - - HttpdConfig = httpd:info(Server), - BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), - {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), - inets_test_lib:send(Type, Socket, BlockRequest), - ct:sleep(100), %% Avoid possible timing issues - ok = httpd:reload_config([{server_name, "httpd_non_disturbing_" ++ Version}, {port, Port}| - proplists:delete(server_name, HttpdConfig)], non_disturbing), - Transport = type(Type), - receive - {Transport, Socket, Msg} -> - ct:pal("Received message ~p~n", [Msg]), - ok - after 2000 -> - ct:fail(timeout) - end, - inets_test_lib:close(Type, Socket), - [{server_name, "httpd_non_disturbing_" ++ Version}] = httpd:info(Server, [server_name]). - - -%%-------------------------------------------------------------------- -%% Internal functions ----------------------------------- -%%-------------------------------------------------------------------- -url(http, End, Config) -> - Port = ?config(port, Config), - {ok,Host} = inet:gethostname(), - ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End. - -do_max_clients(Config) -> - Version = ?config(http_version, Config), - Host = ?config(host, Config), - Port = ?config(port, Config), - Type = ?config(type, Config), - - Request = http_request("GET /index.html ", Version, Host), - BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host), - {ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)), - inets_test_lib:send(Type, Socket, BlockRequest), - ct:sleep(100), %% Avoid possible timing issues - ok = httpd_test_lib:verify_request(Type, Host, - Port, - transport_opts(Type, Config), - ?config(node, Config), - Request, - [{statuscode, 503}, - {version, Version}]), - receive - {_, Socket, _Msg} -> - ok - end, - inets_test_lib:close(Type, Socket), - ct:sleep(100), %% Avoid possible timing issues - ok = httpd_test_lib:verify_request(Type, Host, - Port, - transport_opts(Type, Config), - ?config(node, Config), - Request, - [{statuscode, 200}, - {version, Version}]). - -setup_server_dirs(ServerRoot, DocRoot, DataDir) -> - CgiDir = filename:join(ServerRoot, "cgi-bin"), - AuthDir = filename:join(ServerRoot, "auth"), - PicsDir = filename:join(ServerRoot, "icons"), - - ok = file:make_dir(ServerRoot), - ok = file:make_dir(DocRoot), - ok = file:make_dir(CgiDir), - ok = file:make_dir(AuthDir), - ok = file:make_dir(PicsDir), - - DocSrc = filename:join(DataDir, "server_root/htdocs"), - AuthSrc = filename:join(DataDir, "server_root/auth"), - CgiSrc = filename:join(DataDir, "server_root/cgi-bin"), - PicsSrc = filename:join(DataDir, "server_root/icons"), - - inets_test_lib:copy_dirs(DocSrc, DocRoot), - inets_test_lib:copy_dirs(AuthSrc, AuthDir), - inets_test_lib:copy_dirs(CgiSrc, CgiDir), - inets_test_lib:copy_dirs(PicsSrc, PicsDir), - - Cgi = case test_server:os_type() of - {win32, _} -> - "cgi_echo.exe"; - _ -> - "cgi_echo" - end, - - inets_test_lib:copy_file(Cgi, DataDir, CgiDir), - AbsCgi = filename:join([CgiDir, Cgi]), - {ok, FileInfo} = file:read_file_info(AbsCgi), - ok = file:write_file_info(AbsCgi, FileInfo#file_info{mode = 8#00755}), - - EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]), - {ok, FileInfo1} = file:read_file_info(EnvCGI), - ok = file:write_file_info(EnvCGI, - FileInfo1#file_info{mode = 8#00755}). - -start_apps(Group) when Group == https_basic; - Group == https_limit; - Group == https_custom; - Group == https_basic_auth; - Group == https_auth_api; - Group == https_auth_api_dets; - Group == https_auth_api_mnesia; - Group == https_htaccess; - Group == https_security; - Group == https_reload - -> - inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]); -start_apps(Group) when Group == http_basic; - Group == http_limit; - Group == http_custom; - Group == http_basic_auth; - Group == http_auth_api; - Group == http_auth_api_dets; - Group == http_auth_api_mnesia; - Group == http_htaccess; - Group == http_security; - Group == http_reload-> inets_test_lib:start_apps([inets]). server_start(_, HttpdConfig) -> @@ -1454,6 +188,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_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_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 38d46cc6fd..f52347e39e 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.10.9 +INETS_VSN = 6.0 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" |