mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-12 21:52:07 +02:00
New configure option: --enable-nif
This commit is contained in:
parent
d9e2931ed9
commit
715cc5ea3b
|
@ -55,6 +55,11 @@ ifeq (@full_xml@, true)
|
||||||
EFLAGS+=-DFULL_XML_SUPPORT
|
EFLAGS+=-DFULL_XML_SUPPORT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (@nif@, true)
|
||||||
|
EFLAGS+=-DNIF
|
||||||
|
ERLSHLIBS=xml.so
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (@transient_supervisors@, false)
|
ifeq (@transient_supervisors@, false)
|
||||||
EFLAGS+=-DNO_TRANSIENT_SUPERVISORS
|
EFLAGS+=-DNO_TRANSIENT_SUPERVISORS
|
||||||
endif
|
endif
|
||||||
|
@ -68,7 +73,7 @@ prefix = @prefix@
|
||||||
exec_prefix = @exec_prefix@
|
exec_prefix = @exec_prefix@
|
||||||
|
|
||||||
SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ stringprep stun @tls@ @odbc@ @ejabberd_zlib@
|
SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ stringprep stun @tls@ @odbc@ @ejabberd_zlib@
|
||||||
ERLSHLIBS = expat_erl.so
|
ERLSHLIBS += expat_erl.so
|
||||||
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
|
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
|
||||||
SOURCES_ALL = $(wildcard *.erl)
|
SOURCES_ALL = $(wildcard *.erl)
|
||||||
SOURCES_MISC = $(ERLBEHAVS) $(DEBUGTOOLS)
|
SOURCES_MISC = $(ERLBEHAVS) $(DEBUGTOOLS)
|
||||||
|
|
|
@ -94,6 +94,15 @@ AC_ARG_ENABLE(full_xml,
|
||||||
esac],[full_xml=false])
|
esac],[full_xml=false])
|
||||||
AC_SUBST(full_xml)
|
AC_SUBST(full_xml)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(nif,
|
||||||
|
[AC_HELP_STRING([--enable-nif], [replace some functions with C equivalents. You should have Erlang R13B04 or higher (default: no)])],
|
||||||
|
[case "${enableval}" in
|
||||||
|
yes) nif=true ;;
|
||||||
|
no) nif=false ;;
|
||||||
|
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nif) ;;
|
||||||
|
esac],[nif=false])
|
||||||
|
AC_SUBST(nif)
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
$make_mod_irc
|
$make_mod_irc
|
||||||
$make_mod_muc
|
$make_mod_muc
|
||||||
|
|
|
@ -46,6 +46,7 @@ start(normal, _Args) ->
|
||||||
db_init(),
|
db_init(),
|
||||||
sha:start(),
|
sha:start(),
|
||||||
stringprep_sup:start_link(),
|
stringprep_sup:start_link(),
|
||||||
|
xml:start(),
|
||||||
start(),
|
start(),
|
||||||
translate:start(),
|
translate:start(),
|
||||||
acl:start(),
|
acl:start(),
|
||||||
|
|
|
@ -627,7 +627,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
||||||
Socket = StateData#state.socket,
|
Socket = StateData#state.socket,
|
||||||
TLSSocket = (StateData#state.sockmod):starttls(
|
TLSSocket = (StateData#state.sockmod):starttls(
|
||||||
Socket, TLSOpts,
|
Socket, TLSOpts,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
||||||
fsm_next_state(wait_for_stream,
|
fsm_next_state(wait_for_stream,
|
||||||
StateData#state{socket = TLSSocket,
|
StateData#state{socket = TLSSocket,
|
||||||
|
@ -650,7 +650,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
||||||
Socket = StateData#state.socket,
|
Socket = StateData#state.socket,
|
||||||
ZlibSocket = (StateData#state.sockmod):compress(
|
ZlibSocket = (StateData#state.sockmod):compress(
|
||||||
Socket,
|
Socket,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "compressed",
|
{xmlelement, "compressed",
|
||||||
[{"xmlns", ?NS_COMPRESS}], []})),
|
[{"xmlns", ?NS_COMPRESS}], []})),
|
||||||
fsm_next_state(wait_for_stream,
|
fsm_next_state(wait_for_stream,
|
||||||
|
@ -1453,14 +1453,14 @@ change_shaper(StateData, JID) ->
|
||||||
(StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper).
|
(StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper).
|
||||||
|
|
||||||
send_text(StateData, Text) ->
|
send_text(StateData, Text) ->
|
||||||
?DEBUG("Send XML on stream = ~p", [lists:flatten(Text)]),
|
?DEBUG("Send XML on stream = ~p", [Text]),
|
||||||
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) when StateData#state.xml_socket ->
|
send_element(StateData, El) when StateData#state.xml_socket ->
|
||||||
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
||||||
{xmlstreamelement, El});
|
{xmlstreamelement, El});
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_binary(El)).
|
||||||
|
|
||||||
send_header(StateData, Server, Version, Lang)
|
send_header(StateData, Server, Version, Lang)
|
||||||
when StateData#state.xml_socket ->
|
when StateData#state.xml_socket ->
|
||||||
|
|
|
@ -263,7 +263,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
||||||
TLSOpts = StateData#state.tls_options,
|
TLSOpts = StateData#state.tls_options,
|
||||||
TLSSocket = (StateData#state.sockmod):starttls(
|
TLSSocket = (StateData#state.sockmod):starttls(
|
||||||
Socket, TLSOpts,
|
Socket, TLSOpts,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
||||||
{next_state, wait_for_stream,
|
{next_state, wait_for_stream,
|
||||||
StateData#state{socket = TLSSocket,
|
StateData#state{socket = TLSSocket,
|
||||||
|
@ -618,7 +618,7 @@ send_text(StateData, Text) ->
|
||||||
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_binary(El)).
|
||||||
|
|
||||||
|
|
||||||
change_shaper(StateData, Host, JID) ->
|
change_shaper(StateData, Host, JID) ->
|
||||||
|
|
|
@ -892,7 +892,7 @@ send_text(StateData, Text) ->
|
||||||
ejabberd_socket:send(StateData#state.socket, Text).
|
ejabberd_socket:send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_binary(El)).
|
||||||
|
|
||||||
send_queue(StateData, Q) ->
|
send_queue(StateData, Q) ->
|
||||||
case queue:out(Q) of
|
case queue:out(Q) of
|
||||||
|
|
|
@ -347,7 +347,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
|
||||||
Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
|
Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
|
||||||
jlib:jid_to_string(To),
|
jlib:jid_to_string(To),
|
||||||
Attrs),
|
Attrs),
|
||||||
Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}),
|
Text = xml:element_to_binary({xmlelement, Name, Attrs2, Els}),
|
||||||
send_text(StateData, Text);
|
send_text(StateData, Text);
|
||||||
deny ->
|
deny ->
|
||||||
Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
|
Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
|
||||||
|
@ -391,7 +391,7 @@ send_text(StateData, Text) ->
|
||||||
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_binary(El)).
|
||||||
|
|
||||||
new_id() ->
|
new_id() ->
|
||||||
randoms:get_string().
|
randoms:get_string().
|
||||||
|
|
|
@ -162,7 +162,7 @@ normal_state({route, From, "",
|
||||||
trunc(gen_mod:get_module_opt(
|
trunc(gen_mod:get_module_opt(
|
||||||
StateData#state.server_host,
|
StateData#state.server_host,
|
||||||
mod_muc, min_message_interval, 0) * 1000000),
|
mod_muc, min_message_interval, 0) * 1000000),
|
||||||
Size = iolist_size(xml:element_to_string(Packet)),
|
Size = element_size(Packet),
|
||||||
{MessageShaper, MessageShaperInterval} =
|
{MessageShaper, MessageShaperInterval} =
|
||||||
shaper:update(Activity#activity.message_shaper, Size),
|
shaper:update(Activity#activity.message_shaper, Size),
|
||||||
if
|
if
|
||||||
|
@ -1394,7 +1394,7 @@ prepare_room_queue(StateData) ->
|
||||||
{{value, {message, From}}, _RoomQueue} ->
|
{{value, {message, From}}, _RoomQueue} ->
|
||||||
Activity = get_user_activity(From, StateData),
|
Activity = get_user_activity(From, StateData),
|
||||||
Packet = Activity#activity.message,
|
Packet = Activity#activity.message,
|
||||||
Size = iolist_size(xml:element_to_string(Packet)),
|
Size = element_size(Packet),
|
||||||
{RoomShaper, RoomShaperInterval} =
|
{RoomShaper, RoomShaperInterval} =
|
||||||
shaper:update(StateData#state.room_shaper, Size),
|
shaper:update(StateData#state.room_shaper, Size),
|
||||||
erlang:send_after(
|
erlang:send_after(
|
||||||
|
@ -1405,7 +1405,7 @@ prepare_room_queue(StateData) ->
|
||||||
{{value, {presence, From}}, _RoomQueue} ->
|
{{value, {presence, From}}, _RoomQueue} ->
|
||||||
Activity = get_user_activity(From, StateData),
|
Activity = get_user_activity(From, StateData),
|
||||||
{_Nick, Packet} = Activity#activity.presence,
|
{_Nick, Packet} = Activity#activity.presence,
|
||||||
Size = iolist_size(xml:element_to_string(Packet)),
|
Size = element_size(Packet),
|
||||||
{RoomShaper, RoomShaperInterval} =
|
{RoomShaper, RoomShaperInterval} =
|
||||||
shaper:update(StateData#state.room_shaper, Size),
|
shaper:update(StateData#state.room_shaper, Size),
|
||||||
erlang:send_after(
|
erlang:send_after(
|
||||||
|
@ -2068,7 +2068,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) ->
|
||||||
jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
TSPacket),
|
TSPacket),
|
||||||
Size = iolist_size(xml:element_to_string(SPacket)),
|
Size = element_size(SPacket),
|
||||||
Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, TimeStamp, Size},
|
Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, TimeStamp, Size},
|
||||||
StateData#state.history),
|
StateData#state.history),
|
||||||
add_to_log(text, {FromNick, Packet}, StateData),
|
add_to_log(text, {FromNick, Packet}, StateData),
|
||||||
|
@ -3582,3 +3582,6 @@ tab_count_user(JID) ->
|
||||||
_ ->
|
_ ->
|
||||||
0
|
0
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
element_size(El) ->
|
||||||
|
size(xml:element_to_binary(El)).
|
||||||
|
|
|
@ -123,8 +123,7 @@ loop(Host, AccessMaxOfflineMsgs) ->
|
||||||
M#offline_msg.timestamp))]},
|
M#offline_msg.timestamp))]},
|
||||||
XML =
|
XML =
|
||||||
ejabberd_odbc:escape(
|
ejabberd_odbc:escape(
|
||||||
lists:flatten(
|
xml:element_to_binary(Packet)),
|
||||||
xml:element_to_string(Packet))),
|
|
||||||
odbc_queries:add_spool_sql(Username, XML)
|
odbc_queries:add_spool_sql(Username, XML)
|
||||||
end, Msgs),
|
end, Msgs),
|
||||||
case catch odbc_queries:add_spool(Host, Query) of
|
case catch odbc_queries:add_spool(Host, Query) of
|
||||||
|
|
|
@ -790,7 +790,7 @@ handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) ->
|
||||||
?DEBUG("Trafic Shaper: Delaying request ~p", [Rid]),
|
?DEBUG("Trafic Shaper: Delaying request ~p", [Rid]),
|
||||||
timer:sleep(Pause),
|
timer:sleep(Pause),
|
||||||
%{200, ?HEADER,
|
%{200, ?HEADER,
|
||||||
% xml:element_to_string(
|
% xml:element_to_binary(
|
||||||
% {xmlelement, "body",
|
% {xmlelement, "body",
|
||||||
% [{"xmlns", ?NS_HTTP_BIND},
|
% [{"xmlns", ?NS_HTTP_BIND},
|
||||||
% {"type", "error"}], []})};
|
% {"type", "error"}], []})};
|
||||||
|
@ -827,21 +827,21 @@ handle_http_put_error(Reason, #http_bind{pid=FsmRef, version=Version})
|
||||||
case Reason of
|
case Reason of
|
||||||
not_exists ->
|
not_exists ->
|
||||||
{200, ?HEADER,
|
{200, ?HEADER,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "body",
|
{xmlelement, "body",
|
||||||
[{"xmlns", ?NS_HTTP_BIND},
|
[{"xmlns", ?NS_HTTP_BIND},
|
||||||
{"type", "terminate"},
|
{"type", "terminate"},
|
||||||
{"condition", "item-not-found"}], []})};
|
{"condition", "item-not-found"}], []})};
|
||||||
bad_key ->
|
bad_key ->
|
||||||
{200, ?HEADER,
|
{200, ?HEADER,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "body",
|
{xmlelement, "body",
|
||||||
[{"xmlns", ?NS_HTTP_BIND},
|
[{"xmlns", ?NS_HTTP_BIND},
|
||||||
{"type", "terminate"},
|
{"type", "terminate"},
|
||||||
{"condition", "item-not-found"}], []})};
|
{"condition", "item-not-found"}], []})};
|
||||||
polling_too_frequently ->
|
polling_too_frequently ->
|
||||||
{200, ?HEADER,
|
{200, ?HEADER,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement, "body",
|
{xmlelement, "body",
|
||||||
[{"xmlns", ?NS_HTTP_BIND},
|
[{"xmlns", ?NS_HTTP_BIND},
|
||||||
{"type", "terminate"},
|
{"type", "terminate"},
|
||||||
|
@ -986,7 +986,7 @@ prepare_outpacket_response(#http_bind{id=Sid, wait=Wait,
|
||||||
MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY),
|
MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY),
|
||||||
MaxPause = get_max_pause(To),
|
MaxPause = get_max_pause(To),
|
||||||
{200, ?HEADER,
|
{200, ?HEADER,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement,"body",
|
{xmlelement,"body",
|
||||||
[{"xmlns",
|
[{"xmlns",
|
||||||
?NS_HTTP_BIND},
|
?NS_HTTP_BIND},
|
||||||
|
@ -1041,7 +1041,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) ->
|
||||||
true ->
|
true ->
|
||||||
TypedEls = [check_default_xmlns(OEl) ||
|
TypedEls = [check_default_xmlns(OEl) ||
|
||||||
{xmlstreamelement, OEl} <- OutPacket],
|
{xmlstreamelement, OEl} <- OutPacket],
|
||||||
Body = xml:element_to_string(
|
Body = xml:element_to_binary(
|
||||||
{xmlelement,"body",
|
{xmlelement,"body",
|
||||||
[{"xmlns",
|
[{"xmlns",
|
||||||
?NS_HTTP_BIND}],
|
?NS_HTTP_BIND}],
|
||||||
|
@ -1075,7 +1075,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) ->
|
||||||
StreamTail]
|
StreamTail]
|
||||||
end,
|
end,
|
||||||
{200, ?HEADER,
|
{200, ?HEADER,
|
||||||
xml:element_to_string(
|
xml:element_to_binary(
|
||||||
{xmlelement,"body",
|
{xmlelement,"body",
|
||||||
[{"xmlns",
|
[{"xmlns",
|
||||||
?NS_HTTP_BIND}],
|
?NS_HTTP_BIND}],
|
||||||
|
@ -1191,7 +1191,7 @@ set_inactivity_timer(_Pause, MaxInactivity) ->
|
||||||
elements_to_string([]) ->
|
elements_to_string([]) ->
|
||||||
[];
|
[];
|
||||||
elements_to_string([El | Els]) ->
|
elements_to_string([El | Els]) ->
|
||||||
xml:element_to_string(El) ++ elements_to_string(Els).
|
[xml:element_to_binary(El)|elements_to_string(Els)].
|
||||||
|
|
||||||
%% @spec (To, Default::integer()) -> integer()
|
%% @spec (To, Default::integer()) -> integer()
|
||||||
%% where To = [] | {Host::string(), Version::string()}
|
%% where To = [] | {Host::string(), Version::string()}
|
||||||
|
|
230
src/xml.c
Normal file
230
src/xml.c
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
#include <erl_nif.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct buf {
|
||||||
|
int limit;
|
||||||
|
int len;
|
||||||
|
unsigned char *b;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int make_element(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM el);
|
||||||
|
|
||||||
|
static struct buf *init_buf(ErlNifEnv* env)
|
||||||
|
{
|
||||||
|
struct buf *rbuf = enif_alloc(env, sizeof(struct buf));
|
||||||
|
rbuf->limit = 1024;
|
||||||
|
rbuf->len = 0;
|
||||||
|
rbuf->b = enif_alloc(env, rbuf->limit);
|
||||||
|
return rbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_buf(ErlNifEnv* env, struct buf *rbuf)
|
||||||
|
{
|
||||||
|
if (rbuf) {
|
||||||
|
if (rbuf->b) {
|
||||||
|
enif_free(env, rbuf->b);
|
||||||
|
};
|
||||||
|
enif_free(env, rbuf);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void resize_buf(ErlNifEnv* env, struct buf *rbuf, int len_to_add)
|
||||||
|
{
|
||||||
|
int new_len = rbuf->len + len_to_add;
|
||||||
|
|
||||||
|
if (new_len >= rbuf->limit) {
|
||||||
|
rbuf->limit = ((new_len / 1024) + 1) * 1024;
|
||||||
|
rbuf->b = enif_realloc(env, rbuf->b, rbuf->limit);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buf_add_char(ErlNifEnv* env, struct buf *rbuf, unsigned char c)
|
||||||
|
{
|
||||||
|
resize_buf(env, rbuf, 1);
|
||||||
|
(rbuf->b)[rbuf->len] = c;
|
||||||
|
rbuf->len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buf_add_str(ErlNifEnv* env, struct buf *rbuf, char *data, int len)
|
||||||
|
{
|
||||||
|
resize_buf(env, rbuf, len);
|
||||||
|
memcpy(rbuf->b + rbuf->len, data, len);
|
||||||
|
rbuf->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void crypt(ErlNifEnv* env, struct buf *rbuf, unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
switch (data[i]) {
|
||||||
|
case '&':
|
||||||
|
buf_add_str(env, rbuf, "&", 5);
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
buf_add_str(env, rbuf, "<", 4);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
buf_add_str(env, rbuf, ">", 4);
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
buf_add_str(env, rbuf, """, 6);
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
buf_add_str(env, rbuf, "'", 6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buf_add_char(env, rbuf, data[i]);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static int make_elements(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM els)
|
||||||
|
{
|
||||||
|
ERL_NIF_TERM head, tail;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (enif_get_list_cell(env, els, &head, &tail)) {
|
||||||
|
ret = make_element(env, rbuf, head);
|
||||||
|
if (ret) {
|
||||||
|
els = tail;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int make_attrs(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM attrs)
|
||||||
|
{
|
||||||
|
ErlNifBinary name, data;
|
||||||
|
ERL_NIF_TERM head, tail;
|
||||||
|
const ERL_NIF_TERM *tuple;
|
||||||
|
int arity, ret = 1;
|
||||||
|
|
||||||
|
while (enif_get_list_cell(env, attrs, &head, &tail)) {
|
||||||
|
if (enif_get_tuple(env, head, &arity, &tuple)) {
|
||||||
|
if (arity == 2) {
|
||||||
|
if (enif_inspect_iolist_as_binary(env, tuple[0], &name) &&
|
||||||
|
enif_inspect_iolist_as_binary(env, tuple[1], &data)) {
|
||||||
|
buf_add_char(env, rbuf, ' ');
|
||||||
|
buf_add_str(env, rbuf, (char *)name.data, name.size);
|
||||||
|
buf_add_str(env, rbuf, "='", 2);
|
||||||
|
crypt(env, rbuf, data.data, data.size);
|
||||||
|
buf_add_char(env, rbuf, '\'');
|
||||||
|
attrs = tail;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int make_element(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM el)
|
||||||
|
{
|
||||||
|
ErlNifBinary cdata, name;
|
||||||
|
const ERL_NIF_TERM *tuple;
|
||||||
|
int arity, ret = 0;
|
||||||
|
|
||||||
|
if (enif_get_tuple(env, el, &arity, &tuple)) {
|
||||||
|
if (arity == 2) {
|
||||||
|
if (!enif_compare(env, tuple[0], enif_make_atom(env, "xmlcdata"))) {
|
||||||
|
if (enif_inspect_iolist_as_binary(env, tuple[1], &cdata)) {
|
||||||
|
crypt(env, rbuf, cdata.data, cdata.size);
|
||||||
|
ret = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (arity == 4) {
|
||||||
|
if (!enif_compare(env, tuple[0], enif_make_atom(env, "xmlelement"))) {
|
||||||
|
if (enif_inspect_iolist_as_binary(env, tuple[1], &name)) {
|
||||||
|
buf_add_char(env, rbuf, '<');
|
||||||
|
buf_add_str(env, rbuf, (char *)name.data, name.size);
|
||||||
|
ret = make_attrs(env, rbuf, tuple[2]);
|
||||||
|
if (ret) {
|
||||||
|
if (enif_is_empty_list(env, tuple[3])) {
|
||||||
|
buf_add_str(env, rbuf, "/>", 2);
|
||||||
|
} else {
|
||||||
|
buf_add_char(env, rbuf, '>');
|
||||||
|
ret = make_elements(env, rbuf, tuple[3]);
|
||||||
|
if (ret) {
|
||||||
|
buf_add_str(env, rbuf, "</", 2);
|
||||||
|
buf_add_str(env, rbuf, (char*)name.data, name.size);
|
||||||
|
buf_add_char(env, rbuf, '>');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM element_to(ErlNifEnv* env, int argc,
|
||||||
|
const ERL_NIF_TERM argv[],
|
||||||
|
int as_string)
|
||||||
|
{
|
||||||
|
ErlNifBinary output;
|
||||||
|
ERL_NIF_TERM result;
|
||||||
|
struct buf *rbuf;
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
rbuf = init_buf(env);
|
||||||
|
if (make_element(env, rbuf, argv[0])) {
|
||||||
|
if (as_string) {
|
||||||
|
(rbuf->b)[rbuf->len] = 0;
|
||||||
|
result = enif_make_string(env, (char *) rbuf->b, ERL_NIF_LATIN1);
|
||||||
|
destroy_buf(env, rbuf);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if (enif_alloc_binary(env, rbuf->len, &output)) {
|
||||||
|
memcpy(output.data, rbuf->b, rbuf->len);
|
||||||
|
result = enif_make_binary(env, &output);
|
||||||
|
destroy_buf(env, rbuf);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
destroy_buf(env, rbuf);
|
||||||
|
};
|
||||||
|
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static ERL_NIF_TERM element_to_string(ErlNifEnv* env, int argc, */
|
||||||
|
/* const ERL_NIF_TERM argv[]) */
|
||||||
|
/* { */
|
||||||
|
/* return element_to(env, argc, argv, 1); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
static ERL_NIF_TERM element_to_binary(ErlNifEnv* env, int argc,
|
||||||
|
const ERL_NIF_TERM argv[])
|
||||||
|
{
|
||||||
|
return element_to(env, argc, argv, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ErlNifFunc nif_funcs[] =
|
||||||
|
{
|
||||||
|
/* Stupid Erlang bug with enif_make_string() is fixed
|
||||||
|
in R14A only (OTP-8685), so we can't use
|
||||||
|
element_to_string yet.*/
|
||||||
|
/* {"element_to_string", 1, element_to_string}, */
|
||||||
|
{"element_to_binary", 1, element_to_binary}
|
||||||
|
};
|
||||||
|
|
||||||
|
ERL_NIF_INIT(xml, nif_funcs, NULL, NULL, NULL, NULL)
|
19
src/xml.erl
19
src/xml.erl
|
@ -37,8 +37,11 @@
|
||||||
get_subtag/2, get_subtag_cdata/2,
|
get_subtag/2, get_subtag_cdata/2,
|
||||||
append_subtags/2,
|
append_subtags/2,
|
||||||
get_path_s/2,
|
get_path_s/2,
|
||||||
|
start/0,
|
||||||
replace_tag_attr/3]).
|
replace_tag_attr/3]).
|
||||||
|
|
||||||
|
-include("ejabberd.hrl").
|
||||||
|
|
||||||
%% Select at compile time how to escape characters in binary text
|
%% Select at compile time how to escape characters in binary text
|
||||||
%% nodes.
|
%% nodes.
|
||||||
%% Can be choosen with ./configure --enable-full-xml
|
%% Can be choosen with ./configure --enable-full-xml
|
||||||
|
@ -48,6 +51,22 @@
|
||||||
-define(ESCAPE_BINARY(CData), crypt(CData)).
|
-define(ESCAPE_BINARY(CData), crypt(CData)).
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
|
%% Replace element_to_binary/1 with NIF
|
||||||
|
%% Can be choosen with ./configure --enable-nif
|
||||||
|
-ifdef(NIF).
|
||||||
|
start() ->
|
||||||
|
SOPath = filename:join(ejabberd:get_so_path(), "xml"),
|
||||||
|
case catch erlang:load_nif(SOPath, 0) of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
Err ->
|
||||||
|
?WARNING_MSG("unable to load xml NIF: ~p", [Err])
|
||||||
|
end.
|
||||||
|
-else.
|
||||||
|
start() ->
|
||||||
|
ok.
|
||||||
|
-endif.
|
||||||
|
|
||||||
element_to_binary(El) ->
|
element_to_binary(El) ->
|
||||||
iolist_to_binary(element_to_string(El)).
|
iolist_to_binary(element_to_string(El)).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user