Ejabberd 2.1.10 Developers GuideAlexey Shchepin
+Ejabberd 2.1.x Developers Guide |
diff --git a/doc/features.html b/doc/features.html
index 025511cd3..503ac0d3f 100644
--- a/doc/features.html
+++ b/doc/features.html
@@ -2,7 +2,7 @@
"http://www.w3.org/TR/REC-html40/loose.dtd">
- Ejabberd 2.1.10 Feature Sheet
+Ejabberd 2.1.x Feature Sheet
@@ -50,7 +50,7 @@ SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
- Ejabberd 2.1.10 Feature SheetSander Devrieze
+Ejabberd 2.1.x Feature Sheet |
diff --git a/doc/guide.html b/doc/guide.html
index 787ec960b..397491939 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -6,7 +6,7 @@
- ejabberd 2.1.10
+ ejabberd 2.1.x
Installation and Operation Guide
@@ -76,7 +76,7 @@ BLOCKQUOTE.figure DIV.center DIV.center HR{display:none;}
- ejabberd 2.1.10 |
+ ejabberd 2.1.x |
|
Installation and Operation Guide |
diff --git a/doc/guide.tex b/doc/guide.tex
index 47153d630..77428dbfd 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -829,7 +829,7 @@ The available modules, their purpose and the options allowed by each one are:
Options: \texttt{certfile}
\titem{\texttt{ejabberd\_http}}
Handles incoming HTTP connections.\\
- Options: \texttt{captcha}, \texttt{certfile}, \texttt{http\_bind}, \texttt{http\_poll},
+ Options: \texttt{captcha}, \texttt{certfile}, \texttt{default\_host}, \texttt{http\_bind}, \texttt{http\_poll},
\texttt{request\_handlers}, \texttt{tls}, \texttt{trusted\_proxies}, \texttt{web\_admin}\\
\end{description}
@@ -850,6 +850,11 @@ This is a detailed description of each option allowed by the listening modules:
Simple web page that allows a user to fill a CAPTCHA challenge (see section \ref{captcha}).
\titem{\{certfile, Path\}} Full path to a file containing the default SSL certificate.
To define a certificate file specific for a given domain, use the global option \term{domain\_certfile}.
+ \titem{\{default\_host, undefined|HostName\}}
+ If the HTTP request received by ejabberd contains the HTTP header \term{Host}
+ with an ambiguous virtual host that doesn't match any one defined in ejabberd (see \ref{hostnames}),
+ then this configured HostName is set as the request Host.
+ The default value of this option is: \term{undefined}.
\titem{\{hosts, [Hostname, ...], [HostOption, ...]\}} \ind{options!hosts}
The external Jabber component that connects to this \term{ejabberd\_service}
can serve one or more hostnames.
@@ -1667,7 +1672,7 @@ The configurable options are:
\begin{description}
\titem{\{captcha\_cmd, Path\}}
Full path to a script that generates the image.
- The default value is an empty string: \term{""}
+ The default value disables the feature: \term{undefined}
\titem{\{captcha\_host, ProtocolHostPort\}}
ProtocolHostPort is a string with the host, and optionally the Protocol and Port number.
It must identify where ejabberd listens for CAPTCHA requests.
@@ -5882,6 +5887,7 @@ Thanks to all people who contributed to this guide:
\item Badlop (\ahrefurl{xmpp:badlop@jabberes.org})
\item Evgeniy Khramtsov (\ahrefurl{xmpp:xram@jabber.ru})
\item Florian Zumbiehl (\ahrefurl{xmpp:florz@florz.de})
+\item Ludovic Bocquet (\ahrefurl{xmpp:lbocquet@jabber.org})
\item Marcin Owsiany (\ahrefurl{xmpp:marcin.owsiany@gmail.com})
\item Michael Grigutsch (\ahrefurl{xmpp:migri@jabber.i-pobox.net})
\item Mickael Remond (\ahrefurl{xmpp:mremond@process-one.net})
diff --git a/doc/version.tex b/doc/version.tex
index 40b1b7baa..905ac86f2 100644
--- a/doc/version.tex
+++ b/doc/version.tex
@@ -1,2 +1,2 @@
% ejabberd version (automatically generated).
-\newcommand{\version}{2.1.10}
+\newcommand{\version}{2.1.x}
diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl
index e1fa4768d..1dc443f32 100644
--- a/src/ejabberd_receiver.erl
+++ b/src/ejabberd_receiver.erl
@@ -89,19 +89,19 @@ change_shaper(Pid, Shaper) ->
gen_server:cast(Pid, {change_shaper, Shaper}).
reset_stream(Pid) ->
- gen_server:call(Pid, reset_stream).
+ do_call(Pid, reset_stream).
starttls(Pid, TLSOpts) ->
starttls(Pid, TLSOpts, undefined).
starttls(Pid, TLSOpts, Data) ->
- gen_server:call(Pid, {starttls, TLSOpts, Data}).
+ do_call(Pid, {starttls, TLSOpts, Data}).
compress(Pid, Data) ->
- gen_server:call(Pid, {compress, Data}).
+ do_call(Pid, {compress, Data}).
become_controller(Pid, C2SPid) ->
- gen_server:call(Pid, {become_controller, C2SPid}).
+ do_call(Pid, {become_controller, C2SPid}).
change_controller(Pid, C2SPid) ->
case catch gen_server:call(Pid, {change_controller, C2SPid}) of
@@ -448,3 +448,11 @@ cancel_timer(TRef) when is_reference(TRef) ->
end;
cancel_timer(_) ->
ok.
+
+do_call(Pid, Msg) ->
+ case catch gen_server:call(Pid, Msg) of
+ {'EXIT', Why} ->
+ {error, Why};
+ Res ->
+ Res
+ end.
diff --git a/src/jlib.hrl b/src/jlib.hrl
index e18e8e29c..528f56550 100644
--- a/src/jlib.hrl
+++ b/src/jlib.hrl
@@ -101,6 +101,8 @@
[{"code", Code}, {"type", Type}],
[{xmlelement, Condition, [{"xmlns", ?NS_STANZAS}], []}]}).
+-define(ERR_BAD_FORMAT,
+ ?STANZA_ERROR("406", "modify", "bad-format")).
-define(ERR_BAD_REQUEST,
?STANZA_ERROR("400", "modify", "bad-request")).
-define(ERR_CONFLICT,
@@ -155,6 +157,8 @@
{xmlelement, "text", [{"xmlns", ?NS_STANZAS}],
[{xmlcdata, translate:translate(Lang, Text)}]}]}).
+-define(ERRT_BAD_FORMAT(Lang, Text),
+ ?STANZA_ERRORT("406", "modify", "bad-format", Lang, Text)).
-define(ERRT_BAD_REQUEST(Lang, Text),
?STANZA_ERRORT("400", "modify", "bad-request", Lang, Text)).
-define(ERRT_CONFLICT(Lang, Text),
diff --git a/src/mod_private.erl b/src/mod_private.erl
index f8ba72d47..a123f698b 100644
--- a/src/mod_private.erl
+++ b/src/mod_private.erl
@@ -39,6 +39,11 @@
-record(private_storage, {usns, xml}).
+-define(Xmlel_Query(Attrs, Children),
+(
+ {xmlelement, "query", Attrs, Children}
+)).
+
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
mnesia:create_table(private_storage,
@@ -56,73 +61,97 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE).
-process_sm_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
- #jid{luser = LUser, lserver = LServer} = From,
- case lists:member(LServer, ?MYHOSTS) of
- true ->
- {xmlelement, Name, Attrs, Els} = SubEl,
- case Type of
- set ->
- F = fun() ->
- lists:foreach(
- fun(El) ->
- set_data(LUser, LServer, El)
- end, Els)
- end,
- mnesia:transaction(F),
- IQ#iq{type = result,
- sub_el = [{xmlelement, Name, Attrs, []}]};
- get ->
- case catch get_data(LUser, LServer, Els) of
- {'EXIT', _Reason} ->
- IQ#iq{type = error,
- sub_el = [SubEl,
- ?ERR_INTERNAL_SERVER_ERROR]};
- Res ->
- IQ#iq{type = result,
- sub_el = [{xmlelement, Name, Attrs, Res}]}
- end
- end;
- false ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
+process_sm_iq(#jid{luser = LUser, lserver = LServer},
+ #jid{luser = LUser, lserver = LServer}, IQ)
+ when IQ#iq.type == 'set' ->
+ case IQ#iq.sub_el of
+ {xmlelement, "query", _, Xmlels} ->
+ case filter_xmlels(Xmlels) of
+ [] ->
+ IQ#iq{
+ type = error,
+ sub_el = [IQ#iq.sub_el, ?ERR_NOT_ACCEPTABLE]
+ };
+ Data ->
+ mnesia:transaction(fun() ->
+ lists:foreach(fun
+ (Datum) ->
+ set_data(LUser, LServer, Datum)
+ end, Data)
+ end),
+ IQ#iq{type = result, sub_el = []}
+ end;
+ _ ->
+ IQ#iq{type = error, sub_el = [IQ#iq.sub_el, ?ERR_NOT_ACCEPTABLE]}
+ end;
+%%
+process_sm_iq(#jid{luser = LUser, lserver = LServer},
+ #jid{luser = LUser, lserver = LServer}, IQ)
+ when IQ#iq.type == 'get' ->
+ case IQ#iq.sub_el of
+ {xmlelement, "query", Attrs, Xmlels} ->
+ case filter_xmlels(Xmlels) of
+ [] ->
+ IQ#iq{
+ type = error,
+ sub_el = [IQ#iq.sub_el, ?ERR_BAD_FORMAT]
+ };
+ Data ->
+ case catch get_data(LUser, LServer, Data) of
+ {'EXIT', _Reason} ->
+ IQ#iq{
+ type = error,
+ sub_el = [IQ#iq.sub_el, ?ERR_INTERNAL_SERVER_ERROR]
+ };
+ Storage_Xmlels ->
+ IQ#iq{
+ type = result,
+ sub_el = [?Xmlel_Query(Attrs, Storage_Xmlels)]
+ }
+ end
+ end;
+ _ ->
+ IQ#iq{type = error, sub_el = [IQ#iq.sub_el, ?ERR_BAD_FORMAT]}
+ end;
+%%
+process_sm_iq(_From, _To, IQ) ->
+ IQ#iq{type = error, sub_el = [IQ#iq.sub_el, ?ERR_FORBIDDEN]}.
+
+
+filter_xmlels(Xmlels) ->
+ filter_xmlels(Xmlels, []).
+
+filter_xmlels([], Data) ->
+ lists:reverse(Data);
+filter_xmlels([{xmlelement, _, Attrs, _} = Xmlel | Xmlels], Data) ->
+ case xml:get_attr_s("xmlns", Attrs) of
+ "" -> [];
+ XmlNS -> filter_xmlels(Xmlels, [{XmlNS, Xmlel} | Data])
+ end;
+filter_xmlels([_ | Xmlels], Data) ->
+ filter_xmlels(Xmlels, Data).
+
+
+set_data(LUser, LServer, {XmlNS, Xmlel}) ->
+ mnesia:write(#private_storage{
+ usns = {LUser, LServer, XmlNS},
+ xml = Xmlel
+ }).
+
+
+get_data(LUser, LServer, Data) ->
+ get_data(LUser, LServer, Data, []).
+
+get_data(_LUser, _LServer, [], Storage_Xmlels) ->
+ lists:reverse(Storage_Xmlels);
+get_data(LUser, LServer, [{XmlNS, Xmlel} | Data], Storage_Xmlels) ->
+ case mnesia:dirty_read(private_storage, {LUser, LServer, XmlNS}) of
+ [#private_storage{xml = Storage_Xmlel}] ->
+ get_data(LUser, LServer, Data, [Storage_Xmlel | Storage_Xmlels]);
+ _ ->
+ get_data(LUser, LServer, Data, [Xmlel | Storage_Xmlels])
end.
-set_data(LUser, LServer, El) ->
- case El of
- {xmlelement, _Name, Attrs, _Els} ->
- XMLNS = xml:get_attr_s("xmlns", Attrs),
- case XMLNS of
- "" ->
- ignore;
- _ ->
- mnesia:write(
- #private_storage{usns = {LUser, LServer, XMLNS},
- xml = El})
- end;
- _ ->
- ignore
- end.
-
-get_data(LUser, LServer, Els) ->
- get_data(LUser, LServer, Els, []).
-
-get_data(_LUser, _LServer, [], Res) ->
- lists:reverse(Res);
-get_data(LUser, LServer, [El | Els], Res) ->
- case El of
- {xmlelement, _Name, Attrs, _} ->
- XMLNS = xml:get_attr_s("xmlns", Attrs),
- case mnesia:dirty_read(private_storage, {LUser, LServer, XMLNS}) of
- [R] ->
- get_data(LUser, LServer, Els,
- [R#private_storage.xml | Res]);
- [] ->
- get_data(LUser, LServer, Els,
- [El | Res])
- end;
- _ ->
- get_data(LUser, LServer, Els, Res)
- end.
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl
index 26f9f0d65..5c14790e3 100644
--- a/src/mod_shared_roster.erl
+++ b/src/mod_shared_roster.erl
@@ -631,7 +631,7 @@ add_user_to_group(Host, US, Group) ->
GroupOpts ++ MoreGroupOpts);
nomatch ->
%% Push this new user to members of groups where this group is displayed
- push_user_to_displayed(LUser, LServer, Group, both),
+ push_user_to_displayed(LUser, LServer, Group, Host, both),
%% Push members of groups that are displayed to this group
push_displayed_to_user(LUser, LServer, Group, Host, both),
R = #sr_user{us = US, group_host = {Group, Host}},
@@ -668,7 +668,7 @@ remove_user_from_group(Host, US, Group) ->
end,
Result = mnesia:transaction(F),
%% Push removal of the old user to members of groups where the group that this user was members was displayed
- push_user_to_displayed(LUser, LServer, Group, remove),
+ push_user_to_displayed(LUser, LServer, Group, Host, remove),
%% Push removal of members of groups that where displayed to the group which this user has left
push_displayed_to_user(LUser, LServer, Group, Host, remove),
Result
@@ -689,7 +689,7 @@ register_user(User, Server) ->
%% Get list of groups where this user is member
Groups = get_user_groups({User, Server}),
%% Push this user to members of groups where is displayed a group which this user is member
- [push_user_to_displayed(User, Server, Group, both) || Group <- Groups].
+ [push_user_to_displayed(User, Server, Group, Server, both) || Group <- Groups].
remove_user(User, Server) ->
push_user_to_members(User, Server, remove).
@@ -711,19 +711,19 @@ push_user_to_members(User, Server, Subscription) ->
end, get_group_users(LServer, Group, GroupOpts))
end, lists:usort(SpecialGroups++UserGroups)).
-push_user_to_displayed(LUser, LServer, Group, Subscription) ->
- GroupsOpts = groups_with_opts(LServer),
+push_user_to_displayed(LUser, LServer, Group, Host, Subscription) ->
+ GroupsOpts = groups_with_opts(Host),
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
GroupName = proplists:get_value(name, GroupOpts, Group),
- DisplayedToGroupsOpts = displayed_to_groups(Group, LServer),
- [push_user_to_group(LUser, LServer, GroupD, GroupName, Subscription) || {GroupD, _Opts} <- DisplayedToGroupsOpts].
+ DisplayedToGroupsOpts = displayed_to_groups(Group, Host),
+ [push_user_to_group(LUser, LServer, GroupD, Host, GroupName, Subscription) || {GroupD, _Opts} <- DisplayedToGroupsOpts].
-push_user_to_group(LUser, LServer, Group, GroupName, Subscription) ->
+push_user_to_group(LUser, LServer, Group, Host, GroupName, Subscription) ->
lists:foreach(
- fun({U, S}) when (U == LUser) and (S == LServer) -> ok;
+ fun({U, S}) when (U == LUser) and (S == LServer) -> ok;
({U, S}) ->
push_roster_item(U, S, LUser, LServer, GroupName, Subscription)
- end, get_group_users(LServer, Group)).
+ end, get_group_users(Host, Group)).
%% Get list of groups to which this group is displayed
displayed_to_groups(GroupName, LServer) ->
@@ -819,7 +819,7 @@ user_available(New) ->
fun(OG) ->
?DEBUG("user_available: pushing ~p @ ~p grp ~p",
[LUser, LServer, OG ]),
- push_user_to_displayed(LUser, LServer, OG, both)
+ push_user_to_displayed(LUser, LServer, OG, LServer, both)
end, OnlineGroups);
_ ->
ok
@@ -840,7 +840,7 @@ unset_presence(LUser, LServer, Resource, Status) ->
fun(OG) ->
%% Push removal of the old user to members of groups
%% where the group that this uwas members was displayed
- push_user_to_displayed(LUser, LServer, OG, remove),
+ push_user_to_displayed(LUser, LServer, OG, LServer, remove),
%% Push removal of members of groups that where
%% displayed to the group which thiuser has left
push_displayed_to_user(LUser, LServer, OG, LServer,remove)
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
index 1820f64b8..46830b020 100644
--- a/src/mod_vcard.erl
+++ b/src/mod_vcard.erl
@@ -219,17 +219,17 @@ set_vcard(User, LServer, VCARD) ->
end,
LUser = jlib:nodeprep(User),
- LFN = string:to_lower(FN),
- LFamily = string:to_lower(Family),
- LGiven = string:to_lower(Given),
- LMiddle = string:to_lower(Middle),
- LNickname = string:to_lower(Nickname),
- LBDay = string:to_lower(BDay),
- LCTRY = string:to_lower(CTRY),
- LLocality = string:to_lower(Locality),
- LEMail = string:to_lower(EMail),
- LOrgName = string:to_lower(OrgName),
- LOrgUnit = string:to_lower(OrgUnit),
+ LFN = string2lower(FN),
+ LFamily = string2lower(Family),
+ LGiven = string2lower(Given),
+ LMiddle = string2lower(Middle),
+ LNickname = string2lower(Nickname),
+ LBDay = string2lower(BDay),
+ LCTRY = string2lower(CTRY),
+ LLocality = string2lower(Locality),
+ LEMail = string2lower(EMail),
+ LOrgName = string2lower(OrgName),
+ LOrgUnit = string2lower(OrgUnit),
US = {LUser, LServer},
@@ -271,6 +271,12 @@ set_vcard(User, LServer, VCARD) ->
ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD])
end.
+string2lower(String) ->
+ case stringprep:tolower(String) of
+ Lower when is_list(Lower) -> Lower;
+ error -> string:to_lower(String)
+ end.
+
-define(TLFIELD(Type, Label, Var),
{xmlelement, "field", [{"type", Type},
{"label", translate:translate(Lang, Label)},
@@ -541,7 +547,7 @@ filter_fields([], Match, _LServer) ->
Match;
filter_fields([{SVar, [Val]} | Ds], Match, LServer)
when is_list(Val) and (Val /= "") ->
- LVal = string:to_lower(Val),
+ LVal = string2lower(Val),
NewMatch = case SVar of
"user" ->
case gen_mod:get_module_opt(LServer, ?MODULE,
@@ -618,17 +624,17 @@ set_vcard_t(R, _) ->
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
{LUser, _LServer} = US,
- LFN = string:to_lower(FN),
- LFamily = string:to_lower(Family),
- LGiven = string:to_lower(Given),
- LMiddle = string:to_lower(Middle),
- LNickname = string:to_lower(Nickname),
- LBDay = string:to_lower(BDay),
- LCTRY = string:to_lower(CTRY),
- LLocality = string:to_lower(Locality),
- LEMail = string:to_lower(EMail),
- LOrgName = string:to_lower(OrgName),
- LOrgUnit = string:to_lower(OrgUnit),
+ LFN = string2lower(FN),
+ LFamily = string2lower(Family),
+ LGiven = string2lower(Given),
+ LMiddle = string2lower(Middle),
+ LNickname = string2lower(Nickname),
+ LBDay = string2lower(BDay),
+ LCTRY = string2lower(CTRY),
+ LLocality = string2lower(Locality),
+ LEMail = string2lower(EMail),
+ LOrgName = string2lower(OrgName),
+ LOrgUnit = string2lower(OrgUnit),
if
(LUser == error) or
diff --git a/src/mod_vcard_odbc.erl b/src/mod_vcard_odbc.erl
index a4c23624c..fd1ca9022 100644
--- a/src/mod_vcard_odbc.erl
+++ b/src/mod_vcard_odbc.erl
@@ -186,17 +186,17 @@ set_vcard(User, LServer, VCARD) ->
end,
LUser = jlib:nodeprep(User),
- LFN = string:to_lower(FN),
- LFamily = string:to_lower(Family),
- LGiven = string:to_lower(Given),
- LMiddle = string:to_lower(Middle),
- LNickname = string:to_lower(Nickname),
- LBDay = string:to_lower(BDay),
- LCTRY = string:to_lower(CTRY),
- LLocality = string:to_lower(Locality),
- LEMail = string:to_lower(EMail),
- LOrgName = string:to_lower(OrgName),
- LOrgUnit = string:to_lower(OrgUnit),
+ LFN = string2lower(FN),
+ LFamily = string2lower(Family),
+ LGiven = string2lower(Given),
+ LMiddle = string2lower(Middle),
+ LNickname = string2lower(Nickname),
+ LBDay = string2lower(BDay),
+ LCTRY = string2lower(CTRY),
+ LLocality = string2lower(Locality),
+ LEMail = string2lower(EMail),
+ LOrgName = string2lower(OrgName),
+ LOrgUnit = string2lower(OrgUnit),
if
(LUser == error) or
@@ -252,6 +252,12 @@ set_vcard(User, LServer, VCARD) ->
ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD])
end.
+string2lower(String) ->
+ case stringprep:tolower(String) of
+ Lower when is_list(Lower) -> Lower;
+ error -> string:to_lower(String)
+ end.
+
-define(TLFIELD(Type, Label, Var),
{xmlelement, "field", [{"type", Type},
{"label", translate:translate(Lang, Label)},
@@ -531,7 +537,7 @@ filter_fields([], Match, _LServer) ->
end;
filter_fields([{SVar, [Val]} | Ds], Match, LServer)
when is_list(Val) and (Val /= "") ->
- LVal = string:to_lower(Val),
+ LVal = string2lower(Val),
NewMatch = case SVar of
"user" -> make_val(Match, "lusername", LVal);
"fn" -> make_val(Match, "lfn", LVal);
diff --git a/src/odbc/odbc_queries.erl b/src/odbc/odbc_queries.erl
index 11e36909c..d2fcba476 100644
--- a/src/odbc/odbc_queries.erl
+++ b/src/odbc/odbc_queries.erl
@@ -575,7 +575,7 @@ escape($\n) -> "\\n";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
-escape($') -> "\\'";
+escape($') -> "''";
escape($") -> "\\\"";
escape($\\) -> "\\\\";
escape(C) -> C.
diff --git a/src/tls/tls_drv.c b/src/tls/tls_drv.c
index 188097fb5..bc9fde6fb 100644
--- a/src/tls/tls_drv.c
+++ b/src/tls/tls_drv.c
@@ -433,30 +433,37 @@ static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
"SSL_do_handshake failed");
}
- rlen = 1;
- b = driver_alloc_binary(rlen + BUF_SIZE);
- b->orig_bytes[0] = 0;
+ if (SSL_is_init_finished(d->ssl)) {
+ size = BUF_SIZE + 1;
+ rlen = 1;
+ b = driver_alloc_binary(size);
+ b->orig_bytes[0] = 0;
- while ((res = SSL_read(d->ssl,
- b->orig_bytes + rlen, BUF_SIZE)) > 0)
- {
- //printf("%d bytes of decrypted data read from state machine\r\n",res);
- rlen += res;
- b = driver_realloc_binary(b, rlen + BUF_SIZE);
- }
+ while ((res = SSL_read(d->ssl,
+ b->orig_bytes + rlen, BUF_SIZE)) > 0)
+ {
+ //printf("%d bytes of decrypted data read from state machine\r\n",res);
+ rlen += res;
+ size += BUF_SIZE;
+ b = driver_realloc_binary(b, size);
+ }
- if (res < 0)
- {
- int err = SSL_get_error(d->ssl, res);
+ if (res < 0)
+ {
+ int err = SSL_get_error(d->ssl, res);
- if (err != SSL_ERROR_WANT_READ)
- {
- // TODO
- }
- }
- b = driver_realloc_binary(b, rlen);
- *rbuf = (char *)b;
- return rlen;
+ if (err == SSL_ERROR_WANT_READ)
+ {
+ //printf("SSL_read wants more data\r\n");
+ //return 0;
+ }
+ // TODO
+ }
+ b = driver_realloc_binary(b, rlen);
+ *rbuf = (char *)b;
+ return rlen;
+ }
+ break;
case GET_PEER_CERTIFICATE:
cert = SSL_get_peer_certificate(d->ssl);
if (cert == NULL)
diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl
index aba14f1a9..aff928f72 100644
--- a/src/web/ejabberd_http.erl
+++ b/src/web/ejabberd_http.erl
@@ -65,6 +65,7 @@
request_tp,
request_headers = [],
end_of_request = false,
+ default_host,
trail = "",
websocket_handlers = []
}).
@@ -145,9 +146,11 @@ init({SockMod, Socket}, Opts) ->
false -> []
end,
?DEBUG("WS: ~p~n", [WebSocketHandlers]),
+ DefaultHost = gen_mod:get_opt(default_host, Opts, undefined),
?INFO_MSG("started: ~p", [{SockMod1, Socket1}]),
State = #state{sockmod = SockMod1,
socket = Socket1,
+ default_host = DefaultHost,
request_handlers = RequestHandlers,
websocket_handlers = WebSocketHandlers},
receive_headers(State).
@@ -278,8 +281,9 @@ process_header(State, Data) ->
[State#state.socket,
State#state.request_method,
element(2, State#state.request_path)]),
- {Host, Port, TP} = get_transfer_protocol(SockMod,
+ {HostProvided, Port, TP} = get_transfer_protocol(SockMod,
State#state.request_host),
+ Host = get_host_really_served(State#state.default_host, HostProvided),
State2 = State#state{request_host = Host,
request_port = Port,
request_tp = TP},
@@ -316,6 +320,15 @@ add_header(Name, Value, State) ->
{value, {Param, V}} -> V;
false -> undefined
end).
+
+get_host_really_served(undefined, Provided) ->
+ Provided;
+get_host_really_served(Default, Provided) ->
+ case lists:member(Provided, ?MYHOSTS) of
+ true -> Provided;
+ false -> Default
+ end.
+
%% @spec (SockMod, HostPort) -> {Host::string(), Port::integer(), TP}
%% where
%% SockMod = gen_tcp | tls
diff --git a/src/web/ejabberd_http_bind.erl b/src/web/ejabberd_http_bind.erl
index 72d9e80f6..a014b030c 100644
--- a/src/web/ejabberd_http_bind.erl
+++ b/src/web/ejabberd_http_bind.erl
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_http_bind.erl
%%% Author : Stefan Strigler
-%%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as
+%%% Purpose : Implements XMPP over BOSH (XEP-0206) (formerly known as
%%% HTTP Binding)
%%% Created : 21 Sep 2005 by Stefan Strigler
%%% Modified: may 2009 by Mickael Remond, Alexey Schepin
|
|