diff --git a/doc/dev.html b/doc/dev.html index 83da3eb10..b86448c56 100644 --- a/doc/dev.html +++ b/doc/dev.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/REC-html40/loose.dtd"> -Ejabberd 2.1.10 Developers Guide +<TITLE>Ejabberd 2.1.x Developers Guide @@ -49,7 +49,7 @@ TD P{margin:0px;}

-

Ejabberd 2.1.10 Developers Guide

Alexey Shchepin
+

Ejabberd 2.1.x Developers Guide

Alexey Shchepin
mailto:alexey@sevcom.net
xmpp:aleksey@jabber.ru

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 +<TITLE>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 Sheet

Sander Devrieze
+

Ejabberd 2.1.x Feature Sheet

Sander Devrieze
mailto:s.devrieze@pandora.be
xmpp:sander@devrieze.dyndns.org

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