mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-06 21:37:17 +02:00
Improve build procedure
This commit is contained in:
parent
d1c654a7e1
commit
04f20a21fb
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -16,23 +16,3 @@
|
||||||
/doc/*.toc
|
/doc/*.toc
|
||||||
/doc/contributed_modules.tex
|
/doc/contributed_modules.tex
|
||||||
/doc/version.tex
|
/doc/version.tex
|
||||||
/src/*.beam
|
|
||||||
/src/*.so
|
|
||||||
/src/*.so.dSYM
|
|
||||||
/src/*/*.beam
|
|
||||||
/src/*/Makefile
|
|
||||||
/src/Makefile
|
|
||||||
/src/XmppAddr.asn1db
|
|
||||||
/src/XmppAddr.erl
|
|
||||||
/src/XmppAddr.hrl
|
|
||||||
/src/aclocal.m4
|
|
||||||
/src/autom4te.cache
|
|
||||||
/src/config.log
|
|
||||||
/src/config.status
|
|
||||||
/src/ejabberd.init
|
|
||||||
/src/ejabberdctl.example
|
|
||||||
/src/eldap/ELDAPv3.asn1db
|
|
||||||
/src/eldap/ELDAPv3.erl
|
|
||||||
/src/eldap/ELDAPv3.hrl
|
|
||||||
/src/eldap/eldap_filter_yecc.erl
|
|
||||||
/src/epam
|
|
||||||
|
|
17
Makefile.in
17
Makefile.in
|
@ -1,4 +1,4 @@
|
||||||
REBAR = @REBAR@
|
REBAR = rebar
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
SED = @SED@
|
SED = @SED@
|
||||||
ERL = @ERL@
|
ERL = @ERL@
|
||||||
|
@ -94,16 +94,25 @@ edoc:
|
||||||
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
|
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rebar clean
|
$(REBAR) clean
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f config.status
|
rm -f config.status
|
||||||
rm -f config.log
|
rm -f config.log
|
||||||
rm -f rebar.config
|
rm -f rebar.config
|
||||||
rm -rf deps/*
|
rm -rf deps
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
|
rm -rf rel/files
|
||||||
|
rm -rf rel/ejabberd
|
||||||
|
rm -f rel/reltool.config
|
||||||
|
rm -f src/ejabberd.app.src
|
||||||
[ ! -f ../ChangeLog ] || rm -f ../ChangeLog
|
[ ! -f ../ChangeLog ] || rm -f ../ChangeLog
|
||||||
|
|
||||||
|
rel:
|
||||||
|
mkdir -p rel ; cd rel ; rm -rf files ejabberd ; \
|
||||||
|
$(REBAR) create-node nodeid=ejabberd || exit 1; \
|
||||||
|
$(REBAR) generate
|
||||||
|
|
||||||
TAGS:
|
TAGS:
|
||||||
etags *.erl
|
etags *.erl
|
||||||
|
|
||||||
|
@ -112,4 +121,4 @@ Makefile: Makefile.in
|
||||||
dialyzer: $(BEAMS)
|
dialyzer: $(BEAMS)
|
||||||
@dialyzer -c .
|
@dialyzer -c .
|
||||||
|
|
||||||
.PHONY: src doc edoc dialyzer Makefile TAGS clean distclean
|
.PHONY: src doc edoc dialyzer Makefile TAGS clean distclean rel
|
||||||
|
|
|
@ -1,316 +0,0 @@
|
||||||
/*
|
|
||||||
* ejabberd, Copyright (C) 2002-2013 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., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
* 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <erl_driver.h>
|
|
||||||
#include <ei.h>
|
|
||||||
#include <expat.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define XML_START 0
|
|
||||||
#define XML_END 1
|
|
||||||
#define XML_CDATA 2
|
|
||||||
#define XML_ERROR 3
|
|
||||||
|
|
||||||
#define PARSE_COMMAND 0
|
|
||||||
#define PARSE_FINAL_COMMAND 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* R15B changed several driver callbacks to use ErlDrvSizeT and
|
|
||||||
* ErlDrvSSizeT typedefs instead of int.
|
|
||||||
* This provides missing typedefs on older OTP versions.
|
|
||||||
*/
|
|
||||||
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
|
|
||||||
typedef int ErlDrvSizeT;
|
|
||||||
typedef int ErlDrvSSizeT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ei_x_buff event_buf;
|
|
||||||
ei_x_buff xmlns_buf;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ErlDrvPort port;
|
|
||||||
XML_Parser parser;
|
|
||||||
} expat_data;
|
|
||||||
|
|
||||||
static XML_Memory_Handling_Suite ms;
|
|
||||||
|
|
||||||
void encode_name(const XML_Char *name)
|
|
||||||
{
|
|
||||||
char *name_start;
|
|
||||||
char *prefix_start;
|
|
||||||
char *buf;
|
|
||||||
int name_len, prefix_len, buf_len;
|
|
||||||
|
|
||||||
if ((name_start = strchr(name, '\n'))) {
|
|
||||||
if ((prefix_start = strchr(name_start+1, '\n'))) {
|
|
||||||
name_len = prefix_start - name_start;
|
|
||||||
prefix_len = strlen(prefix_start+1);
|
|
||||||
buf_len = prefix_len + name_len;
|
|
||||||
buf = driver_alloc(buf_len);
|
|
||||||
memcpy(buf, prefix_start+1, prefix_len);
|
|
||||||
memcpy(buf+prefix_len, name_start, name_len);
|
|
||||||
buf[prefix_len] = ':';
|
|
||||||
ei_x_encode_binary(&event_buf, buf, buf_len);
|
|
||||||
driver_free(buf);
|
|
||||||
} else {
|
|
||||||
ei_x_encode_binary(&event_buf, name_start+1, strlen(name_start+1));
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
ei_x_encode_binary(&event_buf, name, strlen(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *erlXML_StartElementHandler(expat_data *d,
|
|
||||||
const XML_Char *name,
|
|
||||||
const XML_Char **atts)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ei_x_encode_list_header(&event_buf, 1);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
ei_x_encode_long(&event_buf, XML_START);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
encode_name(name);
|
|
||||||
ei_x_append(&event_buf, &xmlns_buf);
|
|
||||||
ei_x_free(&xmlns_buf);
|
|
||||||
ei_x_new(&xmlns_buf);
|
|
||||||
|
|
||||||
for (i = 0; atts[i]; i += 2) {}
|
|
||||||
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
ei_x_encode_list_header(&event_buf, i/2);
|
|
||||||
|
|
||||||
for (i = 0; atts[i]; i += 2)
|
|
||||||
{
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
encode_name(atts[i]);
|
|
||||||
ei_x_encode_binary(&event_buf, atts[i+1], strlen(atts[i+1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ei_x_encode_empty_list(&event_buf);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *erlXML_EndElementHandler(expat_data *d,
|
|
||||||
const XML_Char *name)
|
|
||||||
{
|
|
||||||
ei_x_encode_list_header(&event_buf, 1);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
ei_x_encode_long(&event_buf, XML_END);
|
|
||||||
encode_name(name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *erlXML_CharacterDataHandler(expat_data *d,
|
|
||||||
const XML_Char *s,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
ei_x_encode_list_header(&event_buf, 1);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
ei_x_encode_long(&event_buf, XML_CDATA);
|
|
||||||
ei_x_encode_binary(&event_buf, s, len);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *erlXML_StartNamespaceDeclHandler(expat_data *d,
|
|
||||||
const XML_Char *prefix,
|
|
||||||
const XML_Char *uri)
|
|
||||||
{
|
|
||||||
int prefix_len;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
/* From the expat documentation:
|
|
||||||
"For a default namespace declaration (xmlns='...'),
|
|
||||||
the prefix will be null ...
|
|
||||||
... The URI will be null for the case where
|
|
||||||
the default namespace is being unset."
|
|
||||||
|
|
||||||
FIXME: I'm not quite sure what all that means */
|
|
||||||
if (uri == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ei_x_encode_list_header(&xmlns_buf, 1);
|
|
||||||
ei_x_encode_tuple_header(&xmlns_buf, 2);
|
|
||||||
if (prefix) {
|
|
||||||
prefix_len = strlen(prefix);
|
|
||||||
buf = driver_alloc(7 + prefix_len);
|
|
||||||
strcpy(buf, "xmlns:");
|
|
||||||
strcpy(buf+6, prefix);
|
|
||||||
ei_x_encode_binary(&xmlns_buf, buf, strlen(buf));
|
|
||||||
driver_free(buf);
|
|
||||||
} else {
|
|
||||||
ei_x_encode_binary(&xmlns_buf, "xmlns", strlen("xmlns"));
|
|
||||||
};
|
|
||||||
ei_x_encode_binary(&xmlns_buf, uri, strlen(uri));
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff)
|
|
||||||
{
|
|
||||||
expat_data* d = (expat_data*)driver_alloc(sizeof(expat_data));
|
|
||||||
d->port = port;
|
|
||||||
d->parser = XML_ParserCreate_MM("UTF-8", &ms, "\n");
|
|
||||||
XML_SetUserData(d->parser, d);
|
|
||||||
|
|
||||||
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
|
|
||||||
|
|
||||||
XML_SetStartElementHandler(
|
|
||||||
d->parser, (XML_StartElementHandler)erlXML_StartElementHandler);
|
|
||||||
XML_SetEndElementHandler(
|
|
||||||
d->parser, (XML_EndElementHandler)erlXML_EndElementHandler);
|
|
||||||
XML_SetCharacterDataHandler(
|
|
||||||
d->parser, (XML_CharacterDataHandler)erlXML_CharacterDataHandler);
|
|
||||||
|
|
||||||
XML_SetStartNamespaceDeclHandler(
|
|
||||||
d->parser, (XML_StartNamespaceDeclHandler) erlXML_StartNamespaceDeclHandler);
|
|
||||||
XML_SetReturnNSTriplet(d->parser, 1);
|
|
||||||
|
|
||||||
XML_SetDefaultHandler(d->parser, NULL);
|
|
||||||
|
|
||||||
return (ErlDrvData)d;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void expat_erl_stop(ErlDrvData handle)
|
|
||||||
{
|
|
||||||
XML_ParserFree(((expat_data *)handle)->parser);
|
|
||||||
driver_free((char*)handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ErlDrvSSizeT expat_erl_control(ErlDrvData drv_data,
|
|
||||||
unsigned int command,
|
|
||||||
char *buf, ErlDrvSizeT len,
|
|
||||||
char **rbuf, ErlDrvSizeT rlen)
|
|
||||||
{
|
|
||||||
expat_data* d = (expat_data*)drv_data;
|
|
||||||
int res, errcode;
|
|
||||||
char *errstring;
|
|
||||||
ErlDrvBinary *b;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case PARSE_COMMAND:
|
|
||||||
case PARSE_FINAL_COMMAND:
|
|
||||||
ei_x_new_with_version(&event_buf);
|
|
||||||
ei_x_new(&xmlns_buf);
|
|
||||||
#ifdef ENABLE_FLASH_HACK
|
|
||||||
/* Flash hack - Flash clients send a null byte after the stanza. Remove that... */
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int found_null = 0;
|
|
||||||
|
|
||||||
/* Maybe the Flash client sent many stanzas in one packet.
|
|
||||||
If so, there is a null byte between every stanza. */
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
if (buf[i] == '\0') {
|
|
||||||
buf[i] = ' ';
|
|
||||||
found_null = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And also remove the closing slash if this is a
|
|
||||||
flash:stream element. Assume that flash:stream is the
|
|
||||||
last element in the packet, and entirely contained in
|
|
||||||
it. This requires that a null byte has been found. */
|
|
||||||
if (found_null && strstr(buf, "<flash:stream"))
|
|
||||||
/* buf[len - 1] is an erased null byte.
|
|
||||||
buf[len - 2] is >
|
|
||||||
buf[len - 3] is / (maybe)
|
|
||||||
*/
|
|
||||||
if (buf[len - 3] == '/')
|
|
||||||
buf[len - 3] = ' ';
|
|
||||||
}
|
|
||||||
#endif /* ENABLE_FLASH_HACK */
|
|
||||||
|
|
||||||
res = XML_Parse(d->parser, buf, len, command == PARSE_FINAL_COMMAND);
|
|
||||||
|
|
||||||
if(!res)
|
|
||||||
{
|
|
||||||
errcode = XML_GetErrorCode(d->parser);
|
|
||||||
errstring = (char *)XML_ErrorString(errcode);
|
|
||||||
|
|
||||||
ei_x_encode_list_header(&event_buf, 1);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
ei_x_encode_long(&event_buf, XML_ERROR);
|
|
||||||
ei_x_encode_tuple_header(&event_buf, 2);
|
|
||||||
ei_x_encode_long(&event_buf, errcode);
|
|
||||||
ei_x_encode_binary(&event_buf, errstring, strlen(errstring));
|
|
||||||
}
|
|
||||||
|
|
||||||
ei_x_encode_empty_list(&event_buf);
|
|
||||||
|
|
||||||
size = event_buf.index;
|
|
||||||
|
|
||||||
b = driver_alloc_binary(size);
|
|
||||||
memcpy(b->orig_bytes, event_buf.buff, size);
|
|
||||||
|
|
||||||
ei_x_free(&event_buf);
|
|
||||||
ei_x_free(&xmlns_buf);
|
|
||||||
|
|
||||||
*rbuf = (char *)b;
|
|
||||||
return size;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ErlDrvEntry expat_driver_entry = {
|
|
||||||
NULL, /* F_PTR init, N/A */
|
|
||||||
expat_erl_start, /* L_PTR start, called when port is opened */
|
|
||||||
expat_erl_stop, /* F_PTR stop, called when port is closed */
|
|
||||||
NULL, /* F_PTR output, called when erlang has sent */
|
|
||||||
NULL, /* F_PTR ready_input, called when input descriptor ready */
|
|
||||||
NULL, /* F_PTR ready_output, called when output descriptor ready */
|
|
||||||
"expat_erl", /* char *driver_name, the argument to open_port */
|
|
||||||
NULL, /* F_PTR finish, called when unloaded */
|
|
||||||
NULL, /* handle */
|
|
||||||
expat_erl_control, /* F_PTR control, port_command callback */
|
|
||||||
NULL, /* F_PTR timeout, reserved */
|
|
||||||
NULL, /* F_PTR outputv, reserved */
|
|
||||||
/* Added in Erlang/OTP R15B: */
|
|
||||||
NULL, /* ready_async */
|
|
||||||
NULL, /* flush */
|
|
||||||
NULL, /* call */
|
|
||||||
NULL, /* event */
|
|
||||||
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
|
|
||||||
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
|
|
||||||
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
|
|
||||||
0, /* driver_flags */
|
|
||||||
NULL, /* handle2 */
|
|
||||||
NULL, /* process_exit */
|
|
||||||
NULL /* stop_select */
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_INIT(expat_erl) /* must match name in driver_entry */
|
|
||||||
{
|
|
||||||
ms.malloc_fcn = driver_alloc;
|
|
||||||
ms.realloc_fcn = driver_realloc;
|
|
||||||
ms.free_fcn = driver_free;
|
|
||||||
return &expat_driver_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
120
c_src/sha_drv.c
120
c_src/sha_drv.c
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* ejabberd, Copyright (C) 2002-2013 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., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
* 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <erl_driver.h>
|
|
||||||
#include <openssl/sha.h>
|
|
||||||
#ifdef HAVE_MD2
|
|
||||||
#include <openssl/md2.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* R15B changed several driver callbacks to use ErlDrvSizeT and
|
|
||||||
* ErlDrvSSizeT typedefs instead of int.
|
|
||||||
* This provides missing typedefs on older OTP versions.
|
|
||||||
*/
|
|
||||||
#if ERL_DRV_EXTENDED_MAJOR_VERSION < 2
|
|
||||||
typedef int ErlDrvSizeT;
|
|
||||||
typedef int ErlDrvSSizeT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ErlDrvData sha_drv_start(ErlDrvPort port, char *buf)
|
|
||||||
{
|
|
||||||
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ErlDrvSSizeT sha_drv_control(ErlDrvData handle,
|
|
||||||
unsigned int command,
|
|
||||||
char *buf, ErlDrvSizeT len,
|
|
||||||
char **rbuf, ErlDrvSizeT rlen)
|
|
||||||
{
|
|
||||||
ErlDrvBinary *b = NULL;
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
#ifdef HAVE_MD2
|
|
||||||
case 2:
|
|
||||||
rlen = MD2_DIGEST_LENGTH;
|
|
||||||
b = driver_alloc_binary(rlen);
|
|
||||||
if (b) MD2((unsigned char*)buf, len, (unsigned char*)b->orig_bytes);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 224:
|
|
||||||
rlen = SHA224_DIGEST_LENGTH;
|
|
||||||
b = driver_alloc_binary(rlen);
|
|
||||||
if (b) SHA224((unsigned char*)buf, len, (unsigned char*)b->orig_bytes);
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
rlen = SHA256_DIGEST_LENGTH;
|
|
||||||
b = driver_alloc_binary(rlen);
|
|
||||||
if (b) SHA256((unsigned char*)buf, len, (unsigned char*)b->orig_bytes);
|
|
||||||
break;
|
|
||||||
case 384:
|
|
||||||
rlen = SHA384_DIGEST_LENGTH;
|
|
||||||
b = driver_alloc_binary(rlen);
|
|
||||||
if (b) SHA384((unsigned char*)buf, len, (unsigned char*)b->orig_bytes);
|
|
||||||
break;
|
|
||||||
case 512:
|
|
||||||
rlen = SHA512_DIGEST_LENGTH;
|
|
||||||
b = driver_alloc_binary(rlen);
|
|
||||||
if (b) SHA512((unsigned char*)buf, len, (unsigned char*)b->orig_bytes);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (b) {
|
|
||||||
*rbuf = (char *)b;
|
|
||||||
} else {
|
|
||||||
*rbuf = NULL;
|
|
||||||
rlen = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return rlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErlDrvEntry sha_driver_entry = {
|
|
||||||
NULL, /* F_PTR init, N/A */
|
|
||||||
sha_drv_start, /* L_PTR start, called when port is opened */
|
|
||||||
NULL, /* F_PTR stop, called when port is closed */
|
|
||||||
NULL, /* F_PTR output, called when erlang has sent */
|
|
||||||
NULL, /* F_PTR ready_input, called when input descriptor ready */
|
|
||||||
NULL, /* F_PTR ready_output, called when output descriptor ready */
|
|
||||||
"sha_drv", /* char *driver_name, the argument to open_port */
|
|
||||||
NULL, /* F_PTR finish, called when unloaded */
|
|
||||||
NULL, /* handle */
|
|
||||||
sha_drv_control, /* F_PTR control, port_command callback */
|
|
||||||
NULL, /* F_PTR timeout, reserved */
|
|
||||||
NULL, /* F_PTR outputv, reserved */
|
|
||||||
/* Added in Erlang/OTP R15B: */
|
|
||||||
NULL, /* ready_async */
|
|
||||||
NULL, /* flush */
|
|
||||||
NULL, /* call */
|
|
||||||
NULL, /* event */
|
|
||||||
ERL_DRV_EXTENDED_MARKER, /* extended_marker */
|
|
||||||
ERL_DRV_EXTENDED_MAJOR_VERSION, /* major_version */
|
|
||||||
ERL_DRV_EXTENDED_MINOR_VERSION, /* minor_version */
|
|
||||||
0, /* driver_flags */
|
|
||||||
NULL, /* handle2 */
|
|
||||||
NULL, /* process_exit */
|
|
||||||
NULL /* stop_select */
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_INIT(sha_drv) /* must match name in driver_entry */
|
|
||||||
{
|
|
||||||
return &sha_driver_entry;
|
|
||||||
}
|
|
261
c_src/xml.c
261
c_src/xml.c
|
@ -1,261 +0,0 @@
|
||||||
#include <erl_nif.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define SSL40
|
|
||||||
|
|
||||||
#ifdef SSL40
|
|
||||||
#define ENIF_ALLOC(SIZE) enif_alloc(SIZE)
|
|
||||||
#define ENIF_FREE(PTR) enif_free(PTR)
|
|
||||||
#define ENIF_REALLOC(PTR, SIZE) enif_realloc(PTR, SIZE)
|
|
||||||
#define ENIF_ALLOC_BINARY(SIZE, BIN) enif_alloc_binary(SIZE, BIN)
|
|
||||||
#define ENIF_COMPARE(TERM1, TERM2) enif_compare(TERM1, TERM2)
|
|
||||||
#else
|
|
||||||
#define ENIF_ALLOC(SIZE) enif_alloc(env, SIZE)
|
|
||||||
#define ENIF_FREE(PTR) enif_free(env, PTR)
|
|
||||||
#define ENIF_REALLOC(PTR, SIZE) enif_realloc(env, PTR, SIZE)
|
|
||||||
#define ENIF_ALLOC_BINARY(SIZE, BIN) enif_alloc_binary(env, SIZE, BIN)
|
|
||||||
#define ENIF_COMPARE(TERM1, TERM2) enif_compare(env, TERM1, TERM2)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ERL_NIF_TERM atom_xmlelement;
|
|
||||||
static ERL_NIF_TERM atom_xmlcdata;
|
|
||||||
|
|
||||||
struct buf {
|
|
||||||
int limit;
|
|
||||||
int len;
|
|
||||||
unsigned char *b;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int make_element(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM el);
|
|
||||||
|
|
||||||
static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
|
|
||||||
{
|
|
||||||
atom_xmlelement = enif_make_atom(env, "xmlel");
|
|
||||||
atom_xmlcdata = enif_make_atom(env, "xmlcdata");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct buf *init_buf(ErlNifEnv* env)
|
|
||||||
{
|
|
||||||
struct buf *rbuf = ENIF_ALLOC(sizeof(struct buf));
|
|
||||||
rbuf->limit = 1024;
|
|
||||||
rbuf->len = 0;
|
|
||||||
rbuf->b = ENIF_ALLOC(rbuf->limit);
|
|
||||||
return rbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy_buf(ErlNifEnv* env, struct buf *rbuf)
|
|
||||||
{
|
|
||||||
if (rbuf) {
|
|
||||||
if (rbuf->b) {
|
|
||||||
ENIF_FREE(rbuf->b);
|
|
||||||
};
|
|
||||||
ENIF_FREE(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) {
|
|
||||||
while (new_len > rbuf->limit)
|
|
||||||
rbuf->limit *= 2;
|
|
||||||
rbuf->b = ENIF_REALLOC(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(tuple[0], atom_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(tuple[0], atom_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(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL40
|
|
||||||
static ERL_NIF_TERM element_to_string(ErlNifEnv* env, int argc,
|
|
||||||
const ERL_NIF_TERM argv[])
|
|
||||||
{
|
|
||||||
return element_to(env, argc, argv, 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 in Erlang < R14A.*/
|
|
||||||
#ifdef SSL40
|
|
||||||
{"element_to_string", 1, element_to_string},
|
|
||||||
#endif
|
|
||||||
{"element_to_binary", 1, element_to_binary}
|
|
||||||
};
|
|
||||||
|
|
||||||
ERL_NIF_INIT(xml, nif_funcs, load, NULL, NULL, NULL)
|
|
57
configure.ac
57
configure.ac
|
@ -2,10 +2,10 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.53)
|
AC_PREREQ(2.53)
|
||||||
AC_INIT(ejabberd, m4_esyscmd([grep -o -E "\{vsn,.\".*\"\}" src/ejabberd.app.src | cut -d \" -f 2 | tr -d '\n']), [ejabberd@process-one.net], [ejabberd])
|
AC_PACKAGE_VERSION(3.0.0)
|
||||||
|
AC_INIT(ejabberd, 3.0.0, [ejabberd@process-one.net], [ejabberd])
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_SED
|
AC_PROG_SED
|
||||||
|
@ -22,44 +22,23 @@ AC_ERLANG_NEED_ERLC
|
||||||
AC_ERLANG_SUBST_ROOT_DIR
|
AC_ERLANG_SUBST_ROOT_DIR
|
||||||
AC_ERLANG_SUBST_LIB_DIR
|
AC_ERLANG_SUBST_LIB_DIR
|
||||||
|
|
||||||
#locating rebar
|
#locating escript
|
||||||
AC_PATH_PROG([REBAR], [rebar], [])
|
AC_PATH_PROG([ESCRIPT], [escript], [])
|
||||||
|
|
||||||
#locating make
|
#locating make
|
||||||
AC_CHECK_PROG([MAKE], [make], [make], [])
|
AC_CHECK_PROG([MAKE], [make], [make], [])
|
||||||
|
|
||||||
if test "x$REBAR" = "x"; then
|
if test "x$ESCRIPT" = "x"; then
|
||||||
AC_MSG_ERROR(['rebar' was not found])
|
AC_MSG_ERROR(['escript' was not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$MAKE" = "x"; then
|
if test "x$MAKE" = "x"; then
|
||||||
AC_MSG_ERROR(['make' was not found])
|
AC_MSG_ERROR(['make' was not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#locating iconv
|
|
||||||
AM_ICONV
|
|
||||||
#locating libexpat
|
|
||||||
AM_WITH_EXPAT
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
AC_C_CONST
|
|
||||||
|
|
||||||
# Check Erlang headers are installed
|
|
||||||
#AC_CHECK_HEADER(erl_driver.h,,[AC_MSG_ERROR([cannot find Erlang header files])])
|
|
||||||
|
|
||||||
# Change default prefix
|
# Change default prefix
|
||||||
AC_PREFIX_DEFAULT(/)
|
AC_PREFIX_DEFAULT(/)
|
||||||
|
|
||||||
# Checks for library functions.
|
|
||||||
AC_FUNC_MALLOC
|
|
||||||
AC_HEADER_STDC
|
|
||||||
|
|
||||||
#locating zlib
|
|
||||||
AM_WITH_ZLIB
|
|
||||||
|
|
||||||
AC_MOD_ENABLE(pam, no)
|
|
||||||
#locating PAM
|
|
||||||
AM_WITH_PAM
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(hipe,
|
AC_ARG_ENABLE(hipe,
|
||||||
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
|
[AC_HELP_STRING([--enable-hipe], [compile natively with HiPE, not recommended (default: no)])],
|
||||||
[case "${enableval}" in
|
[case "${enableval}" in
|
||||||
|
@ -124,25 +103,9 @@ esac],[nif=false])
|
||||||
AC_SUBST(nif)
|
AC_SUBST(nif)
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
rebar.config])
|
rebar.config
|
||||||
|
src/ejabberd.app.src
|
||||||
#openssl
|
rel/reltool.config])
|
||||||
AM_WITH_OPENSSL
|
|
||||||
# If ssl is kerberized it need krb5.h
|
|
||||||
# On RedHat and OpenBSD, krb5.h is in an unsual place:
|
|
||||||
KRB5_INCLUDE="`krb5-config --cflags 2>/dev/null`"
|
|
||||||
if test -n "$KRB5_INCLUDE" ; then
|
|
||||||
CPPFLAGS="$CPPFLAGS $KRB5_INCLUDE"
|
|
||||||
else
|
|
||||||
# For RedHat For BSD
|
|
||||||
for D in /usr/kerberos/include /usr/include/kerberos /usr/include/kerberosV
|
|
||||||
do
|
|
||||||
if test -d $D ; then
|
|
||||||
CPPFLAGS="$CPPFLAGS -I$D"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
AC_CHECK_HEADER(krb5.h,,)
|
|
||||||
|
|
||||||
ENABLEUSER=""
|
ENABLEUSER=""
|
||||||
AC_ARG_ENABLE(user,
|
AC_ARG_ENABLE(user,
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
-define(MYLANG, ejabberd_config:get_mylang()).
|
-define(MYLANG, ejabberd_config:get_mylang()).
|
||||||
|
|
||||||
-define(MSGS_DIR, <<"msgs">>).
|
-define(MSGS_DIR, filename:join(["priv", "msgs"])).
|
||||||
|
|
||||||
-define(CONFIG_PATH, <<"ejabberd.cfg">>).
|
-define(CONFIG_PATH, <<"ejabberd.cfg">>).
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,8 @@
|
||||||
|
|
||||||
-define(NS_BOB, <<"urn:xmpp:bob">>).
|
-define(NS_BOB, <<"urn:xmpp:bob">>).
|
||||||
|
|
||||||
|
-include("xml.hrl").
|
||||||
|
|
||||||
-define(STANZA_ERROR(Code, Type, Condition),
|
-define(STANZA_ERROR(Code, Type, Condition),
|
||||||
#xmlel{name = <<"error">>,
|
#xmlel{name = <<"error">>,
|
||||||
attrs = [{<<"code">>, Code}, {<<"type">>, Type}],
|
attrs = [{<<"code">>, Code}, {<<"type">>, Type}],
|
||||||
|
@ -617,19 +619,6 @@
|
||||||
|
|
||||||
-type(ljid() :: {binary(), binary(), binary()}).
|
-type(ljid() :: {binary(), binary(), binary()}).
|
||||||
|
|
||||||
-record(xmlel,
|
|
||||||
{
|
|
||||||
name = <<"">> :: binary(),
|
|
||||||
attrs = [] :: [attr()],
|
|
||||||
children = [] :: [xmlel() | cdata()]
|
|
||||||
}).
|
|
||||||
|
|
||||||
-type(cdata() :: {xmlcdata, CData::binary()}).
|
|
||||||
|
|
||||||
-type(attr() :: {Name::binary(), Value::binary()}).
|
|
||||||
|
|
||||||
-type(xmlel() :: #xmlel{}).
|
|
||||||
|
|
||||||
-record(iq, {id = <<"">> :: binary(),
|
-record(iq, {id = <<"">> :: binary(),
|
||||||
type = get :: get | set | result | error,
|
type = get :: get | set | result | error,
|
||||||
xmlns = <<"">> :: binary(),
|
xmlns = <<"">> :: binary(),
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
{erl_opts, [debug_info, {i, "include"}, {i, "deps/logger/include"}]}.
|
{erl_opts, [debug_info,
|
||||||
|
{i, "include"},
|
||||||
|
{i, "deps/logger/include"},
|
||||||
|
{i, "deps/xml/include"}]}.
|
||||||
|
|
||||||
%%{src_dirs, [asn1, src, mod_pubsub_ng]}.
|
%%{src_dirs, [asn1, src, mod_pubsub_ng]}.
|
||||||
{src_dirs, [asn1, src]}.
|
{src_dirs, [asn1, src]}.
|
||||||
|
|
||||||
|
{sub_dirs, ["rel"]}.
|
||||||
|
|
||||||
{deps, [{mysql, ".*", {git, "git://github.com/processone/mysql"}},
|
{deps, [{mysql, ".*", {git, "git://github.com/processone/mysql"}},
|
||||||
{pgsql, ".*", {git, "git://github.com/processone/pgsql"}},
|
{pgsql, ".*", {git, "git://github.com/processone/pgsql"}},
|
||||||
{iconv, ".*", {git, "git://github.com/processone/eiconv"}},
|
{iconv, ".*", {git, "git://github.com/processone/eiconv"}},
|
||||||
|
@ -11,14 +16,14 @@
|
||||||
{tls, ".*", {git, "git://github.com/processone/tls"}},
|
{tls, ".*", {git, "git://github.com/processone/tls"}},
|
||||||
{ezlib, ".*", {git, "git://github.com/processone/zlib"}},
|
{ezlib, ".*", {git, "git://github.com/processone/zlib"}},
|
||||||
{stun, ".*", {git, "git://github.com/processone/stun"}},
|
{stun, ".*", {git, "git://github.com/processone/stun"}},
|
||||||
|
{stringprep, ".*", {git, "git://github.com/processone/stringprep"}},
|
||||||
|
{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client"}},
|
||||||
|
{jiffy, ".*", {git, "git://github.com/davisp/jiffy"}},
|
||||||
|
{ibrowse, ".*", {git, "git://github.com/cmullaparthi/ibrowse"}},
|
||||||
|
{lhttpc, ".*", {git, "git://github.com/esl/lhttpc"}},
|
||||||
|
%%{xml, ".*", {git, "git://github.com/processone/xml"}},
|
||||||
{xmlrpc, ".*", {git, "git://github.com/etnt/xmlrpc"}}]}.
|
{xmlrpc, ".*", {git, "git://github.com/etnt/xmlrpc"}}]}.
|
||||||
|
|
||||||
{port_env, [{"CFLAGS", "-g -O2 -Wall"}]}.
|
|
||||||
|
|
||||||
{port_specs, [{"priv/lib/sha_drv.so", ["c_src/sha_drv.c"]},
|
|
||||||
{"priv/lib/expat_erl.so", ["c_src/expat_erl.c"]},
|
|
||||||
{"priv/lib/xml.so", ["c_src/xml.c"]}]}.
|
|
||||||
|
|
||||||
%% Local Variables:
|
%% Local Variables:
|
||||||
%% mode: erlang
|
%% mode: erlang
|
||||||
%% End:
|
%% End:
|
||||||
|
|
47
rel/reltool.config.in
Normal file
47
rel/reltool.config.in
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{sys, [
|
||||||
|
{lib_dirs, []},
|
||||||
|
{erts, [{mod_cond, derived}, {app_file, strip}]},
|
||||||
|
{app_file, strip},
|
||||||
|
{rel, "@PACKAGE_NAME@", "@PACKAGE_VERSION@",
|
||||||
|
[
|
||||||
|
kernel,
|
||||||
|
stdlib,
|
||||||
|
sasl,
|
||||||
|
ejabberd
|
||||||
|
]},
|
||||||
|
{rel, "start_clean", "",
|
||||||
|
[
|
||||||
|
kernel,
|
||||||
|
stdlib
|
||||||
|
]},
|
||||||
|
{boot_rel, "ejabberd"},
|
||||||
|
{profile, embedded},
|
||||||
|
{incl_cond, exclude},
|
||||||
|
{excl_archive_filters, [".*"]}, %% Do not archive built libs
|
||||||
|
{excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)",
|
||||||
|
"^erts.*/(doc|info|include|lib|man|src)"]},
|
||||||
|
{excl_app_filters, ["\.gitignore"]},
|
||||||
|
{app, sasl, [{incl_cond, include}]},
|
||||||
|
{app, stdlib, [{incl_cond, include}]},
|
||||||
|
{app, kernel, [{incl_cond, include}]},
|
||||||
|
{app, ejabberd, [{incl_cond, include}, {lib_dir, ".."}]}
|
||||||
|
]}.
|
||||||
|
|
||||||
|
{target_dir, "ejabberd"}.
|
||||||
|
|
||||||
|
{overlay, [
|
||||||
|
{mkdir, "log/sasl"},
|
||||||
|
{copy, "files/erl", "\{\{erts_vsn\}\}/bin/erl"},
|
||||||
|
{copy, "files/nodetool", "\{\{erts_vsn\}\}/bin/nodetool"},
|
||||||
|
{copy, "files/ejabberd", "bin/ejabberd"},
|
||||||
|
{copy, "files/ejabberd.cmd", "bin/ejabberd.cmd"},
|
||||||
|
{copy, "files/start_erl.cmd", "bin/start_erl.cmd"},
|
||||||
|
{copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"},
|
||||||
|
{copy, "files/sys.config", "releases/\{\{rel_vsn\}\}/sys.config"},
|
||||||
|
{copy, "files/vm.args", "releases/\{\{rel_vsn\}\}/vm.args"}
|
||||||
|
]}.
|
||||||
|
|
||||||
|
%%% Local Variables:
|
||||||
|
%%% mode: erlang
|
||||||
|
%%% End:
|
||||||
|
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker:
|
|
@ -1,37 +0,0 @@
|
||||||
%% $Id$
|
|
||||||
|
|
||||||
{application, ejabberd,
|
|
||||||
[{description, "ejabberd"},
|
|
||||||
{vsn, "3.0.0"},
|
|
||||||
{modules, []},
|
|
||||||
{registered, [ejabberd,
|
|
||||||
ejabberd_sup,
|
|
||||||
ejabberd_auth,
|
|
||||||
ejabberd_router,
|
|
||||||
ejabberd_router_multicast,
|
|
||||||
ejabberd_sm,
|
|
||||||
ejabberd_s2s,
|
|
||||||
ejabberd_local,
|
|
||||||
ejabberd_listeners,
|
|
||||||
ejabberd_iq_sup,
|
|
||||||
ejabberd_service_sup,
|
|
||||||
ejabberd_s2s_out_sup,
|
|
||||||
ejabberd_s2s_in_sup,
|
|
||||||
ejabberd_c2s_sup,
|
|
||||||
ejabberd_mod_roster,
|
|
||||||
ejabberd_mod_echo,
|
|
||||||
ejabberd_mod_pubsub,
|
|
||||||
ejabberd_mod_irc,
|
|
||||||
ejabberd_mod_muc,
|
|
||||||
ejabberd_offline,
|
|
||||||
random_generator
|
|
||||||
]},
|
|
||||||
{applications, [kernel, stdlib]},
|
|
||||||
{env, []},
|
|
||||||
{mod, {ejabberd_app, []}}]}.
|
|
||||||
|
|
||||||
|
|
||||||
%% Local Variables:
|
|
||||||
%% mode: erlang
|
|
||||||
%% End:
|
|
||||||
%% vim: set filetype=erlang tabstop=8:
|
|
16
src/ejabberd.app.src.in
Normal file
16
src/ejabberd.app.src.in
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
%% $Id$
|
||||||
|
|
||||||
|
{application, ejabberd,
|
||||||
|
[{description, "@PACKAGE_NAME@"},
|
||||||
|
{vsn, "@PACKAGE_VERSION@"},
|
||||||
|
{modules, []},
|
||||||
|
{registered, []},
|
||||||
|
{applications, [kernel, stdlib]},
|
||||||
|
{env, []},
|
||||||
|
{mod, {ejabberd_app, []}}]}.
|
||||||
|
|
||||||
|
|
||||||
|
%% Local Variables:
|
||||||
|
%% mode: erlang
|
||||||
|
%% End:
|
||||||
|
%% vim: set filetype=erlang tabstop=8:
|
|
@ -28,8 +28,9 @@
|
||||||
-author('alexey@process-one.net').
|
-author('alexey@process-one.net').
|
||||||
|
|
||||||
-export([start/0, stop/0,
|
-export([start/0, stop/0,
|
||||||
get_pid_file/0,
|
get_pid_file/0]).
|
||||||
get_so_path/0, get_bin_path/0]).
|
|
||||||
|
-include("logger.hrl").
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
%%ejabberd_cover:start(),
|
%%ejabberd_cover:start(),
|
||||||
|
@ -39,32 +40,6 @@ stop() ->
|
||||||
application:stop(ejabberd).
|
application:stop(ejabberd).
|
||||||
%%ejabberd_cover:stop().
|
%%ejabberd_cover:stop().
|
||||||
|
|
||||||
get_so_path() ->
|
|
||||||
case os:getenv("EJABBERD_SO_PATH") of
|
|
||||||
false ->
|
|
||||||
case code:priv_dir(ejabberd) of
|
|
||||||
{error, _} ->
|
|
||||||
".";
|
|
||||||
Path ->
|
|
||||||
filename:join([Path, "lib"])
|
|
||||||
end;
|
|
||||||
Path ->
|
|
||||||
Path
|
|
||||||
end.
|
|
||||||
|
|
||||||
get_bin_path() ->
|
|
||||||
case os:getenv("EJABBERD_BIN_PATH") of
|
|
||||||
false ->
|
|
||||||
case code:priv_dir(ejabberd) of
|
|
||||||
{error, _} ->
|
|
||||||
".";
|
|
||||||
Path ->
|
|
||||||
filename:join([Path, "bin"])
|
|
||||||
end;
|
|
||||||
Path ->
|
|
||||||
Path
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% @spec () -> false | string()
|
%% @spec () -> false | string()
|
||||||
get_pid_file() ->
|
get_pid_file() ->
|
||||||
case os:getenv("EJABBERD_PID_PATH") of
|
case os:getenv("EJABBERD_PID_PATH") of
|
||||||
|
|
|
@ -110,7 +110,7 @@ commands() ->
|
||||||
result = {res, rescode}},
|
result = {res, rescode}},
|
||||||
#ejabberd_commands{name = get_loglevel, tags = [logs, server],
|
#ejabberd_commands{name = get_loglevel, tags = [logs, server],
|
||||||
desc = "Get the current loglevel",
|
desc = "Get the current loglevel",
|
||||||
module = ejabberd_loglevel, function = get,
|
module = loglevel, function = get,
|
||||||
args = [],
|
args = [],
|
||||||
result = {leveltuple, {tuple, [{levelnumber, integer},
|
result = {leveltuple, {tuple, [{levelnumber, integer},
|
||||||
{levelatom, atom},
|
{levelatom, atom},
|
||||||
|
|
|
@ -34,20 +34,16 @@
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
|
|
||||||
%%%
|
%%%
|
||||||
%%% Application API
|
%%% Application API
|
||||||
%%%
|
%%%
|
||||||
|
|
||||||
start(normal, _Args) ->
|
start(normal, _Args) ->
|
||||||
ejabberd_loglevel:set(4),
|
loglevel:set(4),
|
||||||
write_pid_file(),
|
write_pid_file(),
|
||||||
application:start(sasl),
|
start_apps(),
|
||||||
randoms:start(),
|
randoms:start(),
|
||||||
db_init(),
|
db_init(),
|
||||||
sha:start(),
|
|
||||||
stringprep_sup:start_link(),
|
|
||||||
xml:start(),
|
|
||||||
start(),
|
start(),
|
||||||
translate:start(),
|
translate:start(),
|
||||||
acl:start(),
|
acl:start(),
|
||||||
|
@ -109,19 +105,12 @@ init() ->
|
||||||
%error_logger:logfile({open, ?LOG_PATH}),
|
%error_logger:logfile({open, ?LOG_PATH}),
|
||||||
LogPath = get_log_path(),
|
LogPath = get_log_path(),
|
||||||
error_logger:add_report_handler(ejabberd_logger_h, LogPath),
|
error_logger:add_report_handler(ejabberd_logger_h, LogPath),
|
||||||
erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
|
loop().
|
||||||
case erl_ddll:load_driver(ejabberd:get_so_path(), expat_erl) of
|
|
||||||
ok -> ok;
|
|
||||||
{error, already_loaded} -> ok
|
|
||||||
end,
|
|
||||||
Port = open_port({spawn, "expat_erl"}, [binary]),
|
|
||||||
loop(Port).
|
|
||||||
|
|
||||||
|
loop() ->
|
||||||
loop(Port) ->
|
|
||||||
receive
|
receive
|
||||||
_ ->
|
_ ->
|
||||||
loop(Port)
|
loop()
|
||||||
end.
|
end.
|
||||||
|
|
||||||
db_init() ->
|
db_init() ->
|
||||||
|
@ -250,3 +239,11 @@ delete_pid_file() ->
|
||||||
PidFilename ->
|
PidFilename ->
|
||||||
file:delete(PidFilename)
|
file:delete(PidFilename)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
start_apps() ->
|
||||||
|
application:start(sasl),
|
||||||
|
application:start(ssl),
|
||||||
|
application:start(tls),
|
||||||
|
application:start(xml),
|
||||||
|
application:start(stringprep),
|
||||||
|
application:start(ezlib).
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
plain_password_required/0]).
|
plain_password_required/0]).
|
||||||
|
|
||||||
start(_Host) ->
|
start(_Host) ->
|
||||||
case epam:start() of
|
case application:start(epam) of
|
||||||
{ok, _} -> ok;
|
{ok, _} -> ok;
|
||||||
{error, {already_started, _}} -> ok;
|
{error, {already_started, _}} -> ok;
|
||||||
Err -> Err
|
Err -> Err
|
||||||
|
|
|
@ -453,7 +453,7 @@ process_term(Term, State) ->
|
||||||
{ejabberdctl_access_commands, ACs} ->
|
{ejabberdctl_access_commands, ACs} ->
|
||||||
add_option(ejabberdctl_access_commands, ACs, State);
|
add_option(ejabberdctl_access_commands, ACs, State);
|
||||||
{loglevel, Loglevel} ->
|
{loglevel, Loglevel} ->
|
||||||
ejabberd_loglevel:set(Loglevel),
|
loglevel:set(Loglevel),
|
||||||
State;
|
State;
|
||||||
{max_fsm_queue, N} ->
|
{max_fsm_queue, N} ->
|
||||||
add_option(max_fsm_queue, N, State);
|
add_option(max_fsm_queue, N, State);
|
||||||
|
|
|
@ -157,7 +157,7 @@ handle_call({compress, Data}, _From, State) ->
|
||||||
Reply = ok,
|
Reply = ok,
|
||||||
{reply, Reply,
|
{reply, Reply,
|
||||||
State#socket_state{socket = ZlibSocket,
|
State#socket_state{socket = ZlibSocket,
|
||||||
sockmod = ejabberd_zlib},
|
sockmod = ezlib},
|
||||||
?HIBERNATE_TIMEOUT};
|
?HIBERNATE_TIMEOUT};
|
||||||
handle_call(reset_stream, _From, State) ->
|
handle_call(reset_stream, _From, State) ->
|
||||||
ejabberd_receiver:reset_stream(State#socket_state.receiver),
|
ejabberd_receiver:reset_stream(State#socket_state.receiver),
|
||||||
|
|
|
@ -44,8 +44,8 @@
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
-record(state,
|
-record(state,
|
||||||
{socket :: inet:socket() | tls:tls_socket() | ejabberd_zlib:zlib_socket(),
|
{socket :: inet:socket() | tls:tls_socket() | ezlib:zlib_socket(),
|
||||||
sock_mod = gen_tcp :: gen_tcp | tls | ejabberd_zlib,
|
sock_mod = gen_tcp :: gen_tcp | tls | ezlib,
|
||||||
shaper_state = none :: shaper:shaper(),
|
shaper_state = none :: shaper:shaper(),
|
||||||
c2s_pid :: pid(),
|
c2s_pid :: pid(),
|
||||||
max_stanza_size = infinity :: non_neg_integer() | infinity,
|
max_stanza_size = infinity :: non_neg_integer() | infinity,
|
||||||
|
@ -99,7 +99,7 @@ starttls(Pid, TLSOpts, Data) ->
|
||||||
do_call(Pid, {starttls, TLSOpts, Data}).
|
do_call(Pid, {starttls, TLSOpts, Data}).
|
||||||
|
|
||||||
-spec compress(pid(), iodata() | undefined) -> {error, any()} |
|
-spec compress(pid(), iodata() | undefined) -> {error, any()} |
|
||||||
{ok, ejabberd_zlib:zlib_socket()}.
|
{ok, ezlib:zlib_socket()}.
|
||||||
|
|
||||||
compress(Pid, Data) -> do_call(Pid, {compress, Data}).
|
compress(Pid, Data) -> do_call(Pid, {compress, Data}).
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ handle_call({compress, Data}, _From,
|
||||||
c2s_pid = C2SPid, socket = Socket, sock_mod = SockMod,
|
c2s_pid = C2SPid, socket = Socket, sock_mod = SockMod,
|
||||||
max_stanza_size = MaxStanzaSize} =
|
max_stanza_size = MaxStanzaSize} =
|
||||||
State) ->
|
State) ->
|
||||||
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(SockMod,
|
{ok, ZlibSocket} = ezlib:enable_zlib(SockMod,
|
||||||
Socket),
|
Socket),
|
||||||
if Data /= undefined -> do_send(State, Data);
|
if Data /= undefined -> do_send(State, Data);
|
||||||
true -> ok
|
true -> ok
|
||||||
|
@ -180,9 +180,9 @@ handle_call({compress, Data}, _From,
|
||||||
NewXMLStreamState = xml_stream:new(C2SPid,
|
NewXMLStreamState = xml_stream:new(C2SPid,
|
||||||
MaxStanzaSize),
|
MaxStanzaSize),
|
||||||
NewState = State#state{socket = ZlibSocket,
|
NewState = State#state{socket = ZlibSocket,
|
||||||
sock_mod = ejabberd_zlib,
|
sock_mod = ezlib,
|
||||||
xml_stream_state = NewXMLStreamState},
|
xml_stream_state = NewXMLStreamState},
|
||||||
case ejabberd_zlib:recv_data(ZlibSocket, <<"">>) of
|
case ezlib:recv_data(ZlibSocket, <<"">>) of
|
||||||
{ok, ZlibData} ->
|
{ok, ZlibData} ->
|
||||||
{reply, {ok, ZlibSocket},
|
{reply, {ok, ZlibSocket},
|
||||||
process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT};
|
process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT};
|
||||||
|
@ -250,8 +250,8 @@ handle_info({Tag, _TCPSocket, Data},
|
||||||
?HIBERNATE_TIMEOUT};
|
?HIBERNATE_TIMEOUT};
|
||||||
{error, _Reason} -> {stop, normal, State}
|
{error, _Reason} -> {stop, normal, State}
|
||||||
end;
|
end;
|
||||||
ejabberd_zlib ->
|
ezlib ->
|
||||||
case ejabberd_zlib:recv_data(Socket, Data) of
|
case ezlib:recv_data(Socket, Data) of
|
||||||
{ok, ZlibData} ->
|
{ok, ZlibData} ->
|
||||||
{noreply, process_data(ZlibData, State),
|
{noreply, process_data(ZlibData, State),
|
||||||
?HIBERNATE_TIMEOUT};
|
?HIBERNATE_TIMEOUT};
|
||||||
|
|
|
@ -43,11 +43,11 @@
|
||||||
-type sockmod() :: ejabberd_http_poll | ejabberd_bosh |
|
-type sockmod() :: ejabberd_http_poll | ejabberd_bosh |
|
||||||
ejabberd_http_bind | ejabberd_http_bindjson |
|
ejabberd_http_bind | ejabberd_http_bindjson |
|
||||||
ejabberd_http_ws | ejabberd_http_wsjson |
|
ejabberd_http_ws | ejabberd_http_wsjson |
|
||||||
gen_tcp | tls | ejabberd_zlib.
|
gen_tcp | tls | ezlib.
|
||||||
-type receiver() :: pid () | atom().
|
-type receiver() :: pid () | atom().
|
||||||
-type socket() :: pid() | inet:socket() |
|
-type socket() :: pid() | inet:socket() |
|
||||||
tls:tls_socket() |
|
tls:tls_socket() |
|
||||||
ejabberd_zlib:zlib_socket() |
|
ezlib:zlib_socket() |
|
||||||
ejabberd_bosh:bosh_socket() |
|
ejabberd_bosh:bosh_socket() |
|
||||||
ejabberd_http_ws:ws_socket() |
|
ejabberd_http_ws:ws_socket() |
|
||||||
ejabberd_http_poll:poll_socket().
|
ejabberd_http_poll:poll_socket().
|
||||||
|
@ -152,7 +152,7 @@ compress(SocketData, Data) ->
|
||||||
ejabberd_receiver:compress(SocketData#socket_state.receiver,
|
ejabberd_receiver:compress(SocketData#socket_state.receiver,
|
||||||
Data),
|
Data),
|
||||||
SocketData#socket_state{socket = ZlibSocket,
|
SocketData#socket_state{socket = ZlibSocket,
|
||||||
sockmod = ejabberd_zlib}.
|
sockmod = ezlib}.
|
||||||
|
|
||||||
reset_stream(SocketData)
|
reset_stream(SocketData)
|
||||||
when is_pid(SocketData#socket_state.receiver) ->
|
when is_pid(SocketData#socket_state.receiver) ->
|
||||||
|
@ -255,8 +255,8 @@ get_conn_type(#socket_state{sockmod = SockMod, socket = Socket}) ->
|
||||||
case SockMod of
|
case SockMod of
|
||||||
gen_tcp -> c2s;
|
gen_tcp -> c2s;
|
||||||
tls -> c2s_tls;
|
tls -> c2s_tls;
|
||||||
ejabberd_zlib ->
|
ezlib ->
|
||||||
case ejabberd_zlib:get_sockmod(Socket) of
|
case ezlib:get_sockmod(Socket) of
|
||||||
gen_tcp -> c2s_compressed;
|
gen_tcp -> c2s_compressed;
|
||||||
tls -> c2s_compressed_tls
|
tls -> c2s_compressed_tls
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -430,7 +430,6 @@ get_handle(Name) when is_binary(Name) ->
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
init([Hosts, Port, Rootdn, Passwd, Opts]) ->
|
init([Hosts, Port, Rootdn, Passwd, Opts]) ->
|
||||||
catch ssl:start(),
|
|
||||||
Encrypt = case gen_mod:get_opt(encrypt, Opts,
|
Encrypt = case gen_mod:get_opt(encrypt, Opts,
|
||||||
fun(tls) -> tls;
|
fun(tls) -> tls;
|
||||||
(starttls) -> starttls;
|
(starttls) -> starttls;
|
||||||
|
|
|
@ -39,11 +39,10 @@
|
||||||
-ifdef(USE_IBROWSE).
|
-ifdef(USE_IBROWSE).
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
ibrowse:start(),
|
application:start(ibrowse).
|
||||||
ssl:start().
|
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
ibrowse:stop().
|
application:stop(ibrowse).
|
||||||
|
|
||||||
request(Method, URL, Hdrs, Body, Opts) ->
|
request(Method, URL, Hdrs, Body, Opts) ->
|
||||||
TimeOut = proplists:get_value(timeout, Opts, infinity),
|
TimeOut = proplists:get_value(timeout, Opts, infinity),
|
||||||
|
@ -62,13 +61,10 @@ request(Method, URL, Hdrs, Body, Opts) ->
|
||||||
-ifdef(USE_LHTTPC).
|
-ifdef(USE_LHTTPC).
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
application:start(crypto),
|
application:start(lhttpc).
|
||||||
application:start(ssl),
|
|
||||||
lhttpc:start().
|
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
lhttpc:stop(),
|
application:stop(lhttpc).
|
||||||
application:stop(ssl).
|
|
||||||
|
|
||||||
request(Method, URL, Hdrs, Body, Opts) ->
|
request(Method, URL, Hdrs, Body, Opts) ->
|
||||||
TimeOut = proplists:get_value(timeout, Opts, infinity),
|
TimeOut = proplists:get_value(timeout, Opts, infinity),
|
||||||
|
@ -86,12 +82,10 @@ request(Method, URL, Hdrs, Body, Opts) ->
|
||||||
-else.
|
-else.
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
inets:start(),
|
application:start(inets).
|
||||||
ssl:start().
|
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
inets:stop(),
|
application:start(inets).
|
||||||
ssl:stop().
|
|
||||||
|
|
||||||
to_list(Str) when is_binary(Str) ->
|
to_list(Str) when is_binary(Str) ->
|
||||||
binary_to_list(Str);
|
binary_to_list(Str);
|
||||||
|
|
|
@ -66,7 +66,6 @@ start_link(Host, Opts) ->
|
||||||
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
|
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
ssl:start(),
|
|
||||||
MyHosts = case catch gen_mod:get_opt(
|
MyHosts = case catch gen_mod:get_opt(
|
||||||
hosts, Opts,
|
hosts, Opts,
|
||||||
fun(L) when is_list(L) ->
|
fun(L) when is_list(L) ->
|
||||||
|
|
|
@ -69,7 +69,6 @@ preinit(Parent, State) ->
|
||||||
stop(_Host) -> ok.
|
stop(_Host) -> ok.
|
||||||
|
|
||||||
init(State) ->
|
init(State) ->
|
||||||
inets:start(),
|
|
||||||
ets:new(bl_c2s,
|
ets:new(bl_c2s,
|
||||||
[named_table, public, {keypos, #bl_c2s.ip}]),
|
[named_table, public, {keypos, #bl_c2s.ip}]),
|
||||||
update_bl_c2s(),
|
update_bl_c2s(),
|
||||||
|
|
|
@ -99,7 +99,7 @@ stop(Host) ->
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
|
||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
iconv:start(),
|
application:start(iconv),
|
||||||
MyHost = gen_mod:get_opt_host(Host, Opts,
|
MyHost = gen_mod:get_opt_host(Host, Opts,
|
||||||
<<"irc.@HOST@">>),
|
<<"irc.@HOST@">>),
|
||||||
case gen_mod:db_type(Opts) of
|
case gen_mod:db_type(Opts) of
|
||||||
|
|
114
src/sha.erl
114
src/sha.erl
|
@ -1,114 +0,0 @@
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
%%% File : sha.erl
|
|
||||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%% Purpose :
|
|
||||||
%%% Created : 20 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2013 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., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
%%% 02111-1307 USA
|
|
||||||
%%%
|
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(sha).
|
|
||||||
|
|
||||||
-author('alexey@process-one.net').
|
|
||||||
|
|
||||||
-export([start/0, sha/1, sha1/1, sha224/1, sha256/1,
|
|
||||||
sha384/1, sha512/1, to_hexlist/1]).
|
|
||||||
|
|
||||||
-ifdef(HAVE_MD2).
|
|
||||||
|
|
||||||
-export([md2/1]).
|
|
||||||
|
|
||||||
-endif.
|
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
|
||||||
-include("logger.hrl").
|
|
||||||
|
|
||||||
-define(DRIVER, sha_drv).
|
|
||||||
|
|
||||||
start() ->
|
|
||||||
crypto:start(),
|
|
||||||
Res = case erl_ddll:load_driver(ejabberd:get_so_path(),
|
|
||||||
?DRIVER)
|
|
||||||
of
|
|
||||||
ok -> ok;
|
|
||||||
{error, already_loaded} -> ok;
|
|
||||||
Err -> Err
|
|
||||||
end,
|
|
||||||
case Res of
|
|
||||||
ok ->
|
|
||||||
Port = open_port({spawn, atom_to_list(?DRIVER)},
|
|
||||||
[binary]),
|
|
||||||
register(?DRIVER, Port);
|
|
||||||
{error, Reason} ->
|
|
||||||
?CRITICAL_MSG("unable to load driver '~s': ~s",
|
|
||||||
[driver_path(), erl_ddll:format_error(Reason)])
|
|
||||||
end.
|
|
||||||
|
|
||||||
digit_to_xchar(D) when (D >= 0) and (D < 10) -> D + 48;
|
|
||||||
digit_to_xchar(D) -> D + 87.
|
|
||||||
|
|
||||||
-spec sha(binary()) -> binary().
|
|
||||||
|
|
||||||
sha(Text) ->
|
|
||||||
Bin = crypto:sha(Text),
|
|
||||||
to_hexlist(Bin).
|
|
||||||
|
|
||||||
-spec to_hexlist(binary()) -> binary().
|
|
||||||
|
|
||||||
to_hexlist(Bin) ->
|
|
||||||
iolist_to_binary(lists:reverse(ints_to_rxstr(binary_to_list(Bin), []))).
|
|
||||||
|
|
||||||
ints_to_rxstr([], Res) -> Res;
|
|
||||||
ints_to_rxstr([N | Ns], Res) ->
|
|
||||||
ints_to_rxstr(Ns,
|
|
||||||
[digit_to_xchar(N rem 16), digit_to_xchar(N div 16)
|
|
||||||
| Res]).
|
|
||||||
|
|
||||||
-spec sha1(binary()) -> binary().
|
|
||||||
-spec sha224(binary()) -> binary().
|
|
||||||
-spec sha256(binary()) -> binary().
|
|
||||||
-spec sha384(binary()) -> binary().
|
|
||||||
-spec sha512(binary()) -> binary().
|
|
||||||
|
|
||||||
sha1(Text) -> crypto:sha(Text).
|
|
||||||
|
|
||||||
sha224(Text) -> erlang:port_control(?DRIVER, 224, Text).
|
|
||||||
|
|
||||||
sha256(Text) -> erlang:port_control(?DRIVER, 256, Text).
|
|
||||||
|
|
||||||
sha384(Text) -> erlang:port_control(?DRIVER, 384, Text).
|
|
||||||
|
|
||||||
sha512(Text) -> erlang:port_control(?DRIVER, 512, Text).
|
|
||||||
|
|
||||||
-ifdef(HAVE_MD2).
|
|
||||||
|
|
||||||
-spec md2(binary()) -> binary().
|
|
||||||
|
|
||||||
md2(Text) -> erlang:port_control(?DRIVER, 2, Text).
|
|
||||||
|
|
||||||
-endif.
|
|
||||||
|
|
||||||
driver_path() ->
|
|
||||||
Suffix = case os:type() of
|
|
||||||
{win32, _} -> ".dll";
|
|
||||||
_ -> ".so"
|
|
||||||
end,
|
|
||||||
filename:join(ejabberd:get_so_path(),
|
|
||||||
atom_to_list(?DRIVER) ++ Suffix).
|
|
433
src/xml.erl
433
src/xml.erl
|
@ -1,433 +0,0 @@
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
%%% File : xml.erl
|
|
||||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%% Purpose : XML utils
|
|
||||||
%%% Created : 20 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2013 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., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
%%% 02111-1307 USA
|
|
||||||
%%%
|
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(xml).
|
|
||||||
|
|
||||||
-author('alexey@process-one.net').
|
|
||||||
|
|
||||||
-export([element_to_binary/1,
|
|
||||||
crypt/1, make_text_node/1, remove_cdata/1,
|
|
||||||
remove_subtags/3, get_cdata/1, get_tag_cdata/1,
|
|
||||||
get_attr/2, get_attr_s/2, get_tag_attr/2,
|
|
||||||
get_tag_attr_s/2, get_subtag/2, get_subtag_cdata/2,
|
|
||||||
append_subtags/2, get_path_s/2, start/0,
|
|
||||||
replace_tag_attr/3, to_xmlel/1]).
|
|
||||||
|
|
||||||
-include("jlib.hrl").
|
|
||||||
-include("ejabberd.hrl").
|
|
||||||
-include("logger.hrl").
|
|
||||||
|
|
||||||
%% Select at compile time how to escape characters in binary text
|
|
||||||
%% nodes.
|
|
||||||
%% Can be choosen with ./configure --enable-full-xml
|
|
||||||
-ifdef(FULL_XML_SUPPORT).
|
|
||||||
|
|
||||||
-define(ESCAPE_BINARY(CData), make_text_node(CData)).
|
|
||||||
|
|
||||||
-else.
|
|
||||||
|
|
||||||
-define(ESCAPE_BINARY(CData), crypt(CData)).
|
|
||||||
|
|
||||||
-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.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(element_to_binary/1 ::
|
|
||||||
(
|
|
||||||
El :: xmlel() | cdata())
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
element_to_binary(El) ->
|
|
||||||
iolist_to_binary(element_to_string(El)).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(element_to_string/1 ::
|
|
||||||
(
|
|
||||||
El :: xmlel() | cdata())
|
|
||||||
-> string()
|
|
||||||
).
|
|
||||||
|
|
||||||
element_to_string(El) ->
|
|
||||||
case catch element_to_string_nocatch(El) of
|
|
||||||
{'EXIT', Reason} -> erlang:error({badxml, El, Reason});
|
|
||||||
Result -> Result
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec(element_to_string_nocatch/1 ::
|
|
||||||
(
|
|
||||||
El :: xmlel() | cdata())
|
|
||||||
-> iolist()
|
|
||||||
).
|
|
||||||
|
|
||||||
element_to_string_nocatch(El) ->
|
|
||||||
case El of
|
|
||||||
#xmlel{name = Name, attrs = Attrs, children = Els} ->
|
|
||||||
if Els /= [] ->
|
|
||||||
[$<, Name, attrs_to_list(Attrs), $>,
|
|
||||||
[element_to_string_nocatch(E) || E <- Els], $<, $/,
|
|
||||||
Name, $>];
|
|
||||||
true -> [$<, Name, attrs_to_list(Attrs), $/, $>]
|
|
||||||
end;
|
|
||||||
%% We do not crypt CDATA binary, but we enclose it in XML CDATA
|
|
||||||
{xmlcdata, CData} ->
|
|
||||||
?ESCAPE_BINARY(CData)
|
|
||||||
end.
|
|
||||||
|
|
||||||
attrs_to_list(Attrs) -> [attr_to_list(A) || A <- Attrs].
|
|
||||||
|
|
||||||
attr_to_list({Name, Value}) ->
|
|
||||||
[$\s, Name, $=, $', crypt(Value), $'].
|
|
||||||
|
|
||||||
crypt(S) ->
|
|
||||||
<< <<(case C of
|
|
||||||
$& -> <<"&">>;
|
|
||||||
$< -> <<"<">>;
|
|
||||||
$> -> <<">">>;
|
|
||||||
$" -> <<""">>;
|
|
||||||
$' -> <<"'">>;
|
|
||||||
_ -> <<C>>
|
|
||||||
end)/binary>>
|
|
||||||
|| <<C>> <= S >>.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(make_text_node/1 ::
|
|
||||||
(
|
|
||||||
CData :: binary())
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
make_text_node(CData) ->
|
|
||||||
case cdata_need_escape(CData) of
|
|
||||||
cdata ->
|
|
||||||
CDATA1 = <<"<![CDATA[">>,
|
|
||||||
CDATA2 = <<"]]>">>,
|
|
||||||
iolist_to_binary([CDATA1, CData, CDATA2]);
|
|
||||||
none -> CData;
|
|
||||||
{cdata, EndTokens} ->
|
|
||||||
EscapedCData = escape_cdata(CData, EndTokens),
|
|
||||||
iolist_to_binary(EscapedCData)
|
|
||||||
end.
|
|
||||||
|
|
||||||
cdata_need_escape(CData) ->
|
|
||||||
cdata_need_escape(CData, 0, false, []).
|
|
||||||
|
|
||||||
cdata_need_escape(<<>>, _, false, _) -> none;
|
|
||||||
cdata_need_escape(<<>>, _, true, []) -> cdata;
|
|
||||||
cdata_need_escape(<<>>, _, true, CDataEndTokens) ->
|
|
||||||
{cdata, lists:reverse(CDataEndTokens)};
|
|
||||||
cdata_need_escape(<<$], $], $>, Rest/binary>>,
|
|
||||||
CurrentPosition, _XMLEscape, CDataEndTokens) ->
|
|
||||||
NewPosition = CurrentPosition + 3,
|
|
||||||
cdata_need_escape(Rest, NewPosition, true,
|
|
||||||
[CurrentPosition + 1 | CDataEndTokens]);
|
|
||||||
%% Only <, & need to be escaped in XML text node
|
|
||||||
%% See reference: http://www.w3.org/TR/xml11/#syntax
|
|
||||||
cdata_need_escape(<<$<, Rest/binary>>, CurrentPosition,
|
|
||||||
_XMLEscape, CDataEndTokens) ->
|
|
||||||
cdata_need_escape(Rest, CurrentPosition + 1, true,
|
|
||||||
CDataEndTokens);
|
|
||||||
cdata_need_escape(<<$&, Rest/binary>>, CurrentPosition,
|
|
||||||
_XMLEscape, CDataEndTokens) ->
|
|
||||||
cdata_need_escape(Rest, CurrentPosition + 1, true,
|
|
||||||
CDataEndTokens);
|
|
||||||
cdata_need_escape(<<_:8, Rest/binary>>, CurrentPosition,
|
|
||||||
XMLEscape, CDataEndTokens) ->
|
|
||||||
cdata_need_escape(Rest, CurrentPosition + 1, XMLEscape,
|
|
||||||
CDataEndTokens).
|
|
||||||
|
|
||||||
escape_cdata(CData, EndTokens) ->
|
|
||||||
escape_cdata(CData, 0, EndTokens, []).
|
|
||||||
|
|
||||||
escape_cdata(<<>>, _CurrentPosition, [], Acc) ->
|
|
||||||
lists:reverse(Acc);
|
|
||||||
escape_cdata(Rest, CurrentPosition, [], Acc) ->
|
|
||||||
CDATA1 = <<"<![CDATA[">>,
|
|
||||||
CDATA2 = <<"]]>">>,
|
|
||||||
escape_cdata(<<>>, CurrentPosition, [],
|
|
||||||
[CDATA2, Rest, CDATA1 | Acc]);
|
|
||||||
escape_cdata(CData, Index, [Pos | Positions], Acc) ->
|
|
||||||
CDATA1 = <<"<![CDATA[">>,
|
|
||||||
CDATA2 = <<"]]>">>,
|
|
||||||
Split = Pos - Index,
|
|
||||||
{Part, Rest} = split_binary(CData, Split + 1),
|
|
||||||
escape_cdata(Rest, Pos + 1, Positions,
|
|
||||||
[CDATA2, Part, CDATA1 | Acc]).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(remove_cdata_p/1 ::
|
|
||||||
(
|
|
||||||
El :: xmlel() | cdata())
|
|
||||||
-> boolean()
|
|
||||||
).
|
|
||||||
|
|
||||||
remove_cdata_p(#xmlel{}) -> true;
|
|
||||||
remove_cdata_p(_) -> false.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(remove_cdata/1 ::
|
|
||||||
(
|
|
||||||
L :: [xmlel() | cdata()])
|
|
||||||
-> [xmlel()]
|
|
||||||
).
|
|
||||||
|
|
||||||
remove_cdata(L) -> [E || E <- L, remove_cdata_p(E)].
|
|
||||||
|
|
||||||
-spec(remove_subtags/3 ::
|
|
||||||
(
|
|
||||||
Xmlel :: xmlel(),
|
|
||||||
Name :: binary(),
|
|
||||||
Attr :: attr())
|
|
||||||
-> Xmlel :: xmlel()
|
|
||||||
).
|
|
||||||
|
|
||||||
remove_subtags(#xmlel{name = TagName, attrs = TagAttrs, children = Els},
|
|
||||||
Name, Attr) ->
|
|
||||||
#xmlel{name = TagName, attrs = TagAttrs,
|
|
||||||
children = remove_subtags1(Els, [], Name, Attr)}.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(remove_subtags1/4 ::
|
|
||||||
(
|
|
||||||
Els :: [xmlel() | cdata()],
|
|
||||||
NewEls :: [xmlel()],
|
|
||||||
Name :: binary(),
|
|
||||||
Attr :: attr())
|
|
||||||
-> NewEls :: [xmlel()]
|
|
||||||
).
|
|
||||||
|
|
||||||
remove_subtags1([], NewEls, _Name, _Attr) ->
|
|
||||||
lists:reverse(NewEls);
|
|
||||||
remove_subtags1([El | Els], NewEls, Name,
|
|
||||||
{AttrName, AttrValue} = Attr) ->
|
|
||||||
case El of
|
|
||||||
#xmlel{name = Name, attrs = Attrs} ->
|
|
||||||
case get_attr(AttrName, Attrs) of
|
|
||||||
false ->
|
|
||||||
remove_subtags1(Els, [El | NewEls], Name, Attr);
|
|
||||||
{value, AttrValue} ->
|
|
||||||
remove_subtags1(Els, NewEls, Name, Attr);
|
|
||||||
_ -> remove_subtags1(Els, [El | NewEls], Name, Attr)
|
|
||||||
end;
|
|
||||||
_ -> remove_subtags1(Els, [El | NewEls], Name, Attr)
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec(get_cdata/1 ::
|
|
||||||
(
|
|
||||||
L :: [xmlel() | cdata()])
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_cdata(L) ->
|
|
||||||
(iolist_to_binary(get_cdata(L, <<"">>))).
|
|
||||||
|
|
||||||
-spec(get_cdata/2 ::
|
|
||||||
(
|
|
||||||
L :: [xmlel() | cdata()],
|
|
||||||
S :: binary() | iolist())
|
|
||||||
-> binary() | iolist()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_cdata([{xmlcdata, CData} | L], S) ->
|
|
||||||
get_cdata(L, [S, CData]);
|
|
||||||
get_cdata([_ | L], S) -> get_cdata(L, S);
|
|
||||||
get_cdata([], S) -> S.
|
|
||||||
|
|
||||||
-spec(get_tag_cdata/1 ::
|
|
||||||
(
|
|
||||||
Xmlel :: xmlel())
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_tag_cdata(#xmlel{children = Els}) -> get_cdata(Els).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_attr/2 ::
|
|
||||||
(
|
|
||||||
AttrName :: binary(),
|
|
||||||
Attrs :: [attr()])
|
|
||||||
-> {value, binary()}
|
|
||||||
| false
|
|
||||||
).
|
|
||||||
|
|
||||||
get_attr(AttrName, Attrs) ->
|
|
||||||
case lists:keysearch(AttrName, 1, Attrs) of
|
|
||||||
{value, {_, Val}} -> {value, Val};
|
|
||||||
_ -> false
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_attr_s/2 ::
|
|
||||||
(
|
|
||||||
AttrName :: binary(),
|
|
||||||
Attrs :: [attr()])
|
|
||||||
-> Val :: binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_attr_s(AttrName, Attrs) ->
|
|
||||||
case lists:keysearch(AttrName, 1, Attrs) of
|
|
||||||
{value, {_, Val}} -> Val;
|
|
||||||
_ -> <<"">>
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_tag_attr/2 ::
|
|
||||||
(
|
|
||||||
AttrName :: binary(),
|
|
||||||
Xmlel :: xmlel())
|
|
||||||
-> {value, binary()}
|
|
||||||
| false
|
|
||||||
).
|
|
||||||
|
|
||||||
get_tag_attr(AttrName, #xmlel{attrs = Attrs}) ->
|
|
||||||
get_attr(AttrName, Attrs).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_tag_attr_s/2 ::
|
|
||||||
(
|
|
||||||
AttrName :: binary(),
|
|
||||||
Xmlel :: xmlel())
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_tag_attr_s(AttrName, #xmlel{attrs = Attrs}) ->
|
|
||||||
get_attr_s(AttrName, Attrs).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_subtag/2 ::
|
|
||||||
(
|
|
||||||
Xmlel :: xmlel(),
|
|
||||||
Name :: binary())
|
|
||||||
-> xmlel() | false
|
|
||||||
).
|
|
||||||
|
|
||||||
get_subtag(#xmlel{children = Els}, Name) ->
|
|
||||||
get_subtag1(Els, Name).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_subtag1/2 ::
|
|
||||||
(
|
|
||||||
Els :: [xmlel() | cdata()],
|
|
||||||
Name :: binary())
|
|
||||||
-> xmlel() | false
|
|
||||||
).
|
|
||||||
|
|
||||||
get_subtag1([El | Els], Name) ->
|
|
||||||
case El of
|
|
||||||
#xmlel{name = Name} -> El;
|
|
||||||
_ -> get_subtag1(Els, Name)
|
|
||||||
end;
|
|
||||||
get_subtag1([], _) -> false.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_subtag_cdata/2 ::
|
|
||||||
(
|
|
||||||
Tag :: xmlel(),
|
|
||||||
Name :: binary())
|
|
||||||
-> binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_subtag_cdata(Tag, Name) ->
|
|
||||||
case get_subtag(Tag, Name) of
|
|
||||||
false -> <<"">>;
|
|
||||||
Subtag -> get_tag_cdata(Subtag)
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(append_subtags/2 ::
|
|
||||||
(
|
|
||||||
Xmlel :: xmlel(),
|
|
||||||
SubTags2 :: [xmlel() | cdata()])
|
|
||||||
-> Xmlel :: xmlel()
|
|
||||||
).
|
|
||||||
|
|
||||||
append_subtags(#xmlel{name = Name, attrs = Attrs, children = SubTags1}, SubTags2) ->
|
|
||||||
#xmlel{name = Name, attrs = Attrs, children = SubTags1 ++ SubTags2}.
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(get_path_s/2 ::
|
|
||||||
(
|
|
||||||
El :: xmlel(),
|
|
||||||
Path :: [{elem, Name::binary()}
|
|
||||||
|{attr, Name::binary()}
|
|
||||||
|cdata])
|
|
||||||
-> xmlel()
|
|
||||||
| binary()
|
|
||||||
).
|
|
||||||
|
|
||||||
get_path_s(El, []) -> El;
|
|
||||||
get_path_s(El, [{elem, Name} | Path]) ->
|
|
||||||
case get_subtag(El, Name) of
|
|
||||||
false -> <<"">>;
|
|
||||||
SubEl -> get_path_s(SubEl, Path)
|
|
||||||
end;
|
|
||||||
get_path_s(El, [{attr, Name}]) ->
|
|
||||||
get_tag_attr_s(Name, El);
|
|
||||||
get_path_s(El, [cdata]) -> get_tag_cdata(El).
|
|
||||||
|
|
||||||
%%
|
|
||||||
-spec(replace_tag_attr/3 ::
|
|
||||||
(
|
|
||||||
Name :: binary(),
|
|
||||||
Value :: binary(),
|
|
||||||
Xmlel :: xmlel())
|
|
||||||
-> Xmlel :: #xmlel{
|
|
||||||
name :: binary(),
|
|
||||||
attrs :: [attr(),...],
|
|
||||||
children :: [xmlel() | cdata()]
|
|
||||||
}
|
|
||||||
).
|
|
||||||
|
|
||||||
replace_tag_attr(Name, Value, Xmlel) ->
|
|
||||||
Xmlel#xmlel{
|
|
||||||
attrs = [{Name, Value} | lists:keydelete(Name, 1, Xmlel#xmlel.attrs)]
|
|
||||||
}.
|
|
||||||
|
|
||||||
-spec to_xmlel(xmlelement() | xmlel()) -> xmlel().
|
|
||||||
|
|
||||||
to_xmlel({_, Name, Attrs, Els}) ->
|
|
||||||
#xmlel{name = iolist_to_binary(Name),
|
|
||||||
attrs = [{iolist_to_binary(K), iolist_to_binary(V)}
|
|
||||||
|| {K, V} <- Attrs],
|
|
||||||
children = [to_xmlel(El) || El <- Els]};
|
|
||||||
to_xmlel({xmlcdata, CData}) ->
|
|
||||||
{xmlcdata, iolist_to_binary(CData)}.
|
|
|
@ -1,246 +0,0 @@
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
%%% File : xml_stream.erl
|
|
||||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%% Purpose : Parse XML streams
|
|
||||||
%%% Created : 17 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2013 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., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
%%% 02111-1307 USA
|
|
||||||
%%%
|
|
||||||
%%%----------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(xml_stream).
|
|
||||||
|
|
||||||
-author('alexey@process-one.net').
|
|
||||||
|
|
||||||
-export([new/1, new/2, parse/2, close/1,
|
|
||||||
change_callback_pid/2, parse_element/1]).
|
|
||||||
|
|
||||||
-define(XML_START, 0).
|
|
||||||
|
|
||||||
-define(XML_END, 1).
|
|
||||||
|
|
||||||
-define(XML_CDATA, 2).
|
|
||||||
|
|
||||||
-define(XML_ERROR, 3).
|
|
||||||
|
|
||||||
-define(PARSE_COMMAND, 0).
|
|
||||||
|
|
||||||
-define(PARSE_FINAL_COMMAND, 1).
|
|
||||||
|
|
||||||
-record(xml_stream_state,
|
|
||||||
{callback_pid = self() :: pid(),
|
|
||||||
port :: port(),
|
|
||||||
stack = [] :: stack(),
|
|
||||||
size = 0 :: non_neg_integer(),
|
|
||||||
maxsize = infinity :: non_neg_integer() | infinity}).
|
|
||||||
|
|
||||||
-type xml_stream_el() :: {xmlstreamraw, binary()} |
|
|
||||||
{xmlstreamcdata, binary()} |
|
|
||||||
{xmlstreamelement, xmlel()} |
|
|
||||||
{xmlstreamend, binary()} |
|
|
||||||
{xmlstreamstart, binary(), [attr()]} |
|
|
||||||
{xmlstreamerror, binary()}.
|
|
||||||
|
|
||||||
-type xml_stream_state() :: #xml_stream_state{}.
|
|
||||||
-type stack() :: [xmlel()].
|
|
||||||
-type event() :: {?XML_START, {binary(), [attr()]}} |
|
|
||||||
{?XML_END, binary()} |
|
|
||||||
{?XML_CDATA, binary()} |
|
|
||||||
{?XML_ERROR, binary()}.
|
|
||||||
|
|
||||||
-export_type([xml_stream_state/0, xml_stream_el/0]).
|
|
||||||
|
|
||||||
-include("jlib.hrl").
|
|
||||||
|
|
||||||
process_data(CallbackPid, Stack, Data) ->
|
|
||||||
case Data of
|
|
||||||
{?XML_START, {Name, Attrs}} ->
|
|
||||||
if
|
|
||||||
Stack == [] ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamstart, Name, Attrs}),
|
|
||||||
%% There is no need to store name or attributes of
|
|
||||||
%% stream opening element as it is not used
|
|
||||||
%% anymore.
|
|
||||||
[xmlstreamstart];
|
|
||||||
true ->
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = []}
|
|
||||||
| Stack]
|
|
||||||
end;
|
|
||||||
{?XML_END, EndName} ->
|
|
||||||
case Stack of
|
|
||||||
[xmlstreamstart] ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamend, EndName}),
|
|
||||||
[];
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els},
|
|
||||||
xmlstreamstart] ->
|
|
||||||
NewEl = #xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = lists:reverse(Els)},
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamelement, NewEl}),
|
|
||||||
[xmlstreamstart];
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els},
|
|
||||||
#xmlel{name = Name1, attrs = Attrs1, children = Els1}
|
|
||||||
| Tail] ->
|
|
||||||
NewEl = #xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = lists:reverse(Els)},
|
|
||||||
[{xmlel, Name1, Attrs1, [NewEl | Els1]} | Tail]
|
|
||||||
end;
|
|
||||||
{?XML_CDATA, CData} ->
|
|
||||||
case Stack of
|
|
||||||
[xmlstreamstart] ->
|
|
||||||
catch gen_fsm:send_all_state_event(CallbackPid,
|
|
||||||
{xmlstreamcdata, CData}),
|
|
||||||
[xmlstreamstart];
|
|
||||||
%% Merge CDATA nodes if they are contiguous
|
|
||||||
%% This does not change the semantic: the split in
|
|
||||||
%% several CDATA nodes depends on the TCP/IP packet
|
|
||||||
%% fragmentation
|
|
||||||
[#xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = [{xmlcdata, PreviousCData} | Els]}
|
|
||||||
| Tail] ->
|
|
||||||
[#xmlel{name = Name, attrs = Attrs,
|
|
||||||
children =
|
|
||||||
[{xmlcdata,
|
|
||||||
iolist_to_binary([PreviousCData, CData])}
|
|
||||||
| Els]}
|
|
||||||
| Tail];
|
|
||||||
%% No previous CDATA
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els}
|
|
||||||
| Tail] ->
|
|
||||||
[#xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = [{xmlcdata, CData} | Els]}
|
|
||||||
| Tail];
|
|
||||||
[] -> []
|
|
||||||
end;
|
|
||||||
{?XML_ERROR, Err} ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamerror, Err})
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec new(pid()) -> xml_stream_state().
|
|
||||||
|
|
||||||
new(CallbackPid) -> new(CallbackPid, infinity).
|
|
||||||
|
|
||||||
-spec new(pid(), non_neg_integer() | infinity) -> xml_stream_state().
|
|
||||||
|
|
||||||
new(CallbackPid, MaxSize) ->
|
|
||||||
Port = open_port({spawn, "expat_erl"}, [binary]),
|
|
||||||
#xml_stream_state{callback_pid = CallbackPid,
|
|
||||||
port = Port, stack = [], size = 0, maxsize = MaxSize}.
|
|
||||||
|
|
||||||
-spec change_callback_pid(xml_stream_state(), pid()) -> xml_stream_state().
|
|
||||||
|
|
||||||
change_callback_pid(State, CallbackPid) ->
|
|
||||||
State#xml_stream_state{callback_pid = CallbackPid}.
|
|
||||||
|
|
||||||
-spec parse(xml_stream_state(), iodata()) -> xml_stream_state().
|
|
||||||
|
|
||||||
parse(#xml_stream_state{callback_pid = CallbackPid,
|
|
||||||
port = Port, stack = Stack, size = Size,
|
|
||||||
maxsize = MaxSize} =
|
|
||||||
State,
|
|
||||||
Str) ->
|
|
||||||
StrSize = byte_size(Str),
|
|
||||||
Res = port_control(Port, ?PARSE_COMMAND, Str),
|
|
||||||
{NewStack, NewSize} = lists:foldl(fun (Data,
|
|
||||||
{St, Sz}) ->
|
|
||||||
NewSt = process_data(CallbackPid,
|
|
||||||
St, Data),
|
|
||||||
case NewSt of
|
|
||||||
[_] -> {NewSt, 0};
|
|
||||||
_ -> {NewSt, Sz}
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{Stack, Size + StrSize},
|
|
||||||
binary_to_term(Res)),
|
|
||||||
if NewSize > MaxSize ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamerror,
|
|
||||||
<<"XML stanza is too big">>});
|
|
||||||
true -> ok
|
|
||||||
end,
|
|
||||||
State#xml_stream_state{stack = NewStack,
|
|
||||||
size = NewSize}.
|
|
||||||
|
|
||||||
-spec close(xml_stream_state()) -> true.
|
|
||||||
|
|
||||||
close(#xml_stream_state{port = Port}) ->
|
|
||||||
port_close(Port).
|
|
||||||
|
|
||||||
-spec parse_element(iodata()) -> xmlel() |
|
|
||||||
{error, parse_error} |
|
|
||||||
{error, binary()}.
|
|
||||||
|
|
||||||
parse_element(Str) ->
|
|
||||||
Port = open_port({spawn, "expat_erl"}, [binary]),
|
|
||||||
Res = port_control(Port, ?PARSE_FINAL_COMMAND, Str),
|
|
||||||
port_close(Port),
|
|
||||||
process_element_events(binary_to_term(Res)).
|
|
||||||
|
|
||||||
process_element_events(Events) ->
|
|
||||||
process_element_events(Events, []).
|
|
||||||
|
|
||||||
-spec process_element_events([event()], stack()) -> xmlel() |
|
|
||||||
{error, parse_error} |
|
|
||||||
{error, binary()}.
|
|
||||||
|
|
||||||
process_element_events([], _Stack) ->
|
|
||||||
{error, parse_error};
|
|
||||||
process_element_events([Event | Events], Stack) ->
|
|
||||||
case Event of
|
|
||||||
{?XML_START, {Name, Attrs}} ->
|
|
||||||
process_element_events(Events,
|
|
||||||
[#xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = []}
|
|
||||||
| Stack]);
|
|
||||||
{?XML_END, _EndName} ->
|
|
||||||
case Stack of
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els}
|
|
||||||
| Tail] ->
|
|
||||||
NewEl = #xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = lists:reverse(Els)},
|
|
||||||
case Tail of
|
|
||||||
[] ->
|
|
||||||
if Events == [] -> NewEl;
|
|
||||||
true -> {error, parse_error}
|
|
||||||
end;
|
|
||||||
[#xmlel{name = Name1, attrs = Attrs1, children = Els1}
|
|
||||||
| Tail1] ->
|
|
||||||
process_element_events(Events,
|
|
||||||
[#xmlel{name = Name1,
|
|
||||||
attrs = Attrs1,
|
|
||||||
children = [NewEl | Els1]}
|
|
||||||
| Tail1])
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
{?XML_CDATA, CData} ->
|
|
||||||
case Stack of
|
|
||||||
[#xmlel{name = Name, attrs = Attrs, children = Els}
|
|
||||||
| Tail] ->
|
|
||||||
process_element_events(Events,
|
|
||||||
[#xmlel{name = Name, attrs = Attrs,
|
|
||||||
children =
|
|
||||||
[{xmlcdata, CData} | Els]}
|
|
||||||
| Tail]);
|
|
||||||
[] -> process_element_events(Events, [])
|
|
||||||
end;
|
|
||||||
{?XML_ERROR, Err} -> {error, Err}
|
|
||||||
end.
|
|
Loading…
Reference in New Issue
Block a user