aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/inets/doc/src/httpd_custom_api.xml14
-rw-r--r--lib/inets/doc/src/notes.xml33
-rw-r--r--lib/inets/src/http_server/Makefile12
-rw-r--r--lib/inets/src/http_server/httpd_custom.erl31
-rw-r--r--lib/inets/src/http_server/httpd_custom_api.erl31
-rw-r--r--lib/inets/src/http_server/httpd_response.erl21
-rw-r--r--lib/inets/src/http_server/mod_auth_server.erl2
-rw-r--r--lib/inets/src/http_server/mod_security_server.erl4
-rw-r--r--lib/inets/test/httpd_SUITE.erl38
-rw-r--r--lib/inets/test/httpd_test_lib.erl4
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/notes.xml18
-rw-r--r--lib/mnesia/src/mnesia_bup.erl14
-rw-r--r--lib/mnesia/test/mnesia_evil_backup.erl10
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--otp_versions.table1
16 files changed, 204 insertions, 33 deletions
diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml
index 23417900fa..d2e5441895 100644
--- a/lib/inets/doc/src/httpd_custom_api.xml
+++ b/lib/inets/doc/src/httpd_custom_api.xml
@@ -33,6 +33,20 @@
</description>
<funcs>
+ <func>
+ <name>response_default_headers() -> [Header] </name>
+ <fsummary>Provide default headers for the HTTP servers responses.</fsummary>
+ <type>
+ <v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
+ <d>string:to_lower/1 will be performed on the HeaderName</d>
+ </type>
+ <desc>
+ <p>Provide default headers for the HTTP servers responses. Note that this
+ option may override built-in defaults.
+ </p>
+ </desc>
+ </func>
+
<func>
<name>response_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
<fsummary>Filter and possible alter HTTP response headers.</fsummary>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index eb1027b028..ef11fdc10c 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,38 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.0.1</title>
+ <section><title>Inets 6.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Avoid crash in mod_auth_server and mod_security_server
+ due to using an atom instead of a string when creating a
+ name.</p>
+ <p>
+ Own Id: OTP-13022</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add function response_default_headers/0 to httpd
+ customize API, to allow user to specify default values
+ for HTTP response headers.</p>
+ <p>
+ Own Id: OTP-13013</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.0.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index b09877550d..b9f2290289 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -40,6 +40,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
+
+BEHAVIOUR_MODULES= \
+ httpd_custom_api
+
MODULES = \
httpd \
httpd_acceptor \
@@ -86,10 +90,13 @@ MODULES = \
HRL_FILES = httpd.hrl httpd_internal.hrl mod_auth.hrl
-ERL_FILES = $(MODULES:%=%.erl)
+ERL_FILES = $(MODULES:%=%.erl)\
+ $(BEHAVIOUR_MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
INETS_FLAGS = -D'SERVER_SOFTWARE="$(APPLICATION)/$(VSN)"'
@@ -109,11 +116,12 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
debug opt: $(TARGET_FILES)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES)
rm -f core
docs:
diff --git a/lib/inets/src/http_server/httpd_custom.erl b/lib/inets/src/http_server/httpd_custom.erl
index a1fe058bd1..2b9701ef75 100644
--- a/lib/inets/src/http_server/httpd_custom.erl
+++ b/lib/inets/src/http_server/httpd_custom.erl
@@ -20,16 +20,27 @@
%%
-module(httpd_custom).
--export([response_header/1, request_header/1]).
--export([customize_headers/3]).
+-export([response_header/1, request_header/1, response_default_headers/0]).
+-export([customize_headers/3, response_default_headers/1]).
--include_lib("inets/src/inets_app/inets_internal.hrl").
+-include("../inets_app/inets_internal.hrl").
+
+-behaviour(httpd_custom_api).
+
+%%--------------------------------------------------------------------
+%% Behavior API -----------------------------------
+%%--------------------------------------------------------------------
response_header(Header) ->
{true, httpify(Header)}.
request_header(Header) ->
{true, Header}.
+response_default_headers() ->
+ [].
+%%--------------------------------------------------------------------
+%% Internal API -----------------------------------
+%%--------------------------------------------------------------------
customize_headers(?MODULE, Function, Arg) ->
?MODULE:Function(Arg);
customize_headers(Module, Function, Arg) ->
@@ -43,6 +54,20 @@ customize_headers(Module, Function, Arg) ->
?MODULE:Function(Arg)
end.
+response_default_headers(?MODULE) ->
+ response_default_headers();
+response_default_headers(Module) ->
+ try Module:response_default_headers() of
+ Defaults ->
+ [{http_util:to_lower(Key), Value} || {Key, Value} <- Defaults,
+ is_list(Key), is_list(Value)]
+ catch
+ _:_ ->
+ ?MODULE:response_default_headers()
+ end.
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------
+%%--------------------------------------------------------------------
httpify({Key0, Value}) ->
%% make sure first letter is capital (defacto standard)
Words1 = string:tokens(Key0, "-"),
diff --git a/lib/inets/src/http_server/httpd_custom_api.erl b/lib/inets/src/http_server/httpd_custom_api.erl
new file mode 100644
index 0000000000..282f3a6ee6
--- /dev/null
+++ b/lib/inets/src/http_server/httpd_custom_api.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(httpd_custom_api).
+
+-callback response_default_headers() ->
+ [{Key::string(), Value::string()}].
+-callback response_header({Key::string(), Value::string()}) ->
+ {true, {Key::string(), Value::string()}} | false.
+-callback request_header({Key::string(), Value::string()}) ->
+ {true, {Key::string(), Value::string()}} | false.
+
+-optional_callbacks([response_default_headers/0, response_header/1,
+ request_header/1]).
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 7e73da7060..71243f525a 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -287,14 +287,21 @@ create_header(ConfigDb, KeyValueTupleHeaders) ->
Date = httpd_util:rfc1123_date(),
ContentType = "text/html",
Server = server(ConfigDb),
- Headers0 = add_default_headers([{"date", Date},
- {"content-type", ContentType}
- | if Server=="" -> [];
- true -> [{"server", Server}]
- end
- ],
- KeyValueTupleHeaders),
CustomizeCB = httpd_util:lookup(ConfigDb, customize, httpd_custom),
+
+ CustomDefaults = httpd_custom:response_default_headers(CustomizeCB),
+ SystemDefaultes = ([{"date", Date},
+ {"content-type", ContentType}
+ | if Server=="" -> [];
+ true -> [{"server", Server}]
+ end
+ ]),
+
+ %% System defaults not present in custom defaults will be added
+ %% to defaults
+ Defaults = add_default_headers(SystemDefaultes, CustomDefaults),
+
+ Headers0 = add_default_headers(Defaults, KeyValueTupleHeaders),
lists:filtermap(fun(H) ->
httpd_custom:customize_headers(CustomizeCB, response_header, H)
end,
diff --git a/lib/inets/src/http_server/mod_auth_server.erl b/lib/inets/src/http_server/mod_auth_server.erl
index 3685c2e617..7d1e1a3431 100644
--- a/lib/inets/src/http_server/mod_auth_server.erl
+++ b/lib/inets/src/http_server/mod_auth_server.erl
@@ -316,7 +316,7 @@ lookup(Db, Key) ->
make_name(Addr, Port, Profile) ->
- httpd_util:make_name(?MODULE, Addr, Port, Profile).
+ httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile).
call(Name, Req) ->
diff --git a/lib/inets/src/http_server/mod_security_server.erl b/lib/inets/src/http_server/mod_security_server.erl
index 81561493a0..f9281b0fdc 100644
--- a/lib/inets/src/http_server/mod_security_server.erl
+++ b/lib/inets/src/http_server/mod_security_server.erl
@@ -523,10 +523,10 @@ unblock_user(Info, User, Dir, Addr, Port, Profile, ETS, DETS, CBModule) ->
ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Profile, Dir, '_'}}).
make_name(Addr,Port, Profile) ->
- httpd_util:make_name(?MODULE,Addr,Port, Profile).
+ httpd_util:make_name(?MODULE_STRING, Addr, Port, Profile).
make_name(Addr,Port, Profile, Num) ->
- httpd_util:make_name(?MODULE,Addr,Port,
+ httpd_util:make_name(?MODULE_STRING, Addr,Port,
atom_to_list(Profile) ++ "__" ++ integer_to_list(Num)).
auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index a6236f828a..b50d31a5c1 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -97,7 +97,7 @@ groups() ->
{https_reload, [], [{group, reload}]},
{http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
{limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
- {custom, [], [customize]},
+ {custom, [], [customize, add_default]},
{reload, [], [non_disturbing_reconfiger_dies,
disturbing_reconfiger_dies,
non_disturbing_1_1,
@@ -1003,10 +1003,23 @@ customize(Config) when is_list(Config) ->
{no_header, "Server"},
{version, Version}]).
-response_header({"server", _}) ->
- false;
-response_header(Header) ->
- {true, Header}.
+add_default() ->
+ [{doc, "Test adding default header with custom callback"}].
+
+add_default(Config) when is_list(Config) ->
+ Version = "HTTP/1.1",
+ Host = ?config(host, Config),
+ Type = ?config(type, Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config),
+ transport_opts(Type, Config),
+ ?config(node, Config),
+ http_request("GET /index.html ", Version, Host),
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date", "Override-date"},
+ {header, "X-Frame-Options"},
+ {version, Version}]).
%%-------------------------------------------------------------------------
max_header() ->
@@ -1425,9 +1438,9 @@ server_config(http_limit, Config) ->
%% Make sure option checking code is run
{max_content_length, 100000002}] ++ server_config(http, Config);
server_config(http_custom, Config) ->
- [{custom, ?MODULE}] ++ server_config(http, Config);
+ [{customize, ?MODULE}] ++ server_config(http, Config);
server_config(https_custom, Config) ->
- [{custom, ?MODULE}] ++ server_config(https, Config);
+ [{customize, ?MODULE}] ++ server_config(https, Config);
server_config(https_limit, Config) ->
[{max_clients, 1}] ++ server_config(https, Config);
server_config(http_basic_auth, Config) ->
@@ -2030,3 +2043,14 @@ typestr(ip_comm) ->
"tcp";
typestr(_) ->
"ssl".
+
+response_header({"server", _}) ->
+ false;
+response_header(Header) ->
+ {true, Header}.
+
+response_default_headers() ->
+ [%% Add new header
+ {"X-Frame-Options", "SAMEORIGIN"},
+ %% Override built-in default
+ {"Date", "Override-date"}].
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index cb2e86c81e..a5b836f651 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -294,9 +294,9 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) ->
{value, {LowerHeaderField, Value}} ->
ok;
false ->
- ct:fail({wrong_header_field_value, LowerHeaderField, Header});
+ ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value});
_ ->
- ct:fail({wrong_header_field_value, LowerHeaderField, Header})
+ ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value})
end,
do_validate(Header, Rest, N, P);
do_validate(Header,[{no_header, HeaderField}|Rest],N,P) ->
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index a6aeedfe12..480caeca4b 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.0.1
+INETS_VSN = 6.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 3b35a9879b..8650e03a60 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -39,7 +39,23 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.13.1</title>
+ <section><title>Mnesia 4.13.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a process and file descriptor leak in
+ mnesia:restore/2.</p>
+ <p>
+ Own Id: OTP-13025 Aux Id: seq12957 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.13.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 0e653f2bc4..1f150ae38b 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -157,10 +157,11 @@ fallback_to_schema(Fname) ->
read_schema(Mod, Opaque) ->
R = #restore{bup_module = Mod, bup_data = Opaque},
try read_schema_section(R) of
- {_, {_Header, Schema, _}} -> Schema
+ {R2, {_Header, Schema, _}} ->
+ close_read(R2),
+ Schema
catch throw:{error,_} = Error ->
Error
- after close_read(R)
end.
%% Open backup media and extract schema
@@ -173,8 +174,13 @@ read_schema_section(R) ->
do_read_schema_section(R) ->
R2 = safe_apply(R, open_read, [R#restore.bup_data]),
- {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
- do_read_schema_section(R3, verify_header(RawSchema), []).
+ try
+ {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
+ do_read_schema_section(R3, verify_header(RawSchema), [])
+ catch T:E ->
+ close_read(R2),
+ erlang:raise(T,E,erlang:get_stacktrace())
+ end.
do_read_schema_section(R, {ok, B, C, []}, Acc) ->
case safe_apply(R, read, [R#restore.bup_data]) of
diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl
index 89f2861661..e605fa7926 100644
--- a/lib/mnesia/test/mnesia_evil_backup.erl
+++ b/lib/mnesia/test/mnesia_evil_backup.erl
@@ -232,7 +232,13 @@ restore(Config, Op) ->
Res21 = [{Tab2, N, N+1} || N <- lists:seq(1, 11)],
Res31 = [[{Tab3, N, N+1}, {Tab3, N, N+44}] || N <- lists:seq(1, 10)],
-
+ Check = fun() ->
+ [disk_log:pid2name(X) ||
+ X <- processes(), Data <- [process_info(X, [current_function])],
+ Data =/= undefined,
+ element(1, element(2, lists:keyfind(current_function, 1, Data)))=:= disk_log]
+ end,
+ Before = Check(),
?match({atomic, [Tab1]}, Restore(File1, [{Op, [Tab1]},
{skip_tables, Tabs -- [Tab1]}])),
case Op of
@@ -319,6 +325,8 @@ restore(Config, Op) ->
end,
?match(ok, file:delete(File1)),
?match(ok, file:delete(File2)),
+ ?match([], Check() -- Before),
+
?verify_mnesia(Nodes, []).
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index e27045e16f..0fe5b5db8b 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.13.1
+MNESIA_VSN = 4.13.2
diff --git a/otp_versions.table b/otp_versions.table
index 949441e328..9fc40a9a36 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,4 @@
+OTP-18.1.1 : inets-6.0.2 mnesia-4.13.2 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 jinterface-1.6 kernel-4.1 megaco-3.18 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssh-4.1 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
OTP-18.1 : compiler-6.0.1 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 erts-7.1 eunit-2.2.11 hipe-3.13 inets-6.0.1 kernel-4.1 mnesia-4.13.1 odbc-2.11.1 public_key-1.0.1 sasl-2.6 ssh-4.1 ssl-7.1 stdlib-2.6 tools-2.8.1 wx-1.5 # asn1-4.0 common_test-1.11 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 gs-1.6 ic-4.4 jinterface-1.6 megaco-3.18 observer-2.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 reltool-0.7 runtime_tools-1.9.1 snmp-5.2 syntax_tools-1.7 test_server-3.9 typer-0.9.9 webtool-0.9 xmerl-1.3.8 :
OTP-18.0.3 : erts-7.0.3 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9.1 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :
OTP-18.0.2 : erts-7.0.2 runtime_tools-1.9.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :