aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-11-18 13:39:10 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-11-18 13:39:10 +0300
commitf57f267c542a8e6ddbb31cb3ba05c4fd3798f998 (patch)
tree4322c5f5b94f4d4f657aaa2199fc963cfc485bc8
parentMake common tests working again (diff)
parentAdd auth to mod_http_fileserver (diff)
Merge branch 'master' of github.com:processone/ejabberd
Conflicts: test/ejabberd_SUITE.erl
-rw-r--r--.gitignore1
-rw-r--r--asn1/ELDAPv3.asn1~301
-rw-r--r--include/ejabberd_commands.hrl7
-rw-r--r--rebar.config4
-rw-r--r--src/ejabberd_app.erl1
-rw-r--r--src/ejabberd_oauth.erl2
-rw-r--r--src/ext_mod.erl8
-rw-r--r--src/http_p1.erl358
-rw-r--r--src/mod_admin_extra.erl4
-rw-r--r--src/mod_http_api.erl8
-rw-r--r--src/mod_http_fileserver.erl88
-rw-r--r--src/mod_ip_blacklist.erl4
-rw-r--r--src/mod_muc_room.erl1
-rw-r--r--src/mod_proxy65.erl6
-rw-r--r--src/mod_pubsub.erl7
-rw-r--r--src/mod_register.erl9
-rw-r--r--src/node_flat.erl2
-rw-r--r--src/node_flat_sql.erl2
-rw-r--r--src/pubsub_subscription.erl4
-rw-r--r--src/pubsub_subscription_sql.erl4
-rw-r--r--src/rest.erl39
-rw-r--r--src/str.erl11
-rw-r--r--test/suite.erl15
-rw-r--r--test/suite.hrl3
24 files changed, 146 insertions, 743 deletions
diff --git a/.gitignore b/.gitignore
index bf5fe2863..38d6d77f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@
/doc/version.tex
/ebin/
/ejabberd.init
+/ejabberd.service
/ejabberdctl.example
XmppAddr.hrl
/rel/ejabberd/
diff --git a/asn1/ELDAPv3.asn1~ b/asn1/ELDAPv3.asn1~
deleted file mode 100644
index 1fec35cd8..000000000
--- a/asn1/ELDAPv3.asn1~
+++ /dev/null
@@ -1,301 +0,0 @@
--- LDAPv3 ASN.1 specification, taken from RFC 2251
-
--- Lightweight-Directory-Access-Protocol-V3 DEFINITIONS
-ELDAPv3 DEFINITIONS
-IMPLICIT TAGS ::=
-
-BEGIN
-
-LDAPMessage ::= SEQUENCE {
- messageID MessageID,
- protocolOp CHOICE {
- bindRequest BindRequest,
- bindResponse BindResponse,
- unbindRequest UnbindRequest,
- searchRequest SearchRequest,
- searchResEntry SearchResultEntry,
- searchResDone SearchResultDone,
- searchResRef SearchResultReference,
- modifyRequest ModifyRequest,
- modifyResponse ModifyResponse,
- addRequest AddRequest,
- addResponse AddResponse,
- delRequest DelRequest,
- delResponse DelResponse,
- modDNRequest ModifyDNRequest,
- modDNResponse ModifyDNResponse,
- compareRequest CompareRequest,
- compareResponse CompareResponse,
- abandonRequest AbandonRequest,
- extendedReq ExtendedRequest,
- extendedResp ExtendedResponse },
- controls [0] Controls OPTIONAL }
-
-MessageID ::= INTEGER (0 .. maxInt)
-
-maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
-
-LDAPString ::= OCTET STRING
-
-LDAPOID ::= OCTET STRING
-
-LDAPDN ::= LDAPString
-
-RelativeLDAPDN ::= LDAPString
-
-AttributeType ::= LDAPString
-
-AttributeDescription ::= LDAPString
-
-
-
-
--- Wahl, et. al. Standards Track [Page 44]
---
--- RFC 2251 LDAPv3 December 1997
-
-
-AttributeDescriptionList ::= SEQUENCE OF
- AttributeDescription
-
-AttributeValue ::= OCTET STRING
-
-AttributeValueAssertion ::= SEQUENCE {
- attributeDesc AttributeDescription,
- assertionValue AssertionValue }
-
-AssertionValue ::= OCTET STRING
-
-Attribute ::= SEQUENCE {
- type AttributeDescription,
- vals SET OF AttributeValue }
-
-MatchingRuleId ::= LDAPString
-
-LDAPResult ::= SEQUENCE {
- resultCode ENUMERATED {
- success (0),
- operationsError (1),
- protocolError (2),
- timeLimitExceeded (3),
- sizeLimitExceeded (4),
- compareFalse (5),
- compareTrue (6),
- authMethodNotSupported (7),
- strongAuthRequired (8),
- -- 9 reserved --
- referral (10), -- new
- adminLimitExceeded (11), -- new
- unavailableCriticalExtension (12), -- new
- confidentialityRequired (13), -- new
- saslBindInProgress (14), -- new
- noSuchAttribute (16),
- undefinedAttributeType (17),
- inappropriateMatching (18),
- constraintViolation (19),
- attributeOrValueExists (20),
- invalidAttributeSyntax (21),
- -- 22-31 unused --
- noSuchObject (32),
- aliasProblem (33),
- invalidDNSyntax (34),
- -- 35 reserved for undefined isLeaf --
- aliasDereferencingProblem (36),
- -- 37-47 unused --
- inappropriateAuthentication (48),
-
--- Wahl, et. al. Standards Track [Page 45]
---
--- RFC 2251 LDAPv3 December 1997
-
-
- invalidCredentials (49),
- insufficientAccessRights (50),
- busy (51),
- unavailable (52),
- unwillingToPerform (53),
- loopDetect (54),
- -- 55-63 unused --
- namingViolation (64),
- objectClassViolation (65),
- notAllowedOnNonLeaf (66),
- notAllowedOnRDN (67),
- entryAlreadyExists (68),
- objectClassModsProhibited (69),
- -- 70 reserved for CLDAP --
- affectsMultipleDSAs (71), -- new
- -- 72-79 unused --
- other (80) },
- -- 81-90 reserved for APIs --
- matchedDN LDAPDN,
- errorMessage LDAPString,
- referral [3] Referral OPTIONAL }
-
-Referral ::= SEQUENCE OF LDAPURL
-
-LDAPURL ::= LDAPString -- limited to characters permitted in URLs
-
-Controls ::= SEQUENCE OF Control
-
-Control ::= SEQUENCE {
- controlType LDAPOID,
- criticality BOOLEAN DEFAULT FALSE,
- controlValue OCTET STRING OPTIONAL }
-
-BindRequest ::= [APPLICATION 0] SEQUENCE {
- version INTEGER (1 .. 127),
- name LDAPDN,
- authentication AuthenticationChoice }
-
-AuthenticationChoice ::= CHOICE {
- simple [0] OCTET STRING,
- -- 1 and 2 reserved
- sasl [3] SaslCredentials }
-
-SaslCredentials ::= SEQUENCE {
- mechanism LDAPString,
- credentials OCTET STRING OPTIONAL }
-
-BindResponse ::= [APPLICATION 1] SEQUENCE {
-
--- Wahl, et. al. Standards Track [Page 46]
---
--- RFC 2251 LDAPv3 December 1997
-
-
- COMPONENTS OF LDAPResult,
- serverSaslCreds [7] OCTET STRING OPTIONAL }
-
-UnbindRequest ::= [APPLICATION 2] NULL
-
-SearchRequest ::= [APPLICATION 3] SEQUENCE {
- baseObject LDAPDN,
- scope ENUMERATED {
- baseObject (0),
- singleLevel (1),
- wholeSubtree (2) },
- derefAliases ENUMERATED {
- neverDerefAliases (0),
- derefInSearching (1),
- derefFindingBaseObj (2),
- derefAlways (3) },
- sizeLimit INTEGER (0 .. maxInt),
- timeLimit INTEGER (0 .. maxInt),
- typesOnly BOOLEAN,
- filter Filter,
- attributes AttributeDescriptionList }
-
-Filter ::= CHOICE {
- and [0] SET OF Filter,
- or [1] SET OF Filter,
- not [2] Filter,
- equalityMatch [3] AttributeValueAssertion,
- substrings [4] SubstringFilter,
- greaterOrEqual [5] AttributeValueAssertion,
- lessOrEqual [6] AttributeValueAssertion,
- present [7] AttributeDescription,
- approxMatch [8] AttributeValueAssertion,
- extensibleMatch [9] MatchingRuleAssertion }
-
-SubstringFilter ::= SEQUENCE {
- type AttributeDescription,
- -- at least one must be present
- substrings SEQUENCE OF CHOICE {
- initial [0] LDAPString,
- any [1] LDAPString,
- final [2] LDAPString } }
-
-MatchingRuleAssertion ::= SEQUENCE {
- matchingRule [1] MatchingRuleId OPTIONAL,
- type [2] AttributeDescription OPTIONAL,
- matchValue [3] AssertionValue,
- dnAttributes [4] BOOLEAN DEFAULT FALSE }
-
--- Wahl, et. al. Standards Track [Page 47]
---
--- RFC 2251 LDAPv3 December 1997
-
-SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
- objectName LDAPDN,
- attributes PartialAttributeList }
-
-PartialAttributeList ::= SEQUENCE OF SEQUENCE {
- type AttributeDescription,
- vals SET OF AttributeValue }
-
-SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
-
-SearchResultDone ::= [APPLICATION 5] LDAPResult
-
-ModifyRequest ::= [APPLICATION 6] SEQUENCE {
- object LDAPDN,
- modification SEQUENCE OF SEQUENCE {
- operation ENUMERATED {
- add (0),
- delete (1),
- replace (2) },
- modification AttributeTypeAndValues } }
-
-AttributeTypeAndValues ::= SEQUENCE {
- type AttributeDescription,
- vals SET OF AttributeValue }
-
-ModifyResponse ::= [APPLICATION 7] LDAPResult
-
-AddRequest ::= [APPLICATION 8] SEQUENCE {
- entry LDAPDN,
- attributes AttributeList }
-
-AttributeList ::= SEQUENCE OF SEQUENCE {
- type AttributeDescription,
- vals SET OF AttributeValue }
-
-AddResponse ::= [APPLICATION 9] LDAPResult
-
-DelRequest ::= [APPLICATION 10] LDAPDN
-
-DelResponse ::= [APPLICATION 11] LDAPResult
-
-ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
- entry LDAPDN,
- newrdn RelativeLDAPDN,
- deleteoldrdn BOOLEAN,
- newSuperior [0] LDAPDN OPTIONAL }
-
-ModifyDNResponse ::= [APPLICATION 13] LDAPResult
-
--- Wahl, et. al. Standards Track [Page 48]
---
--- RFC 2251 LDAPv3 December 1997
-
-
-CompareRequest ::= [APPLICATION 14] SEQUENCE {
- entry LDAPDN,
- ava AttributeValueAssertion }
-
-CompareResponse ::= [APPLICATION 15] LDAPResult
-
-AbandonRequest ::= [APPLICATION 16] MessageID
-
-ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
- requestName [0] LDAPOID,
- requestValue [1] OCTET STRING OPTIONAL }
-
-ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
- COMPONENTS OF LDAPResult,
- responseName [10] LDAPOID OPTIONAL,
- response [11] OCTET STRING OPTIONAL }
-
-passwdModifyOID LDAPOID ::= "1.3.6.1.4.1.4203.1.11.1"
-
-PasswdModifyRequestValue ::= SEQUENCE {
- userIdentity [0] OCTET STRING OPTIONAL,
- oldPasswd [1] OCTET STRING OPTIONAL,
- newPasswd [2] OCTET STRING OPTIONAL }
-
-PasswdModifyResponseValue ::= SEQUENCE {
- genPasswd [0] OCTET STRING OPTIONAL }
-
-END
-
-
diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl
index c5c34b743..199be890e 100644
--- a/include/ejabberd_commands.hrl
+++ b/include/ejabberd_commands.hrl
@@ -46,12 +46,13 @@
%% to command, so that the command can perform additional check.
-record(ejabberd_commands,
- {name :: atom(),
+ {name :: atom(),
tags = [] :: [atom()] | '_' | '$2',
desc = "" :: string() | '_' | '$3',
longdesc = "" :: string() | '_',
- version = 0 :: integer(),
- module :: atom() | '_',
+ version = 0 :: integer(),
+ weight = 1 :: integer(),
+ module :: atom() | '_',
function :: atom() | '_',
args = [] :: [aterm()] | '_' | '$1' | '$2',
policy = restricted :: open | restricted | admin | user,
diff --git a/rebar.config b/rebar.config
index 3ad5cf6e7..fca8d19e2 100644
--- a/rebar.config
+++ b/rebar.config
@@ -8,11 +8,11 @@
%%%-------------------------------------------------------------------
{deps, [{lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.2.1"}}},
- {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.5"}}},
+ {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.6"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.4"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.7"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.6"}}},
- {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.15"}}},
+ {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.16"}}},
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.7"}}},
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.8"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.6"}}},
diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl
index e88f24e1e..1791aa790 100644
--- a/src/ejabberd_app.erl
+++ b/src/ejabberd_app.erl
@@ -225,7 +225,6 @@ start_apps() ->
ejabberd:start_app(fast_tls),
ejabberd:start_app(fast_xml),
ejabberd:start_app(stringprep),
- http_p1:start(),
ejabberd:start_app(cache_tab).
opt_type(net_ticktime) ->
diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl
index e03b78fe8..74e26e8da 100644
--- a/src/ejabberd_oauth.erl
+++ b/src/ejabberd_oauth.erl
@@ -471,7 +471,7 @@ process(_Handlers,
[{<<"href">>, <<"https://www.ejabberd.im">>},
{<<"title">>, <<"ejabberd XMPP server">>}],
<<"ejabberd">>),
- ?C(" is maintained by "),
+ ?C(<<" is maintained by ">>),
?XAC(<<"a">>,
[{<<"href">>, <<"https://www.process-one.net">>},
{<<"title">>, <<"ProcessOne - Leader in Instant Messaging and Push Solutions">>}],
diff --git a/src/ext_mod.erl b/src/ext_mod.erl
index 842bb09fc..a2109e569 100644
--- a/src/ext_mod.erl
+++ b/src/ext_mod.erl
@@ -45,7 +45,7 @@
start() ->
[code:add_patha(module_ebin_dir(Module))
|| {Module, _} <- installed()],
- application:start(inets),
+ p1_http:start(),
ejabberd_commands:register_commands(get_commands_spec()).
stop() ->
@@ -271,10 +271,10 @@ geturl(Url, Hdrs, UsrOpts) ->
[U, Pass] -> [{proxy_user, U}, {proxy_password, Pass}];
_ -> []
end,
- case httpc:request(get, {Url, Hdrs}, Host++User++UsrOpts++[{version, "HTTP/1.0"}], []) of
- {ok, {{_, 200, _}, Headers, Response}} ->
+ case p1_http:request(get, Url, Hdrs, [], Host++User++UsrOpts++[{version, "HTTP/1.0"}]) of
+ {ok, 200, Headers, Response} ->
{ok, Headers, Response};
- {ok, {{_, Code, _}, _Headers, Response}} ->
+ {ok, Code, _Headers, Response} ->
{error, {Code, Response}};
{error, Reason} ->
{error, Reason}
diff --git a/src/http_p1.erl b/src/http_p1.erl
deleted file mode 100644
index f430bbe11..000000000
--- a/src/http_p1.erl
+++ /dev/null
@@ -1,358 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File : http_p1.erl
-%%% Author : Emilio Bustos <ebustos@process-one.net>
-%%% Purpose : Provide a common API for inets / lhttpc / ibrowse
-%%% Created : 29 Jul 2010 by Emilio Bustos <ebustos@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License along
-%%% with this program; if not, write to the Free Software Foundation, Inc.,
-%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-%%%
-%%%----------------------------------------------------------------------
-
--module(http_p1).
-
--author('ebustos@process-one.net').
-
--export([start/0, stop/0, get/1, get/2, post/2, post/3,
- request/3, request/4, request/5,
- get_pool_size/0, set_pool_size/1]).
-
--include("logger.hrl").
-
--define(USE_INETS, 1).
-% -define(USE_LHTTPC, 1).
-% -define(USE_IBROWSE, 1).
-% inets used as default if none specified
-
--ifdef(USE_IBROWSE).
-
-start() ->
- ejabberd:start_app(ibrowse).
-
-stop() ->
- application:stop(ibrowse).
-
-request(Method, URL, Hdrs, Body, Opts) ->
- TimeOut = proplists:get_value(timeout, Opts, infinity),
- Options = [{inactivity_timeout, TimeOut}
- | proplists:delete(timeout, Opts)],
- case ibrowse:send_req(URL, Hdrs, Method, Body, Options)
- of
- {ok, Status, Headers, Response} ->
- {ok, jlib:binary_to_integer(Status), Headers,
- Response};
- {error, Reason} -> {error, Reason}
- end.
-
-get_pool_size() ->
- application:get_env(ibrowse, default_max_sessions, 10).
-
-set_pool_size(Size) ->
- application:set_env(ibrowse, default_max_sessions, Size).
-
--else.
-
--ifdef(USE_LHTTPC).
-
-start() ->
- ejabberd:start_app(lhttpc).
-
-stop() ->
- application:stop(lhttpc).
-
-request(Method, URL, Hdrs, Body, Opts) ->
- {[TO, SO], Rest} = proplists:split(Opts, [timeout, socket_options]),
- TimeOut = proplists:get_value(timeout, TO, infinity),
- SockOpt = proplists:get_value(socket_options, SO, []),
- Options = [{connect_options, SockOpt} | Rest],
- Result = lhttpc:request(URL, Method, Hdrs, Body, TimeOut, Options),
- ?DEBUG("HTTP request -> response:~n"
- "** Method = ~p~n"
- "** URI = ~s~n"
- "** Body = ~s~n"
- "** Hdrs = ~p~n"
- "** Timeout = ~p~n"
- "** Options = ~p~n"
- "** Response = ~p",
- [Method, URL, Body, Hdrs, TimeOut, Options, Result]),
- case Result of
- {ok, {{Status, _Reason}, Headers, Response}} ->
- {ok, Status, Headers, (Response)};
- {error, Reason} -> {error, Reason}
- end.
-
-get_pool_size() ->
- Opts = proplists:get_value(lhttpc_manager, lhttpc_manager:list_pools()),
- proplists:get_value(max_pool_size,Opts).
-
-set_pool_size(Size) ->
- lhttpc_manager:set_max_pool_size(lhttpc_manager, Size).
-
--else.
-
-start() ->
- ejabberd:start_app(inets).
-
-stop() ->
- application:stop(inets).
-
-to_list(Str) when is_binary(Str) ->
- binary_to_list(Str);
-to_list(Str) ->
- Str.
-
-request(Method, URLRaw, HdrsRaw, Body, Opts) ->
- Hdrs = lists:map(fun({N, V}) ->
- {to_list(N), to_list(V)}
- end, HdrsRaw),
- URL = to_list(URLRaw),
-
- Request = case Method of
- get -> {URL, Hdrs};
- head -> {URL, Hdrs};
- delete -> {URL, Hdrs};
- _ -> % post, etc.
- {URL, Hdrs,
- to_list(proplists:get_value(<<"content-type">>, HdrsRaw, [])),
- Body}
- end,
- Options = case proplists:get_value(timeout, Opts,
- infinity)
- of
- infinity -> proplists:delete(timeout, Opts);
- _ -> Opts
- end,
- case httpc:request(Method, Request, Options, []) of
- {ok, {{_, Status, _}, Headers, Response}} ->
- {ok, Status, Headers, Response};
- {error, Reason} -> {error, Reason}
- end.
-
-get_pool_size() ->
- {ok, Size} = httpc:get_option(max_sessions),
- Size.
-
-set_pool_size(Size) ->
- httpc:set_option(max_sessions, Size).
-
--endif.
-
--endif.
-
--type({header,
- {type, 63, tuple,
- [{type, 63, union,
- [{type, 63, string, []}, {type, 63, atom, []}]},
- {type, 63, string, []}]},
- []}).
-
--type({headers,
- {type, 64, list, [{type, 64, header, []}]}, []}).
-
--type({option,
- {type, 67, union,
- [{type, 67, tuple,
- [{atom, 67, connect_timeout}, {type, 67, timeout, []}]},
- {type, 68, tuple,
- [{atom, 68, timeout}, {type, 68, timeout, []}]},
- {type, 70, tuple,
- [{atom, 70, send_retry},
- {type, 70, non_neg_integer, []}]},
- {type, 71, tuple,
- [{atom, 71, partial_upload},
- {type, 71, union,
- [{type, 71, non_neg_integer, []},
- {atom, 71, infinity}]}]},
- {type, 72, tuple,
- [{atom, 72, partial_download}, {type, 72, pid, []},
- {type, 72, union,
- [{type, 72, non_neg_integer, []},
- {atom, 72, infinity}]}]}]},
- []}).
-
--type({options,
- {type, 74, list, [{type, 74, option, []}]}, []}).
-
--type({result,
- {type, 76, union,
- [{type, 76, tuple,
- [{atom, 76, ok},
- {type, 76, tuple,
- [{type, 76, tuple,
- [{type, 76, pos_integer, []}, {type, 76, string, []}]},
- {type, 76, headers, []}, {type, 76, string, []}]}]},
- {type, 77, tuple,
- [{atom, 77, error}, {type, 77, atom, []}]}]},
- []}).
-
-%% @spec (URL) -> Result
-%% URL = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a GET request.
-%% Would be the same as calling `request(get, URL, [])',
-%% that is {@link request/3} with an empty header list.
-%% @end
-%% @see request/3
--spec get(string()) -> result().
-get(URL) -> request(get, URL, []).
-
-%% @spec (URL, Hdrs) -> Result
-%% URL = string()
-%% Hdrs = [{Header, Value}]
-%% Header = string()
-%% Value = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a GET request.
-%% Would be the same as calling `request(get, URL, Hdrs)'.
-%% @end
-%% @see request/3
--spec get(string(), headers()) -> result().
-get(URL, Hdrs) -> request(get, URL, Hdrs).
-
-%% @spec (URL, RequestBody) -> Result
-%% URL = string()
-%% RequestBody = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a POST request with form data.
-%% Would be the same as calling
-%% `request(post, URL, [{"content-type", "x-www-form-urlencoded"}], Body)'.
-%% @end
-%% @see request/4
--spec post(string(), string()) -> result().
-post(URL, Body) ->
- request(post, URL,
- [{<<"content-type">>, <<"x-www-form-urlencoded">>}],
- Body).
-
-%% @spec (URL, Hdrs, RequestBody) -> Result
-%% URL = string()
-%% Hdrs = [{Header, Value}]
-%% Header = string()
-%% Value = string()
-%% RequestBody = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a POST request.
-%% Would be the same as calling
-%% `request(post, URL, Hdrs, Body)'.
-%% @end
-%% @see request/4
--spec post(string(), headers(), string()) -> result().
-post(URL, Hdrs, Body) ->
- NewHdrs = case [X
- || {X, _} <- Hdrs,
- str:to_lower(X) == <<"content-type">>]
- of
- [] ->
- [{<<"content-type">>, <<"x-www-form-urlencoded">>}
- | Hdrs];
- _ -> Hdrs
- end,
- request(post, URL, NewHdrs, Body).
-
-%% @spec (Method, URL, Hdrs) -> Result
-%% Method = atom()
-%% URL = string()
-%% Hdrs = [{Header, Value}]
-%% Header = string()
-%% Value = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a request without a body.
-%% Would be the same as calling `request(Method, URL, Hdrs, [], [])',
-%% that is {@link request/5} with an empty body.
-%% @end
-%% @see request/5
--spec request(atom(), string(), headers()) -> result().
-request(Method, URL, Hdrs) ->
- request(Method, URL, Hdrs, [], []).
-
-%% @spec (Method, URL, Hdrs, RequestBody) -> Result
-%% Method = atom()
-%% URL = string()
-%% Hdrs = [{Header, Value}]
-%% Header = string()
-%% Value = string()
-%% RequestBody = string()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a request with a body.
-%% Would be the same as calling
-%% `request(Method, URL, Hdrs, Body, [])', that is {@link request/5}
-%% with no options.
-%% @end
-%% @see request/5
--spec request(atom(), string(), headers(), string()) -> result().
-request(Method, URL, Hdrs, Body) ->
- request(Method, URL, Hdrs, Body, []).
-
-%% @spec (Method, URL, Hdrs, RequestBody, Options) -> Result
-%% Method = atom()
-%% URL = string()
-%% Hdrs = [{Header, Value}]
-%% Header = string()
-%% Value = string()
-%% RequestBody = string()
-%% Options = [Option]
-%% Option = {timeout, Milliseconds | infinity} |
-%% {connect_timeout, Milliseconds | infinity} |
-%% {socket_options, [term()]} |
-
-%% Milliseconds = integer()
-%% Result = {ok, StatusCode, Hdrs, ResponseBody}
-%% | {error, Reason}
-%% StatusCode = integer()
-%% ResponseBody = string()
-%% Reason = connection_closed | connect_timeout | timeout
-%% @doc Sends a request with a body.
-%% Would be the same as calling
-%% `request(Method, URL, Hdrs, Body, [])', that is {@link request/5}
-%% with no options.
-%% @end
-%% @see request/5
--spec request(atom(), string(), headers(), string(), options()) -> result().
-
-% ibrowse {response_format, response_format()} |
-% Options - [option()]
-% Option - {sync, boolean()} | {stream, StreamTo} | {body_format, body_format()} | {full_result,
-% boolean()} | {headers_as_is, boolean()}
-%body_format() = string() | binary()
-% The body_format option is only valid for the synchronous request and the default is string.
-% When making an asynchronous request the body will always be received as a binary.
-% lhttpc: always binary
-
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
index 2967e86a0..053ce8092 100644
--- a/src/mod_admin_extra.erl
+++ b/src/mod_admin_extra.erl
@@ -176,8 +176,8 @@ get_commands_spec() ->
desc = "Check if the password hash is correct",
longdesc = "Allowed hash methods: md5, sha.",
module = ?MODULE, function = check_password_hash,
- args = [{user, binary}, {host, binary}, {passwordhash, string},
- {hashmethod, string}],
+ args = [{user, binary}, {host, binary}, {passwordhash, binary},
+ {hashmethod, binary}],
args_example = [<<"peter">>, <<"myserver.com">>,
<<"5ebe2294ecd0e0f08eab7690d2a6ee69">>, <<"md5">>],
args_desc = ["User name to check", "Server to check",
diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl
index 881587ede..a189777b1 100644
--- a/src/mod_http_api.erl
+++ b/src/mod_http_api.erl
@@ -273,7 +273,7 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) ->
fun ({Key, binary}, Acc) ->
[{Key, <<>>}|Acc];
({Key, string}, Acc) ->
- [{Key, <<>>}|Acc];
+ [{Key, ""}|Acc];
({Key, integer}, Acc) ->
[{Key, 0}|Acc];
({Key, {list, _}}, Acc) ->
@@ -406,10 +406,10 @@ format_arg(Elements, {list, ElementsDef})
format_arg(Arg, integer) when is_integer(Arg) -> Arg;
format_arg(Arg, binary) when is_list(Arg) -> process_unicode_codepoints(Arg);
format_arg(Arg, binary) when is_binary(Arg) -> Arg;
-format_arg(Arg, string) when is_list(Arg) -> process_unicode_codepoints(Arg);
-format_arg(Arg, string) when is_binary(Arg) -> Arg;
+format_arg(Arg, string) when is_list(Arg) -> Arg;
+format_arg(Arg, string) when is_binary(Arg) -> binary_to_list(Arg);
format_arg(undefined, binary) -> <<>>;
-format_arg(undefined, string) -> <<>>;
+format_arg(undefined, string) -> "";
format_arg(Arg, Format) ->
?ERROR_MSG("don't know how to format Arg ~p for format ~p", [Arg, Format]),
throw({invalid_parameter,
diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl
index 728a2d137..a896cb8b4 100644
--- a/src/mod_http_fileserver.erl
+++ b/src/mod_http_fileserver.erl
@@ -56,7 +56,7 @@
-record(state,
{host, docroot, accesslog, accesslogfd,
directory_indices, custom_headers, default_content_type,
- content_types = []}).
+ content_types = [], user_access = none}).
-define(PROCNAME, ejabberd_mod_http_fileserver).
@@ -133,7 +133,8 @@ start_link(Host, Opts) ->
init([Host, Opts]) ->
try initialize(Host, Opts) of
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes} ->
+ CustomHeaders, DefaultContentType, ContentTypes,
+ UserAccess} ->
{ok, #state{host = Host,
accesslog = AccessLog,
accesslogfd = AccessLogFD,
@@ -141,7 +142,8 @@ init([Host, Opts]) ->
directory_indices = DirectoryIndices,
custom_headers = CustomHeaders,
default_content_type = DefaultContentType,
- content_types = ContentTypes}}
+ content_types = ContentTypes,
+ user_access = UserAccess}}
catch
throw:Reason ->
{stop, Reason}
@@ -165,7 +167,15 @@ initialize(Host, Opts) ->
[]),
DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
fun iolist_to_binary/1,
- ?DEFAULT_CONTENT_TYPE),
+ ?DEFAULT_CONTENT_TYPE),
+ UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts,
+ mod_opt_type(must_authenticate_with),
+ []),
+ UserAccess = case UserAccess0 of
+ [] -> none;
+ _ ->
+ dict:from_list(UserAccess0)
+ end,
ContentTypes = build_list_content_types(
gen_mod:get_opt(content_types, Opts,
fun(L) when is_list(L) ->
@@ -180,7 +190,7 @@ initialize(Host, Opts) ->
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
<<", ">>)]),
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- CustomHeaders, DefaultContentType, ContentTypes}.
+ CustomHeaders, DefaultContentType, ContentTypes, UserAccess}.
%% @spec (AdminCTs::[CT], Default::[CT]) -> [CT]
@@ -246,10 +256,11 @@ try_open_log(FN, Host) ->
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call({serve, LocalPath}, _From, State) ->
- Reply = serve(LocalPath, State#state.docroot, State#state.directory_indices,
+handle_call({serve, LocalPath, Auth}, _From, State) ->
+ Reply = serve(LocalPath, Auth, State#state.docroot, State#state.directory_indices,
State#state.custom_headers,
- State#state.default_content_type, State#state.content_types),
+ State#state.default_content_type, State#state.content_types,
+ State#state.user_access),
{reply, Reply, State};
handle_call(_Request, _From, State) ->
{reply, ok, State}.
@@ -305,9 +316,9 @@ code_change(_OldVsn, State, _Extra) ->
%% @doc Handle an HTTP request.
%% LocalPath is the part of the requested URL path that is "local to the module".
%% Returns the page to be sent back to the client and/or HTTP status code.
-process(LocalPath, Request) ->
+process(LocalPath, #request{host = Host, auth = Auth} = Request) ->
?DEBUG("Requested ~p", [LocalPath]),
- try gen_server:call(get_proc_name(Request#request.host), {serve, LocalPath}) of
+ try gen_server:call(get_proc_name(Host), {serve, LocalPath, Auth}) of
{FileSize, Code, Headers, Contents} ->
add_to_log(FileSize, Code, Request),
{Code, Headers, Contents}
@@ -318,21 +329,38 @@ process(LocalPath, Request) ->
ejabberd_web:error(not_found)
end.
-serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes) ->
- FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
- case file:read_file_info(FileName) of
- {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
- {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
- {error, eacces} -> ?HTTP_ERR_FORBIDDEN;
- {ok, #file_info{type = directory}} -> serve_index(FileName,
- DirectoryIndices,
- CustomHeaders,
- DefaultContentType,
- ContentTypes);
- {ok, FileInfo} -> serve_file(FileInfo, FileName,
- CustomHeaders,
- DefaultContentType,
- ContentTypes)
+
+serve(LocalPath, Auth, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType,
+ ContentTypes, UserAccess) ->
+ CanProceed = case {UserAccess, Auth} of
+ {none, _} -> true;
+ {_, {User, Pass}} ->
+ case dict:find(User, UserAccess) of
+ {ok, Pass} -> true;
+ _ -> false
+ end;
+ _ ->
+ false
+ end,
+ case CanProceed of
+ true ->
+ FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
+ case file:read_file_info(FileName) of
+ {error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
+ {error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
+ {error, eacces} -> ?HTTP_ERR_FORBIDDEN;
+ {ok, #file_info{type = directory}} -> serve_index(FileName,
+ DirectoryIndices,
+ CustomHeaders,
+ DefaultContentType,
+ ContentTypes);
+ {ok, FileInfo} -> serve_file(FileInfo, FileName,
+ CustomHeaders,
+ DefaultContentType,
+ ContentTypes)
+ end;
+ _ ->
+ ?HTTP_ERR_FORBIDDEN
end.
%% Troll through the directory indices attempting to find one which
@@ -466,6 +494,14 @@ mod_opt_type(default_content_type) ->
mod_opt_type(directory_indices) ->
fun (L) when is_list(L) -> L end;
mod_opt_type(docroot) -> fun (A) -> A end;
+mod_opt_type(must_authenticate_with) ->
+ fun (L) when is_list(L) ->
+ lists:map(fun(UP) when is_binary(UP) ->
+ [K, V] = binary:split(UP, <<":">>),
+ {K, V}
+ end, L)
+ end;
mod_opt_type(_) ->
[accesslog, content_types, custom_headers,
- default_content_type, directory_indices, docroot].
+ default_content_type, directory_indices, docroot,
+ must_authenticate_with].
diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl
index 897810927..ab17a8891 100644
--- a/src/mod_ip_blacklist.erl
+++ b/src/mod_ip_blacklist.erl
@@ -89,9 +89,9 @@ loop(_State) -> receive stop -> ok end.
%% TODO: Support comment lines starting by %
update_bl_c2s() ->
?INFO_MSG("Updating C2S Blacklist", []),
- case httpc:request(?BLC2S) of
+ case p1_http:get(?BLC2S) of
{ok, 200, _Headers, Body} ->
- IPs = str:tokens(Body, <<"\n">>),
+ IPs = str:tokens(iolist_to_binary(Body), <<"\n">>),
ets:delete_all_objects(bl_c2s),
lists:foreach(fun (IP) ->
ets:insert(bl_c2s,
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index c83565734..060ac2bcd 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -3548,6 +3548,7 @@ make_opts(StateData) ->
?MAKE_CONFIG_OPT(#config.allow_voice_requests),
?MAKE_CONFIG_OPT(#config.allow_subscription),
?MAKE_CONFIG_OPT(#config.mam),
+ ?MAKE_CONFIG_OPT(#config.presence_broadcast),
?MAKE_CONFIG_OPT(#config.voice_request_min_interval),
?MAKE_CONFIG_OPT(#config.vcard),
{captcha_whitelist,
diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl
index beea35725..2d0d9ae0a 100644
--- a/src/mod_proxy65.erl
+++ b/src/mod_proxy65.erl
@@ -93,12 +93,10 @@ mod_opt_type(auth_type) ->
end;
mod_opt_type(recbuf) ->
fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(shaper) ->
- fun (A) when is_atom(A) -> A end;
+mod_opt_type(shaper) -> fun acl:shaper_rules_validator/1;
mod_opt_type(sndbuf) ->
fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(access) ->
- fun (A) when is_atom(A) -> A end;
+mod_opt_type(access) -> fun acl:access_rules_validator/1;
mod_opt_type(host) -> fun iolist_to_binary/1;
mod_opt_type(hostname) -> fun iolist_to_binary/1;
mod_opt_type(ip) ->
diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl
index a586935b8..a138b1896 100644
--- a/src/mod_pubsub.erl
+++ b/src/mod_pubsub.erl
@@ -251,7 +251,7 @@ init([ServerHost, Opts]) ->
Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>),
ejabberd_router:register_route(Host, ServerHost),
Access = gen_mod:get_opt(access_createnode, Opts,
- fun(A) when is_atom(A) -> A end, all),
+ fun acl:access_rules_validator/1, all),
PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts,
fun(A) when is_boolean(A) -> A end, true),
IQDisc = gen_mod:get_opt(iqdisc, Opts,
@@ -262,7 +262,7 @@ init([ServerHost, Opts]) ->
fun(A) when is_integer(A) andalso A >= 0 -> A end, ?MAXITEMS),
MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts,
fun(A) when is_integer(A) andalso A >= 0 -> A end, undefined),
- pubsub_index:init(Host, ServerHost, Opts),
+ [pubsub_index:init(Host, ServerHost, Opts) || gen_mod:db_type(ServerHost, ?MODULE)==mnesia],
{Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
DefaultModule = plugin(Host, hd(Plugins)),
BaseOptions = DefaultModule:options(),
@@ -3899,8 +3899,7 @@ purge_offline(Host, LJID, Node) ->
Error
end.
-mod_opt_type(access_createnode) ->
- fun (A) when is_atom(A) -> A end;
+mod_opt_type(access_createnode) -> fun acl:access_rules_validator/1;
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(host) -> fun iolist_to_binary/1;
mod_opt_type(ignore_pep_from_offline) ->
diff --git a/src/mod_register.erl b/src/mod_register.erl
index 44a64539e..dc8ca995c 100644
--- a/src/mod_register.erl
+++ b/src/mod_register.erl
@@ -613,14 +613,11 @@ check_ip_access(undefined, _IPAccess) ->
check_ip_access(IPAddress, IPAccess) ->
acl:match_rule(global, IPAccess, IPAddress).
-mod_opt_type(access) ->
- fun acl:access_rules_validator/1;
-mod_opt_type(access_from) ->
- fun (A) when is_atom(A) -> A end;
+mod_opt_type(access) -> fun acl:access_rules_validator/1;
+mod_opt_type(access_from) -> fun acl:access_rules_validator/1;
mod_opt_type(captcha_protected) ->
fun (B) when is_boolean(B) -> B end;
-mod_opt_type(ip_access) ->
- fun acl:access_rules_validator/1;
+mod_opt_type(ip_access) -> fun acl:access_rules_validator/1;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(password_strength) ->
fun (N) when is_number(N), N >= 0 -> N end;
diff --git a/src/node_flat.erl b/src/node_flat.erl
index 3afa49f22..9c1bc9b98 100644
--- a/src/node_flat.erl
+++ b/src/node_flat.erl
@@ -50,7 +50,7 @@
path_to_node/1, can_fetch_item/2, is_subscribed/1]).
init(_Host, _ServerHost, _Opts) ->
- %pubsub_subscription:init(),
+ %pubsub_subscription:init(Host, ServerHost, Opts),
mnesia:create_table(pubsub_state,
[{disc_copies, [node()]},
{type, ordered_set},
diff --git a/src/node_flat_sql.erl b/src/node_flat_sql.erl
index 5adf1e559..7e5ce788f 100644
--- a/src/node_flat_sql.erl
+++ b/src/node_flat_sql.erl
@@ -61,7 +61,7 @@
encode_host_like/1]).
init(_Host, _ServerHost, _Opts) ->
- %%pubsub_subscription_sql:init(),
+ %%pubsub_subscription_sql:init(Host, ServerHost, Opts),
ok.
terminate(_Host, _ServerHost) ->
diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl
index f2c962257..297c6627c 100644
--- a/src/pubsub_subscription.erl
+++ b/src/pubsub_subscription.erl
@@ -28,7 +28,7 @@
-author("bjc@kublai.com").
%% API
--export([init/0, subscribe_node/3, unsubscribe_node/3,
+-export([init/3, subscribe_node/3, unsubscribe_node/3,
get_subscription/3, set_subscription/4,
make_subid/0,
get_options_xform/2, parse_options_xform/1]).
@@ -73,7 +73,7 @@
%%====================================================================
%% API
%%====================================================================
-init() -> ok = create_table().
+init(_Host, _ServerHost, _Opts) -> ok = create_table().
subscribe_node(JID, NodeId, Options) ->
case catch mnesia:sync_dirty(fun add_subscription/3, [JID, NodeId, Options])
diff --git a/src/pubsub_subscription_sql.erl b/src/pubsub_subscription_sql.erl
index 922b2a418..bb7b64112 100644
--- a/src/pubsub_subscription_sql.erl
+++ b/src/pubsub_subscription_sql.erl
@@ -28,7 +28,7 @@
-author("pablo.polvorin@process-one.net").
%% API
--export([init/0, subscribe_node/3, unsubscribe_node/3,
+-export([init/3, subscribe_node/3, unsubscribe_node/3,
get_subscription/3, set_subscription/4,
make_subid/0,
get_options_xform/2, parse_options_xform/1]).
@@ -71,7 +71,7 @@
%% API
%%====================================================================
-init() -> ok = create_table().
+init(_Host, _ServerHost, _Opts) -> ok = create_table().
-spec subscribe_node(_JID :: _, _NodeId :: _, Options :: [] | mod_pubsub:subOptions()) ->
{result, mod_pubsub:subId()}.
diff --git a/src/rest.erl b/src/rest.erl
index 01b04f66a..091002fa5 100644
--- a/src/rest.erl
+++ b/src/rest.erl
@@ -28,7 +28,7 @@
-behaviour(ejabberd_config).
-export([start/1, stop/1, get/2, get/3, post/4, delete/2,
- request/6, with_retry/4, opt_type/1]).
+ put/4, patch/4, request/6, with_retry/4, opt_type/1]).
-include("logger.hrl").
@@ -36,14 +36,14 @@
-define(CONNECT_TIMEOUT, 8000).
start(Host) ->
- http_p1:start(),
+ p1_http:start(),
Pool_size =
ejabberd_config:get_option({ext_api_http_pool_size, Host},
fun(X) when is_integer(X), X > 0->
X
end,
100),
- http_p1:set_pool_size(Pool_size).
+ p1_http:set_pool_size(Pool_size).
stop(_Host) ->
ok.
@@ -71,18 +71,17 @@ delete(Server, Path) ->
request(Server, delete, Path, [], "application/json", <<>>).
post(Server, Path, Params, Content) ->
- Data = case catch jiffy:encode(Content) of
- {'EXIT', Reason} ->
- ?ERROR_MSG("HTTP content encodage failed:~n"
- "** Content = ~p~n"
- "** Err = ~p",
- [Content, Reason]),
- <<>>;
- Encoded ->
- Encoded
- end,
+ Data = encode_json(Content),
request(Server, post, Path, Params, "application/json", Data).
+put(Server, Path, Params, Content) ->
+ Data = encode_json(Content),
+ request(Server, put, Path, Params, "application/json", Data).
+
+patch(Server, Path, Params, Content) ->
+ Data = encode_json(Content),
+ request(Server, patch, Path, Params, "application/json", Data).
+
request(Server, Method, Path, Params, Mime, Data) ->
URI = url(Server, Path, Params),
Opts = [{connect_timeout, ?CONNECT_TIMEOUT},
@@ -91,7 +90,7 @@ request(Server, Method, Path, Params, Mime, Data) ->
{"content-type", Mime},
{"User-Agent", "ejabberd"}],
Begin = os:timestamp(),
- Result = case catch http_p1:request(Method, URI, Hdrs, Data, Opts) of
+ Result = case catch p1_http:request(Method, URI, Hdrs, Data, Opts) of
{ok, Code, _, <<>>} ->
{ok, Code, []};
{ok, Code, _, <<" ">>} ->
@@ -147,6 +146,18 @@ request(Server, Method, Path, Params, Mime, Data) ->
%%% HTTP helpers
%%%----------------------------------------------------------------------
+encode_json(Content) ->
+ case catch jiffy:encode(Content) of
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("HTTP content encodage failed:~n"
+ "** Content = ~p~n"
+ "** Err = ~p",
+ [Content, Reason]),
+ <<>>;
+ Encoded ->
+ Encoded
+ end.
+
base_url(Server, Path) ->
Tail = case iolist_to_binary(Path) of
<<$/, Ok/binary>> -> Ok;
diff --git a/src/str.erl b/src/str.erl
index 439ae6a7a..43fd51878 100644
--- a/src/str.erl
+++ b/src/str.erl
@@ -93,7 +93,10 @@ rchr(B, C) ->
-spec str(binary(), binary()) -> non_neg_integer().
str(B1, B2) ->
- string:str(binary_to_list(B1), binary_to_list(B2)).
+ case binary:match(B1, B2) of
+ {R, _Len} -> R+1;
+ _ -> 0
+ end.
-spec rstr(binary(), binary()) -> non_neg_integer().
@@ -113,7 +116,7 @@ cspan(B1, B2) ->
-spec copies(binary(), non_neg_integer()) -> binary().
copies(B, N) ->
- iolist_to_binary(string:copies(binary_to_list(B), N)).
+ binary:copy(B, N).
-spec words(binary()) -> pos_integer().
@@ -201,7 +204,7 @@ join(L, Sep) ->
-spec substr(binary(), pos_integer()) -> binary().
substr(B, N) ->
- iolist_to_binary(string:substr(binary_to_list(B), N)).
+ binary_part(B, N-1, byte_size(B)-N+1).
-spec chr(binary(), char()) -> non_neg_integer().
@@ -221,7 +224,7 @@ chars(C, N) ->
-spec substr(binary(), pos_integer(), non_neg_integer()) -> binary().
substr(B, S, E) ->
- iolist_to_binary(string:substr(binary_to_list(B), S, E)).
+ binary_part(B, S-1, E).
-spec strip(binary(), both | left | right, char()) -> binary().
diff --git a/test/suite.erl b/test/suite.erl
index a288a5f66..49ebaa891 100644
--- a/test/suite.erl
+++ b/test/suite.erl
@@ -481,9 +481,22 @@ format_element(El) ->
false -> io_lib:format(" ~s~n", El)
end.
+substitute_forwarded(#mam_result{sub_els = Sub} = El) ->
+ El#mam_result{sub_els = [substitute_forwarded(SEl) || SEl <- Sub]};
+substitute_forwarded(#carbons_sent{forwarded = Sub} = El) ->
+ El#carbons_sent{forwarded = [substitute_forwarded(SEl) || SEl <- Sub]};
+substitute_forwarded(#message{sub_els = Sub} = El) ->
+ El#message{sub_els = [substitute_forwarded(SEl) || SEl <- Sub]};
+substitute_forwarded(#forwarded{delay = Delay, xml_els = Sub}) ->
+ #forwarded_decoded{delay = Delay, sub_els = [xmpp:decode(SEl) || SEl <- Sub]};
+substitute_forwarded(El) ->
+ El.
+
+
+
decode(El, NS, Opts) ->
try
- Pkt = xmpp:decode(El, NS, Opts),
+ Pkt = substitute_forwarded(xmpp:decode(El, NS, Opts)),
ct:pal("RECV:~n~s~n~s",
[format_element(El), xmpp:pp(Pkt)]),
Pkt
diff --git a/test/suite.hrl b/test/suite.hrl
index 00239f8cf..d9a9c5ab0 100644
--- a/test/suite.hrl
+++ b/test/suite.hrl
@@ -5,6 +5,9 @@
-include("mod_proxy65.hrl").
-include("xmpp_codec.hrl").
+-record(forwarded_decoded, {delay :: #delay{},
+ sub_els = [] :: [fxml:xmlel()]}).
+
-define(STREAM_TRAILER, <<"</stream:stream>">>).
-define(PUBSUB(Node), <<(?NS_PUBSUB)/binary, "#", Node>>).