mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Merge branch 'master' of github.com:processone/ejabberd
Conflicts: test/ejabberd_SUITE.erl
This commit is contained in:
commit
f57f267c54
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,6 +29,7 @@
|
||||
/doc/version.tex
|
||||
/ebin/
|
||||
/ejabberd.init
|
||||
/ejabberd.service
|
||||
/ejabberdctl.example
|
||||
XmppAddr.hrl
|
||||
/rel/ejabberd/
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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"}}},
|
||||
|
@ -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) ->
|
||||
|
@ -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">>}],
|
||||
|
@ -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}
|
||||
|
358
src/http_p1.erl
358
src/http_p1.erl
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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].
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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) ->
|
||||
|
@ -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) ->
|
||||
|
@ -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;
|
||||
|
@ -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},
|
||||
|
@ -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) ->
|
||||
|
@ -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])
|
||||
|
@ -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()}.
|
||||
|
39
src/rest.erl
39
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;
|
||||
|
11
src/str.erl
11
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().
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>>).
|
||||
|
Loading…
Reference in New Issue
Block a user