mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Delete expat_erl, stringprep, xml and xml_stream; replaced by exmpp (EJAB-991)
SVN Revision: 2409
This commit is contained in:
parent
35c1c3774c
commit
f5868a0952
1
README
1
README
@ -8,7 +8,6 @@ Quickstart guide
|
|||||||
To compile ejabberd you need:
|
To compile ejabberd you need:
|
||||||
- GNU Make
|
- GNU Make
|
||||||
- GCC
|
- GCC
|
||||||
- Libexpat 1.95 or higher
|
|
||||||
- Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
- Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
||||||
- exmpp 0.9.1 or higher
|
- exmpp 0.9.1 or higher
|
||||||
- OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL
|
- OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL
|
||||||
|
@ -335,7 +335,6 @@ as long as your system have all the dependencies.</P><P> <A NAME="installreq"></
|
|||||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||||
GNU Make
|
GNU Make
|
||||||
</LI><LI CLASS="li-itemize">GCC
|
</LI><LI CLASS="li-itemize">GCC
|
||||||
</LI><LI CLASS="li-itemize">Libexpat 1.95 or higher
|
|
||||||
</LI><LI CLASS="li-itemize">Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
</LI><LI CLASS="li-itemize">Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
||||||
</LI><LI CLASS="li-itemize">exmpp 0.9.1 or higher
|
</LI><LI CLASS="li-itemize">exmpp 0.9.1 or higher
|
||||||
</LI><LI CLASS="li-itemize">OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL encryption. Optional, highly recommended.
|
</LI><LI CLASS="li-itemize">OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL encryption. Optional, highly recommended.
|
||||||
|
@ -299,7 +299,6 @@ To compile \ejabberd{} on a `Unix-like' operating system, you need:
|
|||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item GNU Make
|
\item GNU Make
|
||||||
\item GCC
|
\item GCC
|
||||||
\item Libexpat 1.95 or higher
|
|
||||||
\item Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
\item Erlang/OTP R12B-5. Support for R13 or higher is experimental.
|
||||||
\item exmpp 0.9.1 or higher
|
\item exmpp 0.9.1 or higher
|
||||||
\item OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL encryption. Optional, highly recommended.
|
\item OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL encryption. Optional, highly recommended.
|
||||||
|
@ -63,8 +63,8 @@ endif
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
exec_prefix = @exec_prefix@
|
exec_prefix = @exec_prefix@
|
||||||
|
|
||||||
SUBDIRS = @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ stringprep @tls@ @odbc@ @ejabberd_zlib@
|
SUBDIRS = @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ @tls@ @odbc@ @ejabberd_zlib@
|
||||||
ERLSHLIBS = expat_erl.so
|
ERLSHLIBS =
|
||||||
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 = $(filter-out $(ERLBEHAVS),$(SOURCES_ALL))
|
SOURCES = $(filter-out $(ERLBEHAVS),$(SOURCES_ALL))
|
||||||
|
494
src/configure
vendored
494
src/configure
vendored
@ -578,6 +578,7 @@ PACKAGE_VERSION='version'
|
|||||||
PACKAGE_STRING='ejabberd.erl version'
|
PACKAGE_STRING='ejabberd.erl version'
|
||||||
PACKAGE_BUGREPORT='ejabberd@process-one.net'
|
PACKAGE_BUGREPORT='ejabberd@process-one.net'
|
||||||
|
|
||||||
|
ac_default_prefix=/
|
||||||
# Factoring default headers for most tests.
|
# Factoring default headers for most tests.
|
||||||
ac_includes_default="\
|
ac_includes_default="\
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -614,7 +615,6 @@ ac_includes_default="\
|
|||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif"
|
#endif"
|
||||||
|
|
||||||
ac_default_prefix=/
|
|
||||||
ac_subst_vars='SHELL
|
ac_subst_vars='SHELL
|
||||||
PATH_SEPARATOR
|
PATH_SEPARATOR
|
||||||
PACKAGE_NAME
|
PACKAGE_NAME
|
||||||
@ -669,8 +669,6 @@ ERLANG_EXMPP
|
|||||||
CPP
|
CPP
|
||||||
GREP
|
GREP
|
||||||
EGREP
|
EGREP
|
||||||
EXPAT_CFLAGS
|
|
||||||
EXPAT_LIBS
|
|
||||||
LIBOBJS
|
LIBOBJS
|
||||||
mod_muc
|
mod_muc
|
||||||
make_mod_muc
|
make_mod_muc
|
||||||
@ -1311,7 +1309,6 @@ Optional Packages:
|
|||||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||||
--with-erlang=PREFIX path to erlc and erl
|
--with-erlang=PREFIX path to erlc and erl
|
||||||
--with-expat=PREFIX prefix where EXPAT is installed
|
|
||||||
--with-zlib=PREFIX prefix where zlib is installed
|
--with-zlib=PREFIX prefix where zlib is installed
|
||||||
--with-pam=PREFIX prefix where PAM is installed
|
--with-pam=PREFIX prefix where PAM is installed
|
||||||
--with-openssl=PREFIX prefix where OPENSSL is installed
|
--with-openssl=PREFIX prefix where OPENSSL is installed
|
||||||
@ -3034,8 +3031,123 @@ echo "$as_me: error: erlang program was not properly executed, (conftest.out was
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#locating libexpat
|
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
|
||||||
|
{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
|
||||||
|
echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
|
||||||
|
if test "${ac_cv_c_const+set}" = set; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
/* FIXME: Include the comments suggested by Paul. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
/* Ultrix mips cc rejects this. */
|
||||||
|
typedef int charset[2];
|
||||||
|
const charset cs;
|
||||||
|
/* SunOS 4.1.1 cc rejects this. */
|
||||||
|
char const *const *pcpcc;
|
||||||
|
char **ppc;
|
||||||
|
/* NEC SVR4.0.2 mips cc rejects this. */
|
||||||
|
struct point {int x, y;};
|
||||||
|
static struct point const zero = {0,0};
|
||||||
|
/* AIX XL C 1.02.0.0 rejects this.
|
||||||
|
It does not let you subtract one const X* pointer from another in
|
||||||
|
an arm of an if-expression whose if-part is not a constant
|
||||||
|
expression */
|
||||||
|
const char *g = "string";
|
||||||
|
pcpcc = &g + (g ? g-g : 0);
|
||||||
|
/* HPUX 7.0 cc rejects these. */
|
||||||
|
++pcpcc;
|
||||||
|
ppc = (char**) pcpcc;
|
||||||
|
pcpcc = (char const *const *) ppc;
|
||||||
|
{ /* SCO 3.2v4 cc rejects this. */
|
||||||
|
char *t;
|
||||||
|
char const *s = 0 ? (char *) 0 : (char const *) 0;
|
||||||
|
|
||||||
|
*t++ = 0;
|
||||||
|
if (s) return 0;
|
||||||
|
}
|
||||||
|
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
|
||||||
|
int x[] = {25, 17};
|
||||||
|
const int *foo = &x[0];
|
||||||
|
++foo;
|
||||||
|
}
|
||||||
|
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
|
||||||
|
typedef const int *iptr;
|
||||||
|
iptr p = 0;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
{ /* AIX XL C 1.02.0.0 rejects this saying
|
||||||
|
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
|
||||||
|
struct s { int j; const int *ap[3]; };
|
||||||
|
struct s *b; b->j = 5;
|
||||||
|
}
|
||||||
|
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
|
||||||
|
const int foo = 10;
|
||||||
|
if (!foo) return 0;
|
||||||
|
}
|
||||||
|
return !cs[0] && !zero.x;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext
|
||||||
|
if { (ac_try="$ac_compile"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_compile") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest.$ac_objext; then
|
||||||
|
ac_cv_c_const=yes
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
ac_cv_c_const=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
|
||||||
|
echo "${ECHO_T}$ac_cv_c_const" >&6; }
|
||||||
|
if test $ac_cv_c_const = no; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define const
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Check Erlang headers are installed
|
||||||
|
#AC_CHECK_HEADER(erl_driver.h,,[AC_MSG_ERROR([cannot find Erlang header files])])
|
||||||
|
|
||||||
|
# Change default prefix
|
||||||
|
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
ac_ext=c
|
ac_ext=c
|
||||||
ac_cpp='$CPP $CPPFLAGS'
|
ac_cpp='$CPP $CPPFLAGS'
|
||||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||||
@ -3673,371 +3785,6 @@ done
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-expat was given.
|
|
||||||
if test "${with_expat+set}" = set; then
|
|
||||||
withval=$with_expat;
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
EXPAT_CFLAGS=
|
|
||||||
EXPAT_LIBS=
|
|
||||||
if test x"$with_expat" != x; then
|
|
||||||
EXPAT_CFLAGS="-I$with_expat/include"
|
|
||||||
EXPAT_LIBS="-L$with_expat/lib"
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ echo "$as_me:$LINENO: checking for XML_ParserCreate in -lexpat" >&5
|
|
||||||
echo $ECHO_N "checking for XML_ParserCreate in -lexpat... $ECHO_C" >&6; }
|
|
||||||
if test "${ac_cv_lib_expat_XML_ParserCreate+set}" = set; then
|
|
||||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
|
||||||
else
|
|
||||||
ac_check_lib_save_LIBS=$LIBS
|
|
||||||
LIBS="-lexpat "$EXPAT_LIBS" $LIBS"
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
|
|
||||||
/* Override any GCC internal prototype to avoid an error.
|
|
||||||
Use char because int might match the return type of a GCC
|
|
||||||
builtin and then its argument prototype would still apply. */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
char XML_ParserCreate ();
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
return XML_ParserCreate ();
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
|
||||||
if { (ac_try="$ac_link"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
|
||||||
(eval "$ac_link") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest$ac_exeext &&
|
|
||||||
$as_test_x conftest$ac_exeext; then
|
|
||||||
ac_cv_lib_expat_XML_ParserCreate=yes
|
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_cv_lib_expat_XML_ParserCreate=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
|
||||||
LIBS=$ac_check_lib_save_LIBS
|
|
||||||
fi
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_cv_lib_expat_XML_ParserCreate" >&5
|
|
||||||
echo "${ECHO_T}$ac_cv_lib_expat_XML_ParserCreate" >&6; }
|
|
||||||
if test $ac_cv_lib_expat_XML_ParserCreate = yes; then
|
|
||||||
EXPAT_LIBS="$EXPAT_LIBS -lexpat"
|
|
||||||
expat_found=yes
|
|
||||||
else
|
|
||||||
expat_found=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test $expat_found = no; then
|
|
||||||
{ { echo "$as_me:$LINENO: error: Could not find development files of Expat library" >&5
|
|
||||||
echo "$as_me: error: Could not find development files of Expat library" >&2;}
|
|
||||||
{ (exit 1); exit 1; }; }
|
|
||||||
fi
|
|
||||||
expat_save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $EXPAT_CFLAGS"
|
|
||||||
expat_save_CPPFLAGS="$CPPFLAGS"
|
|
||||||
CPPFLAGS="$CPPFLAGS $EXPAT_CFLAGS"
|
|
||||||
|
|
||||||
for ac_header in expat.h
|
|
||||||
do
|
|
||||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
|
||||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
|
||||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
|
||||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
|
||||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
|
||||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
|
||||||
fi
|
|
||||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
|
||||||
echo "${ECHO_T}$ac_res" >&6; }
|
|
||||||
else
|
|
||||||
# Is the header compilable?
|
|
||||||
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
|
|
||||||
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
$ac_includes_default
|
|
||||||
#include <$ac_header>
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
ac_header_compiler=yes
|
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_header_compiler=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
|
||||||
echo "${ECHO_T}$ac_header_compiler" >&6; }
|
|
||||||
|
|
||||||
# Is the header present?
|
|
||||||
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
|
|
||||||
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <$ac_header>
|
|
||||||
_ACEOF
|
|
||||||
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
|
||||||
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } >/dev/null && {
|
|
||||||
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
}; then
|
|
||||||
ac_header_preproc=yes
|
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_header_preproc=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f conftest.err conftest.$ac_ext
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
|
||||||
echo "${ECHO_T}$ac_header_preproc" >&6; }
|
|
||||||
|
|
||||||
# So? What about this header?
|
|
||||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
|
||||||
yes:no: )
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
|
|
||||||
ac_header_preproc=yes
|
|
||||||
;;
|
|
||||||
no:yes:* )
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
|
|
||||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
|
|
||||||
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
|
|
||||||
( cat <<\_ASBOX
|
|
||||||
## --------------------------------------- ##
|
|
||||||
## Report this to ejabberd@process-one.net ##
|
|
||||||
## --------------------------------------- ##
|
|
||||||
_ASBOX
|
|
||||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
|
||||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
|
||||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
|
||||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
|
||||||
else
|
|
||||||
eval "$as_ac_Header=\$ac_header_preproc"
|
|
||||||
fi
|
|
||||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
|
||||||
echo "${ECHO_T}$ac_res" >&6; }
|
|
||||||
|
|
||||||
fi
|
|
||||||
if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
|
||||||
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
|
||||||
_ACEOF
|
|
||||||
|
|
||||||
else
|
|
||||||
expat_found=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
if test $expat_found = no; then
|
|
||||||
{ { echo "$as_me:$LINENO: error: Could not find expat.h" >&5
|
|
||||||
echo "$as_me: error: Could not find expat.h" >&2;}
|
|
||||||
{ (exit 1); exit 1; }; }
|
|
||||||
fi
|
|
||||||
CFLAGS="$expat_save_CFLAGS"
|
|
||||||
CPPFLAGS="$expat_save_CPPFLAGS"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
|
|
||||||
echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
|
|
||||||
if test "${ac_cv_c_const+set}" = set; then
|
|
||||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
|
||||||
else
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
/* FIXME: Include the comments suggested by Paul. */
|
|
||||||
#ifndef __cplusplus
|
|
||||||
/* Ultrix mips cc rejects this. */
|
|
||||||
typedef int charset[2];
|
|
||||||
const charset cs;
|
|
||||||
/* SunOS 4.1.1 cc rejects this. */
|
|
||||||
char const *const *pcpcc;
|
|
||||||
char **ppc;
|
|
||||||
/* NEC SVR4.0.2 mips cc rejects this. */
|
|
||||||
struct point {int x, y;};
|
|
||||||
static struct point const zero = {0,0};
|
|
||||||
/* AIX XL C 1.02.0.0 rejects this.
|
|
||||||
It does not let you subtract one const X* pointer from another in
|
|
||||||
an arm of an if-expression whose if-part is not a constant
|
|
||||||
expression */
|
|
||||||
const char *g = "string";
|
|
||||||
pcpcc = &g + (g ? g-g : 0);
|
|
||||||
/* HPUX 7.0 cc rejects these. */
|
|
||||||
++pcpcc;
|
|
||||||
ppc = (char**) pcpcc;
|
|
||||||
pcpcc = (char const *const *) ppc;
|
|
||||||
{ /* SCO 3.2v4 cc rejects this. */
|
|
||||||
char *t;
|
|
||||||
char const *s = 0 ? (char *) 0 : (char const *) 0;
|
|
||||||
|
|
||||||
*t++ = 0;
|
|
||||||
if (s) return 0;
|
|
||||||
}
|
|
||||||
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
|
|
||||||
int x[] = {25, 17};
|
|
||||||
const int *foo = &x[0];
|
|
||||||
++foo;
|
|
||||||
}
|
|
||||||
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
|
|
||||||
typedef const int *iptr;
|
|
||||||
iptr p = 0;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
{ /* AIX XL C 1.02.0.0 rejects this saying
|
|
||||||
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
|
|
||||||
struct s { int j; const int *ap[3]; };
|
|
||||||
struct s *b; b->j = 5;
|
|
||||||
}
|
|
||||||
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
|
|
||||||
const int foo = 10;
|
|
||||||
if (!foo) return 0;
|
|
||||||
}
|
|
||||||
return !cs[0] && !zero.x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
ac_cv_c_const=yes
|
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_cv_c_const=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
|
|
||||||
echo "${ECHO_T}$ac_cv_c_const" >&6; }
|
|
||||||
if test $ac_cv_c_const = no; then
|
|
||||||
|
|
||||||
cat >>confdefs.h <<\_ACEOF
|
|
||||||
#define const
|
|
||||||
_ACEOF
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Check Erlang headers are installed
|
|
||||||
#AC_CHECK_HEADER(erl_driver.h,,[AC_MSG_ERROR([cannot find Erlang header files])])
|
|
||||||
|
|
||||||
# Change default prefix
|
|
||||||
|
|
||||||
|
|
||||||
# Checks for library functions.
|
|
||||||
|
|
||||||
for ac_header in stdlib.h
|
for ac_header in stdlib.h
|
||||||
do
|
do
|
||||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
@ -5226,7 +4973,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile $make_mod_muc $make_mod_pubsub $make_mod_proxy65 $make_eldap $make_pam $make_web stringprep/Makefile $make_tls $make_odbc $make_ejabberd_zlib"
|
ac_config_files="$ac_config_files Makefile $make_mod_muc $make_mod_pubsub $make_mod_proxy65 $make_eldap $make_pam $make_web $make_tls $make_odbc $make_ejabberd_zlib"
|
||||||
|
|
||||||
#openssl
|
#openssl
|
||||||
|
|
||||||
@ -6219,7 +5966,6 @@ do
|
|||||||
"$make_eldap") CONFIG_FILES="$CONFIG_FILES $make_eldap" ;;
|
"$make_eldap") CONFIG_FILES="$CONFIG_FILES $make_eldap" ;;
|
||||||
"$make_pam") CONFIG_FILES="$CONFIG_FILES $make_pam" ;;
|
"$make_pam") CONFIG_FILES="$CONFIG_FILES $make_pam" ;;
|
||||||
"$make_web") CONFIG_FILES="$CONFIG_FILES $make_web" ;;
|
"$make_web") CONFIG_FILES="$CONFIG_FILES $make_web" ;;
|
||||||
"stringprep/Makefile") CONFIG_FILES="$CONFIG_FILES stringprep/Makefile" ;;
|
|
||||||
"$make_tls") CONFIG_FILES="$CONFIG_FILES $make_tls" ;;
|
"$make_tls") CONFIG_FILES="$CONFIG_FILES $make_tls" ;;
|
||||||
"$make_odbc") CONFIG_FILES="$CONFIG_FILES $make_odbc" ;;
|
"$make_odbc") CONFIG_FILES="$CONFIG_FILES $make_odbc" ;;
|
||||||
"$make_ejabberd_zlib") CONFIG_FILES="$CONFIG_FILES $make_ejabberd_zlib" ;;
|
"$make_ejabberd_zlib") CONFIG_FILES="$CONFIG_FILES $make_ejabberd_zlib" ;;
|
||||||
@ -6337,8 +6083,6 @@ ERLANG_EXMPP!$ERLANG_EXMPP$ac_delim
|
|||||||
CPP!$CPP$ac_delim
|
CPP!$CPP$ac_delim
|
||||||
GREP!$GREP$ac_delim
|
GREP!$GREP$ac_delim
|
||||||
EGREP!$EGREP$ac_delim
|
EGREP!$EGREP$ac_delim
|
||||||
EXPAT_CFLAGS!$EXPAT_CFLAGS$ac_delim
|
|
||||||
EXPAT_LIBS!$EXPAT_LIBS$ac_delim
|
|
||||||
LIBOBJS!$LIBOBJS$ac_delim
|
LIBOBJS!$LIBOBJS$ac_delim
|
||||||
mod_muc!$mod_muc$ac_delim
|
mod_muc!$mod_muc$ac_delim
|
||||||
make_mod_muc!$make_mod_muc$ac_delim
|
make_mod_muc!$make_mod_muc$ac_delim
|
||||||
@ -6373,7 +6117,7 @@ INSTALLUSER!$INSTALLUSER$ac_delim
|
|||||||
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then
|
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 86; then
|
||||||
break
|
break
|
||||||
elif $ac_last_try; then
|
elif $ac_last_try; then
|
||||||
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
||||||
|
@ -14,8 +14,6 @@ fi
|
|||||||
|
|
||||||
#locating erlang
|
#locating erlang
|
||||||
AM_WITH_ERLANG
|
AM_WITH_ERLANG
|
||||||
#locating libexpat
|
|
||||||
AM_WITH_EXPAT
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
@ -98,7 +96,6 @@ AC_CONFIG_FILES([Makefile
|
|||||||
$make_eldap
|
$make_eldap
|
||||||
$make_pam
|
$make_pam
|
||||||
$make_web
|
$make_web
|
||||||
stringprep/Makefile
|
|
||||||
$make_tls
|
$make_tls
|
||||||
$make_odbc
|
$make_odbc
|
||||||
$make_ejabberd_zlib])
|
$make_ejabberd_zlib])
|
||||||
|
@ -99,19 +99,7 @@ init() ->
|
|||||||
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),
|
erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
|
||||||
case erl_ddll:load_driver(ejabberd:get_so_path(), expat_erl) of
|
ok.
|
||||||
ok -> ok;
|
|
||||||
{error, already_loaded} -> ok
|
|
||||||
end,
|
|
||||||
Port = open_port({spawn, expat_erl}, [binary]),
|
|
||||||
loop(Port).
|
|
||||||
|
|
||||||
|
|
||||||
loop(Port) ->
|
|
||||||
receive
|
|
||||||
_ ->
|
|
||||||
loop(Port)
|
|
||||||
end.
|
|
||||||
|
|
||||||
db_init() ->
|
db_init() ->
|
||||||
case mnesia:system_info(extra_db_nodes) of
|
case mnesia:system_info(extra_db_nodes) of
|
||||||
|
190
src/expat_erl.c
190
src/expat_erl.c
@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* ejabberd, Copyright (C) 2002-2009 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
|
|
||||||
|
|
||||||
ei_x_buff event_buf;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ErlDrvPort port;
|
|
||||||
XML_Parser parser;
|
|
||||||
} expat_data;
|
|
||||||
|
|
||||||
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);
|
|
||||||
ei_x_encode_string(&event_buf, name);
|
|
||||||
|
|
||||||
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);
|
|
||||||
ei_x_encode_string(&event_buf, atts[i]);
|
|
||||||
ei_x_encode_string(&event_buf, 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);
|
|
||||||
ei_x_encode_string(&event_buf, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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("UTF-8");
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
return (ErlDrvData)d;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void expat_erl_stop(ErlDrvData handle)
|
|
||||||
{
|
|
||||||
XML_ParserFree(((expat_data *)handle)->parser);
|
|
||||||
driver_free((char*)handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int expat_erl_control(ErlDrvData drv_data,
|
|
||||||
unsigned int command,
|
|
||||||
char *buf, int len,
|
|
||||||
char **rbuf, int 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);
|
|
||||||
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_string(&event_buf, 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);
|
|
||||||
|
|
||||||
*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 */
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_INIT(expat_erl) /* must match name in driver_entry */
|
|
||||||
{
|
|
||||||
return &expat_driver_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -566,7 +566,7 @@ get_user_list(_, User, Server)
|
|||||||
%% If Dir = in, User@Server is the destination account (To).
|
%% If Dir = in, User@Server is the destination account (To).
|
||||||
check_packet(_, User, Server,
|
check_packet(_, User, Server,
|
||||||
#userlist{list = List, needdb = NeedDb},
|
#userlist{list = List, needdb = NeedDb},
|
||||||
{From, To, #xmlel{name = PName, attrs = Attrs}},
|
{From, To, #xmlel{name = PName} = El},
|
||||||
Dir) when
|
Dir) when
|
||||||
PName =:= message ;
|
PName =:= message ;
|
||||||
PName =:= iq ;
|
PName =:= iq ;
|
||||||
@ -579,7 +579,7 @@ check_packet(_, User, Server,
|
|||||||
'message' -> message;
|
'message' -> message;
|
||||||
'iq' -> iq;
|
'iq' -> iq;
|
||||||
'presence' ->
|
'presence' ->
|
||||||
case xml:get_attr_s("type", Attrs) of
|
case exmpp_xml:get_attribute(El, type, '') of
|
||||||
%% notification
|
%% notification
|
||||||
'' -> presence;
|
'' -> presence;
|
||||||
'unavailable' -> presence;
|
'unavailable' -> presence;
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
# $Id$
|
|
||||||
|
|
||||||
CC = @CC@
|
|
||||||
CFLAGS = @CFLAGS@
|
|
||||||
CPPFLAGS = @CPPFLAGS@
|
|
||||||
LDFLAGS = @LDFLAGS@
|
|
||||||
LIBS = @LIBS@
|
|
||||||
|
|
||||||
ERLANG_CFLAGS = @ERLANG_CFLAGS@
|
|
||||||
ERLANG_LIBS = @ERLANG_LIBS@
|
|
||||||
|
|
||||||
# Assume Linux-style dynamic library flags
|
|
||||||
DYNAMIC_LIB_CFLAGS = -fpic -shared
|
|
||||||
ifeq ($(shell uname),Darwin)
|
|
||||||
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
|
|
||||||
endif
|
|
||||||
ifeq ($(shell uname),SunOs)
|
|
||||||
DYNAMIC_LIB_CFLAGS = -KPIC -G -z text
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
EFLAGS += -I ..
|
|
||||||
EFLAGS += -pz ..
|
|
||||||
|
|
||||||
# make debug=true to compile Erlang module with debug informations.
|
|
||||||
ifdef debug
|
|
||||||
EFLAGS+=+debug_info
|
|
||||||
endif
|
|
||||||
|
|
||||||
ERLSHLIBS = ../stringprep_drv.so
|
|
||||||
OUTDIR = ..
|
|
||||||
SOURCES = $(wildcard *.erl)
|
|
||||||
BEAMS = $(addprefix $(OUTDIR)/,$(SOURCES:.erl=.beam))
|
|
||||||
|
|
||||||
|
|
||||||
all: $(BEAMS) $(ERLSHLIBS)
|
|
||||||
|
|
||||||
$(OUTDIR)/%.beam: %.erl
|
|
||||||
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
|
|
||||||
|
|
||||||
#all: $(ERLSHLIBS)
|
|
||||||
# erl -s make all report "{outdir, \"..\"}" -noinput -s erlang halt
|
|
||||||
|
|
||||||
$(ERLSHLIBS): ../%.so: %.c uni_data.c uni_norm.c
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(INCLUDES) \
|
|
||||||
$(subst ../,,$(subst .so,.c,$@)) $(LIBS) \
|
|
||||||
$(ERLANG_LIBS) \
|
|
||||||
$(ERLANG_CFLAGS) \
|
|
||||||
-o $@ \
|
|
||||||
$(DYNAMIC_LIB_CFLAGS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(BEAMS) $(ERLSHLIBS)
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
rm -f Makefile
|
|
||||||
|
|
||||||
TAGS:
|
|
||||||
etags *.erl
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
|
|
||||||
include ..\Makefile.inc
|
|
||||||
|
|
||||||
EFLAGS = -I .. -pz ..
|
|
||||||
|
|
||||||
OUTDIR = ..
|
|
||||||
BEAMS = ..\stringprep.beam ..\stringprep_sup.beam
|
|
||||||
|
|
||||||
SOURCE = stringprep_drv.c
|
|
||||||
AUXIL = uni_data.c uni_norm.c
|
|
||||||
OBJECT = stringprep_drv.o
|
|
||||||
DLL = $(OUTDIR)\stringprep_drv.dll
|
|
||||||
|
|
||||||
ALL : $(DLL) $(BEAMS)
|
|
||||||
|
|
||||||
CLEAN :
|
|
||||||
-@erase $(DLL)
|
|
||||||
-@erase $(OUTDIR)\stringprep_drv.exp
|
|
||||||
-@erase $(OUTDIR)\stringprep_drv.lib
|
|
||||||
-@erase $(OBJECT)
|
|
||||||
-@erase $(BEAMS)
|
|
||||||
|
|
||||||
$(OUTDIR)\stringprep.beam : stringprep.erl
|
|
||||||
erlc -W $(EFLAGS) -o $(OUTDIR) stringprep.erl
|
|
||||||
|
|
||||||
$(OUTDIR)\stringprep_sup.beam : stringprep_sup.erl
|
|
||||||
erlc -W $(EFLAGS) -o $(OUTDIR) stringprep_sup.erl
|
|
||||||
|
|
||||||
CC=cl.exe
|
|
||||||
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include"
|
|
||||||
|
|
||||||
LD=link.exe
|
|
||||||
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
|
|
||||||
|
|
||||||
$(DLL) : $(OBJECT)
|
|
||||||
$(LD) $(LD_FLAGS) -out:$(DLL) $(OBJECT)
|
|
||||||
|
|
||||||
$(OBJECT) : $(SOURCE) $(AUXIL)
|
|
||||||
$(CC) $(CC_FLAGS) -c -Fo$(OBJECT) $(SOURCE)
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
|||||||
%%%----------------------------------------------------------------------
|
|
||||||
%%% File : stringprep.erl
|
|
||||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
|
||||||
%%% Purpose : Interface to stringprep_drv
|
|
||||||
%%% Created : 16 Feb 2003 by Alexey Shchepin <alexey@proces-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2009 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(stringprep).
|
|
||||||
-author('alexey@process-one.net').
|
|
||||||
|
|
||||||
-behaviour(gen_server).
|
|
||||||
|
|
||||||
-export([start/0, start_link/0,
|
|
||||||
tolower/1,
|
|
||||||
nameprep/1,
|
|
||||||
nodeprep/1,
|
|
||||||
resourceprep/1]).
|
|
||||||
|
|
||||||
%% Internal exports, call-back functions.
|
|
||||||
-export([init/1,
|
|
||||||
handle_call/3,
|
|
||||||
handle_cast/2,
|
|
||||||
handle_info/2,
|
|
||||||
code_change/3,
|
|
||||||
terminate/2]).
|
|
||||||
|
|
||||||
-define(STRINGPREP_PORT, stringprep_port).
|
|
||||||
|
|
||||||
-define(NAMEPREP_COMMAND, 1).
|
|
||||||
-define(NODEPREP_COMMAND, 2).
|
|
||||||
-define(RESOURCEPREP_COMMAND, 3).
|
|
||||||
|
|
||||||
start() ->
|
|
||||||
gen_server:start({local, ?MODULE}, ?MODULE, [], []).
|
|
||||||
|
|
||||||
start_link() ->
|
|
||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
||||||
|
|
||||||
init([]) ->
|
|
||||||
case erl_ddll:load_driver(ejabberd:get_so_path(), stringprep_drv) of
|
|
||||||
ok -> ok;
|
|
||||||
{error, already_loaded} -> ok
|
|
||||||
end,
|
|
||||||
Port = open_port({spawn, stringprep_drv}, []),
|
|
||||||
register(?STRINGPREP_PORT, Port),
|
|
||||||
{ok, Port}.
|
|
||||||
|
|
||||||
|
|
||||||
%%% --------------------------------------------------------
|
|
||||||
%%% The call-back functions.
|
|
||||||
%%% --------------------------------------------------------
|
|
||||||
|
|
||||||
handle_call(_, _, State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
handle_cast(_, State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
handle_info({'EXIT', Port, Reason}, Port) ->
|
|
||||||
{stop, {port_died, Reason}, Port};
|
|
||||||
handle_info({'EXIT', _Pid, _Reason}, Port) ->
|
|
||||||
{noreply, Port};
|
|
||||||
handle_info(_, State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
|
||||||
{ok, State}.
|
|
||||||
|
|
||||||
terminate(_Reason, Port) ->
|
|
||||||
Port ! {self, close},
|
|
||||||
ok.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tolower(String) ->
|
|
||||||
control(0, String).
|
|
||||||
|
|
||||||
nameprep(String) ->
|
|
||||||
control(?NAMEPREP_COMMAND, String).
|
|
||||||
|
|
||||||
nodeprep(String) ->
|
|
||||||
control(?NODEPREP_COMMAND, String).
|
|
||||||
|
|
||||||
resourceprep(String) ->
|
|
||||||
control(?RESOURCEPREP_COMMAND, String).
|
|
||||||
|
|
||||||
control(Command, String) ->
|
|
||||||
case port_control(?STRINGPREP_PORT, Command, String) of
|
|
||||||
[0 | _] -> error;
|
|
||||||
[1 | Res] -> Res
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,410 +0,0 @@
|
|||||||
/*
|
|
||||||
* ejabberd, Copyright (C) 2002-2009 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 "uni_data.c"
|
|
||||||
#include "uni_norm.c"
|
|
||||||
|
|
||||||
#define NAMEPREP_COMMAND 1
|
|
||||||
#define NODEPREP_COMMAND 2
|
|
||||||
#define RESOURCEPREP_COMMAND 3
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ErlDrvPort port;
|
|
||||||
} stringprep_data;
|
|
||||||
|
|
||||||
|
|
||||||
static ErlDrvData stringprep_erl_start(ErlDrvPort port, char *buff)
|
|
||||||
{
|
|
||||||
stringprep_data* d = (stringprep_data*)driver_alloc(sizeof(stringprep_data));
|
|
||||||
d->port = port;
|
|
||||||
|
|
||||||
//set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
|
|
||||||
|
|
||||||
return (ErlDrvData)d;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stringprep_erl_stop(ErlDrvData handle)
|
|
||||||
{
|
|
||||||
driver_free((char*)handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Hangul constants */
|
|
||||||
#define SBase 0xAC00
|
|
||||||
#define LBase 0x1100
|
|
||||||
#define VBase 0x1161
|
|
||||||
#define TBase 0x11A7
|
|
||||||
#define LCount 19
|
|
||||||
#define VCount 21
|
|
||||||
#define TCount 28
|
|
||||||
#define NCount (VCount * TCount)
|
|
||||||
#define SCount (LCount * NCount)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "canonical_ordering" and "compose" functions are based on nfkc.c from Gnome
|
|
||||||
* library
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void canonical_ordering(int *str, int len)
|
|
||||||
{
|
|
||||||
int i, j, t;
|
|
||||||
int last, next;
|
|
||||||
|
|
||||||
last = GetUniCharCClass(str[0]);
|
|
||||||
for (i = 0; i < len - 1; i++)
|
|
||||||
{
|
|
||||||
next = GetUniCharCClass(str[i + 1]);
|
|
||||||
if (next != 0 && last > next)
|
|
||||||
{
|
|
||||||
for (j = i; j >= 0; j--)
|
|
||||||
{
|
|
||||||
if (GetUniCharCClass(str[j]) <= next)
|
|
||||||
break;
|
|
||||||
t = str[j + 1];
|
|
||||||
str[j + 1] = str[j];
|
|
||||||
str[j] = t;
|
|
||||||
}
|
|
||||||
next = last;
|
|
||||||
}
|
|
||||||
last = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int compose(int ch1, int ch2)
|
|
||||||
{
|
|
||||||
int info1, info2;
|
|
||||||
|
|
||||||
if (LBase <= ch1 && ch1 < LBase + LCount &&
|
|
||||||
VBase <= ch2 && ch2 < VBase + VCount) {
|
|
||||||
return SBase + ((ch1 - LBase) * VCount + (ch2 - VBase)) * TCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SBase <= ch1 && ch1 < SBase + SCount && ((ch1 - SBase) % TCount) == 0 &&
|
|
||||||
TBase <= ch2 && ch2 < TBase + TCount) {
|
|
||||||
return ch1 + ch2 - TBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
info1 = GetUniCharCompInfo(ch1);
|
|
||||||
if (info1 != -1 && info1 & CompSingleMask) {
|
|
||||||
if (!(info1 & CompSecondMask) &&
|
|
||||||
ch2 == compFirstList[info1 & CompMask][0]) {
|
|
||||||
return compFirstList[info1 & CompMask][1];
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
info2 = GetUniCharCompInfo(ch2);
|
|
||||||
if (info2 != -1 && info2 & CompSingleMask) {
|
|
||||||
if ((info2 & CompSecondMask) &&
|
|
||||||
ch1 == compSecondList[info2 & CompMask][0]) {
|
|
||||||
return compSecondList[info2 & CompMask][1];
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info1 != -1 && info2 != -1 &&
|
|
||||||
!(info1 & CompSecondMask) && (info2 & CompSecondMask))
|
|
||||||
return compBothList[info1][info2 & CompMask];
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ADD_UCHAR(ruc) \
|
|
||||||
if (ruc <= 0x7F) { \
|
|
||||||
if (pos >= size) { \
|
|
||||||
size = 2*size + 1; \
|
|
||||||
rstring = driver_realloc(rstring, size); \
|
|
||||||
} \
|
|
||||||
rstring[pos] = (char) ruc; \
|
|
||||||
pos++; \
|
|
||||||
} else if (ruc <= 0x7FF) { \
|
|
||||||
if (pos + 1 >= size) { \
|
|
||||||
size = 2*size + 2; \
|
|
||||||
rstring = driver_realloc(rstring, size); \
|
|
||||||
} \
|
|
||||||
rstring[pos] = (char) ((ruc >> 6) | 0xC0); \
|
|
||||||
rstring[pos+1] = (char) ((ruc | 0x80) & 0xBF); \
|
|
||||||
pos += 2; \
|
|
||||||
} else if (ruc <= 0xFFFF) { \
|
|
||||||
if (pos + 2 >= size) { \
|
|
||||||
size = 2*size + 3; \
|
|
||||||
rstring = driver_realloc(rstring, size); \
|
|
||||||
} \
|
|
||||||
rstring[pos] = (char) ((ruc >> 12) | 0xE0); \
|
|
||||||
rstring[pos+1] = (char) (((ruc >> 6) | 0x80) & 0xBF); \
|
|
||||||
rstring[pos+2] = (char) ((ruc | 0x80) & 0xBF); \
|
|
||||||
pos += 3; \
|
|
||||||
} else if (ruc <= 0x1FFFFF) { \
|
|
||||||
if (pos + 3 >= size) { \
|
|
||||||
size = 2*size + 4; \
|
|
||||||
rstring = driver_realloc(rstring, size); \
|
|
||||||
} \
|
|
||||||
rstring[pos] = (char) ((ruc >> 18) | 0xF0); \
|
|
||||||
rstring[pos+1] = (char) (((ruc >> 12) | 0x80) & 0xBF); \
|
|
||||||
rstring[pos+2] = (char) (((ruc >> 6) | 0x80) & 0xBF); \
|
|
||||||
rstring[pos+3] = (char) ((ruc | 0x80) & 0xBF); \
|
|
||||||
pos += 4; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ADD_UCHAR32(str, pos, len, ch) \
|
|
||||||
if (pos >= len) { \
|
|
||||||
len = 2*len + 1; \
|
|
||||||
str = driver_realloc(str, len * sizeof(int)); \
|
|
||||||
} \
|
|
||||||
str[pos] = ch; \
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
|
|
||||||
#define ADD_DECOMP(ruc) \
|
|
||||||
info = GetUniCharDecompInfo(ruc); \
|
|
||||||
if (info >= 0) { \
|
|
||||||
decomp_len = GetDecompLen(info); \
|
|
||||||
decomp_shift = GetDecompShift(info); \
|
|
||||||
for (j = 0; j < decomp_len; j++) { \
|
|
||||||
ADD_UCHAR32(str32, str32pos, str32len, \
|
|
||||||
decompList[decomp_shift + j]); \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
ADD_UCHAR32(str32, str32pos, str32len, ruc); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int stringprep_erl_control(ErlDrvData drv_data,
|
|
||||||
unsigned int command,
|
|
||||||
char *buf, int len,
|
|
||||||
char **rbuf, int rlen)
|
|
||||||
{
|
|
||||||
int i, j, pos=1;
|
|
||||||
unsigned char c;
|
|
||||||
int bad = 0;
|
|
||||||
int uc = 0, ruc;
|
|
||||||
int size;
|
|
||||||
int info;
|
|
||||||
int prohibit = 0, tolower = 0;
|
|
||||||
char *rstring;
|
|
||||||
int *mc;
|
|
||||||
int *str32;
|
|
||||||
int str32len, str32pos = 0;
|
|
||||||
int decomp_len, decomp_shift;
|
|
||||||
int comp_pos, comp_starter_pos;
|
|
||||||
int cclass_prev, cclass2;
|
|
||||||
int ch1, ch2;
|
|
||||||
int first_ral, last_ral, have_ral, have_l;
|
|
||||||
|
|
||||||
size = len + 1;
|
|
||||||
|
|
||||||
rstring = driver_alloc(size);
|
|
||||||
rstring[0] = 0;
|
|
||||||
|
|
||||||
str32len = len + 1;
|
|
||||||
|
|
||||||
str32 = driver_alloc(str32len * sizeof(int));
|
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
prohibit = ACMask;
|
|
||||||
tolower = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NAMEPREP_COMMAND:
|
|
||||||
prohibit = ACMask;
|
|
||||||
tolower = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODEPREP_COMMAND:
|
|
||||||
prohibit = ACMask | C11Mask | C21Mask | XNPMask;
|
|
||||||
tolower = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RESOURCEPREP_COMMAND:
|
|
||||||
prohibit = ACMask | C21Mask;
|
|
||||||
tolower = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
c = buf[i];
|
|
||||||
if (c < 0x80) {
|
|
||||||
uc = c;
|
|
||||||
} else if (c < 0xC0) {
|
|
||||||
bad = 1;
|
|
||||||
} else if (c < 0xE0) {
|
|
||||||
if (i+1 < len && (buf[i+1] & 0xC0) == 0x80) {
|
|
||||||
uc = ((c & 0x1F) << 6) | (buf[i+1] & 0x3F);
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
bad = 1;
|
|
||||||
}
|
|
||||||
} else if (c < 0xF0) {
|
|
||||||
if (i+2 < len && (buf[i+1] & 0xC0) == 0x80 &&
|
|
||||||
(buf[i+2] & 0xC0) == 0x80) {
|
|
||||||
uc = ((c & 0x0F) << 12)
|
|
||||||
| ((buf[i+1] & 0x3F) << 6)
|
|
||||||
| (buf[i+2] & 0x3F);
|
|
||||||
i += 2;
|
|
||||||
} else {
|
|
||||||
bad = 1;
|
|
||||||
}
|
|
||||||
} else if (c < 0xF8) {
|
|
||||||
if (i+3 < len &&
|
|
||||||
(buf[i+1] & 0xC0) == 0x80 &&
|
|
||||||
(buf[i+2] & 0xC0) == 0x80 &&
|
|
||||||
(buf[i+3] & 0xC0) == 0x80) {
|
|
||||||
uc = ((c & 0x07) << 18)
|
|
||||||
| ((buf[i+1] & 0x3F) << 12)
|
|
||||||
| ((buf[i+2] & 0x3F) << 6)
|
|
||||||
| (buf[i+3] & 0x3F);
|
|
||||||
i += 3;
|
|
||||||
if (uc > 0x10FFFF)
|
|
||||||
bad = 1;
|
|
||||||
} else {
|
|
||||||
bad = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bad = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bad) {
|
|
||||||
*rbuf = rstring;
|
|
||||||
driver_free(str32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = GetUniCharInfo(uc);
|
|
||||||
|
|
||||||
if (!(info & B1Mask))
|
|
||||||
{
|
|
||||||
if (tolower) {
|
|
||||||
if (!(info & MCMask))
|
|
||||||
{
|
|
||||||
ruc = uc + GetDelta(info);
|
|
||||||
ADD_DECOMP(ruc);
|
|
||||||
} else {
|
|
||||||
mc = GetMC(info);
|
|
||||||
for (j = 1; j <= mc[0]; j++) {
|
|
||||||
ruc = mc[j];
|
|
||||||
ADD_DECOMP(ruc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ruc = uc;
|
|
||||||
ADD_DECOMP(ruc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str32pos == 0) {
|
|
||||||
rstring[0] = 1;
|
|
||||||
*rbuf = rstring;
|
|
||||||
driver_free(str32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
canonical_ordering(str32, str32pos);
|
|
||||||
|
|
||||||
comp_pos = 1;
|
|
||||||
comp_starter_pos = 0;
|
|
||||||
ch1 = str32[0];
|
|
||||||
cclass_prev = GetUniCharCClass(ch1);
|
|
||||||
for (i = 1; i < str32pos; i++)
|
|
||||||
{
|
|
||||||
ch2 = str32[i];
|
|
||||||
cclass2 = GetUniCharCClass(ch2);
|
|
||||||
if ((cclass_prev == 0 || cclass2 > cclass_prev) &&
|
|
||||||
(ruc = compose(ch1, ch2))) {
|
|
||||||
ch1 = ruc;
|
|
||||||
} else {
|
|
||||||
if (cclass2 == 0) {
|
|
||||||
str32[comp_starter_pos] = ch1;
|
|
||||||
comp_starter_pos = comp_pos++;
|
|
||||||
ch1 = ch2;
|
|
||||||
cclass_prev = 0;
|
|
||||||
} else {
|
|
||||||
str32[comp_pos++] = ch2;
|
|
||||||
cclass_prev = cclass2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str32[comp_starter_pos] = ch1;
|
|
||||||
str32pos = comp_pos;
|
|
||||||
|
|
||||||
last_ral = have_ral = have_l = 0;
|
|
||||||
info = GetUniCharInfo(str32[0]);
|
|
||||||
first_ral = info & D1Mask;
|
|
||||||
for (i = 0; i < str32pos; i++)
|
|
||||||
{
|
|
||||||
ruc = str32[i];
|
|
||||||
info = GetUniCharInfo(ruc);
|
|
||||||
if (info & prohibit) {
|
|
||||||
*rbuf = rstring;
|
|
||||||
driver_free(str32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
last_ral = info & D1Mask;
|
|
||||||
have_ral = have_ral || last_ral;
|
|
||||||
have_l = info & D2Mask;
|
|
||||||
ADD_UCHAR(ruc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_ral && (!first_ral || !last_ral || have_l)) {
|
|
||||||
*rbuf = rstring;
|
|
||||||
driver_free(str32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rstring[0] = 1;
|
|
||||||
*rbuf = rstring;
|
|
||||||
driver_free(str32);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ErlDrvEntry stringprep_driver_entry = {
|
|
||||||
NULL, /* F_PTR init, N/A */
|
|
||||||
stringprep_erl_start, /* L_PTR start, called when port is opened */
|
|
||||||
stringprep_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 */
|
|
||||||
"stringprep_drv", /* char *driver_name, the argument to open_port */
|
|
||||||
NULL, /* F_PTR finish, called when unloaded */
|
|
||||||
NULL, /* handle */
|
|
||||||
stringprep_erl_control, /* F_PTR control, port_command callback */
|
|
||||||
NULL, /* F_PTR timeout, reserved */
|
|
||||||
NULL /* F_PTR outputv, reserved */
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_INIT(stringprep_erl) /* must match name in driver_entry */
|
|
||||||
{
|
|
||||||
return &stringprep_driver_entry;
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% File : stringprep_sup.erl
|
|
||||||
%%% Author : Mickael Remond <mremond@process-one.net>
|
|
||||||
%%% Description : Supervisor for the Stringprep worker.
|
|
||||||
%%% Created : 29 Jun 2007 by Mickael Remond <mremond@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2009 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(stringprep_sup).
|
|
||||||
|
|
||||||
-behaviour(supervisor).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([start_link/0]).
|
|
||||||
|
|
||||||
%% Supervisor callbacks
|
|
||||||
-export([init/1]).
|
|
||||||
|
|
||||||
-define(SERVER, ?MODULE).
|
|
||||||
|
|
||||||
%%====================================================================
|
|
||||||
%% API functions
|
|
||||||
%%====================================================================
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
|
||||||
%% Description: Starts the supervisor
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
start_link() ->
|
|
||||||
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
|
|
||||||
|
|
||||||
%%====================================================================
|
|
||||||
%% Supervisor callbacks
|
|
||||||
%%====================================================================
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
|
|
||||||
%% ignore |
|
|
||||||
%% {error, Reason}
|
|
||||||
%% Description: Whenever a supervisor is started using
|
|
||||||
%% supervisor:start_link/[2,3], this function is called by the new process
|
|
||||||
%% to find out about restart strategy, maximum restart frequency and child
|
|
||||||
%% specifications.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
init([]) ->
|
|
||||||
StringPrep = {stringprep,
|
|
||||||
{stringprep, start_link, []},
|
|
||||||
permanent,
|
|
||||||
brutal_kill,
|
|
||||||
worker,
|
|
||||||
[stringprep]},
|
|
||||||
{ok,{{one_for_all,10,1}, [StringPrep]}}.
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,437 +0,0 @@
|
|||||||
# uni_parse.tcl --
|
|
||||||
#
|
|
||||||
# This program parses the UnicodeData file and generates the
|
|
||||||
# corresponding uni_data.c file with compressed character
|
|
||||||
# data tables. The input to this program should be rfc3454.txt
|
|
||||||
#
|
|
||||||
# Copyright (c) 1998-1999 by Scriptics Corporation.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Modified for ejabberd by Alexey Shchepin
|
|
||||||
#
|
|
||||||
# RCS: @(#) $Id$
|
|
||||||
|
|
||||||
|
|
||||||
namespace eval uni {
|
|
||||||
set shift 8; # number of bits of data within a page
|
|
||||||
# This value can be adjusted to find the
|
|
||||||
# best split to minimize table size
|
|
||||||
|
|
||||||
variable pMap; # map from page to page index, each entry is
|
|
||||||
# an index into the pages table, indexed by
|
|
||||||
# page number
|
|
||||||
variable pages; # map from page index to page info, each
|
|
||||||
# entry is a list of indices into the groups
|
|
||||||
# table, the list is indexed by the offset
|
|
||||||
variable groups; # list of character info values, indexed by
|
|
||||||
# group number, initialized with the
|
|
||||||
# unassigned character group
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::getValue {i} {
|
|
||||||
variable casemap
|
|
||||||
variable casemap2
|
|
||||||
variable tablemap
|
|
||||||
|
|
||||||
if {[info exists tablemap($i)]} {
|
|
||||||
set tables $tablemap($i)
|
|
||||||
} else {
|
|
||||||
set tables {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[info exists casemap2($i)]} {
|
|
||||||
set multicase 1
|
|
||||||
set delta $casemap2($i)
|
|
||||||
} else {
|
|
||||||
set multicase 0
|
|
||||||
if {[info exists casemap($i)]} {
|
|
||||||
set delta $casemap($i)
|
|
||||||
} else {
|
|
||||||
set delta 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {abs($delta) > 0xFFFFF} {
|
|
||||||
puts "delta must be less than 22 bits wide"
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
set ac 0
|
|
||||||
set c11 0
|
|
||||||
set c21 0
|
|
||||||
set b1 0
|
|
||||||
set d1 0
|
|
||||||
set d2 0
|
|
||||||
set xnp 0
|
|
||||||
|
|
||||||
foreach tab $tables {
|
|
||||||
switch -glob -- $tab {
|
|
||||||
C.1.1 {set c11 1}
|
|
||||||
C.2.1 {set c21 1}
|
|
||||||
C.* {set ac 1}
|
|
||||||
A.1 {set ac 1}
|
|
||||||
B.1 {set b1 1}
|
|
||||||
D.1 {set d1 1}
|
|
||||||
D.2 {set d2 1}
|
|
||||||
XNP {set xnp 1}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set val [expr {($ac << 0) |
|
|
||||||
($c11 << 1) |
|
|
||||||
($c21 << 2) |
|
|
||||||
($b1 << 3) |
|
|
||||||
($d1 << 4) |
|
|
||||||
($d2 << 5) |
|
|
||||||
($xnp << 6) |
|
|
||||||
($multicase << 7) |
|
|
||||||
($delta << 11)}]
|
|
||||||
|
|
||||||
return $val
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::getGroup {value} {
|
|
||||||
variable groups
|
|
||||||
|
|
||||||
set gIndex [lsearch -exact $groups $value]
|
|
||||||
if {$gIndex == -1} {
|
|
||||||
set gIndex [llength $groups]
|
|
||||||
lappend groups $value
|
|
||||||
}
|
|
||||||
return $gIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::addPage {info} {
|
|
||||||
variable pMap
|
|
||||||
variable pages
|
|
||||||
variable pages_map
|
|
||||||
|
|
||||||
if {[info exists pages_map($info)]} {
|
|
||||||
lappend pMap $pages_map($info)
|
|
||||||
} else {
|
|
||||||
set pIndex [llength $pages]
|
|
||||||
lappend pages $info
|
|
||||||
set pages_map($info) $pIndex
|
|
||||||
lappend pMap $pIndex
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
proc uni::load_tables {data} {
|
|
||||||
variable casemap
|
|
||||||
variable casemap2
|
|
||||||
variable multicasemap
|
|
||||||
variable tablemap
|
|
||||||
|
|
||||||
set multicasemap {}
|
|
||||||
set table ""
|
|
||||||
|
|
||||||
foreach line [split $data \n] {
|
|
||||||
if {$table == ""} {
|
|
||||||
if {[regexp { ----- Start Table (.*) -----} $line temp table]} {
|
|
||||||
#puts "Start table '$table'"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if {[regexp { ----- End Table (.*) -----} $line temp table1]} {
|
|
||||||
set table ""
|
|
||||||
} else {
|
|
||||||
if {$table == "B.1"} {
|
|
||||||
if {[regexp {^ ([[:xdigit:]]+); ;} $line \
|
|
||||||
temp val]} {
|
|
||||||
scan $val %x val
|
|
||||||
if {$val <= 0x10ffff} {
|
|
||||||
lappend tablemap($val) $table
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif {$table == "B.2"} {
|
|
||||||
if {[regexp {^ ([[:xdigit:]]+); ([[:xdigit:]]+);} $line \
|
|
||||||
temp from to]} {
|
|
||||||
scan $from %x from
|
|
||||||
scan $to %x to
|
|
||||||
if {$from <= 0x10ffff && $to <= 0x10ffff} {
|
|
||||||
set casemap($from) [expr {$to - $from}]
|
|
||||||
}
|
|
||||||
} elseif {[regexp {^ ([[:xdigit:]]+); ([[:xdigit:]]+) ([[:xdigit:]]+);} $line \
|
|
||||||
temp from to1 to2]} {
|
|
||||||
scan $from %x from
|
|
||||||
scan $to1 %x to1
|
|
||||||
scan $to2 %x to2
|
|
||||||
if {$from <= 0x10ffff && \
|
|
||||||
$to1 <= 0x10ffff && $to2 <= 0x10ffff} {
|
|
||||||
set casemap2($from) [llength $multicasemap]
|
|
||||||
lappend multicasemap [list $to1 $to2]
|
|
||||||
}
|
|
||||||
} elseif {[regexp {^ ([[:xdigit:]]+); ([[:xdigit:]]+) ([[:xdigit:]]+) ([[:xdigit:]]+);} $line \
|
|
||||||
temp from to1 to2 to3]} {
|
|
||||||
scan $from %x from
|
|
||||||
scan $to1 %x to1
|
|
||||||
scan $to2 %x to2
|
|
||||||
scan $to3 %x to3
|
|
||||||
if {$from <= 0x10ffff && \
|
|
||||||
$to1 <= 0x10ffff && $to2 <= 0x10ffff && \
|
|
||||||
$to3 <= 0x10ffff} {
|
|
||||||
set casemap2($from) [llength $multicasemap]
|
|
||||||
lappend multicasemap [list $to1 $to2 $to3]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#puts "missed: $line"
|
|
||||||
}
|
|
||||||
|
|
||||||
} elseif {$table != "B.3"} {
|
|
||||||
if {[regexp {^ ([[:xdigit:]]+)-([[:xdigit:]]+)} $line \
|
|
||||||
temp from to]} {
|
|
||||||
scan $from %x from
|
|
||||||
scan $to %x to
|
|
||||||
for {set i $from} {$i <= $to && $i <= 0x10ffff} {incr i} {
|
|
||||||
lappend tablemap($i) $table
|
|
||||||
}
|
|
||||||
} elseif {[regexp {^ ([[:xdigit:]]+)} $line \
|
|
||||||
temp val]} {
|
|
||||||
scan $val %x val
|
|
||||||
if {$val <= 0x10ffff} {
|
|
||||||
lappend tablemap($val) $table
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# XMPP nodeprep prohibited
|
|
||||||
foreach val {22 26 27 2f 3a 3c 3e 40} {
|
|
||||||
scan $val %x val
|
|
||||||
lappend tablemap($val) XNP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::buildTables {} {
|
|
||||||
variable shift
|
|
||||||
|
|
||||||
variable casemap
|
|
||||||
variable tablemap
|
|
||||||
|
|
||||||
variable pMap {}
|
|
||||||
variable pages {}
|
|
||||||
variable groups {}
|
|
||||||
set info {} ;# temporary page info
|
|
||||||
|
|
||||||
set mask [expr {(1 << $shift) - 1}]
|
|
||||||
|
|
||||||
set next 0
|
|
||||||
|
|
||||||
for {set i 0} {$i <= 0x10ffff} {incr i} {
|
|
||||||
set gIndex [getGroup [getValue $i]]
|
|
||||||
|
|
||||||
# Split character index into offset and page number
|
|
||||||
set offset [expr {$i & $mask}]
|
|
||||||
set page [expr {($i >> $shift)}]
|
|
||||||
|
|
||||||
# Add the group index to the info for the current page
|
|
||||||
lappend info $gIndex
|
|
||||||
|
|
||||||
# If this is the last entry in the page, add the page
|
|
||||||
if {$offset == $mask} {
|
|
||||||
addPage $info
|
|
||||||
set info {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::main {} {
|
|
||||||
global argc argv0 argv
|
|
||||||
variable pMap
|
|
||||||
variable pages
|
|
||||||
variable groups
|
|
||||||
variable shift
|
|
||||||
variable multicasemap
|
|
||||||
|
|
||||||
if {$argc != 2} {
|
|
||||||
puts stderr "\nusage: $argv0 <datafile> <outdir>\n"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
set f [open [lindex $argv 0] r]
|
|
||||||
set data [read $f]
|
|
||||||
close $f
|
|
||||||
|
|
||||||
load_tables $data
|
|
||||||
buildTables
|
|
||||||
puts "X = [llength $pMap] Y= [llength $pages] A= [llength $groups]"
|
|
||||||
set size [expr {[llength $pMap] + [llength $pages]*(1<<$shift)}]
|
|
||||||
puts "shift = $shift, space = $size"
|
|
||||||
|
|
||||||
set f [open [file join [lindex $argv 1] uni_data.c] w]
|
|
||||||
fconfigure $f -translation lf
|
|
||||||
puts $f "/*
|
|
||||||
* uni_data.c --
|
|
||||||
*
|
|
||||||
* Declarations of Unicode character information tables. This file is
|
|
||||||
* automatically generated by the uni_parse.tcl script. Do not
|
|
||||||
* modify this file by hand.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1998 by Scriptics Corporation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Modified for ejabberd by Alexey Shchepin
|
|
||||||
*
|
|
||||||
* RCS: @(#) \$Id\$
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A 16-bit Unicode character is split into two parts in order to index
|
|
||||||
* into the following tables. The lower OFFSET_BITS comprise an offset
|
|
||||||
* into a page of characters. The upper bits comprise the page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define OFFSET_BITS $shift
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The pageMap is indexed by page number and returns an alternate page number
|
|
||||||
* that identifies a unique page of characters. Many Unicode characters map
|
|
||||||
* to the same alternate page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char pageMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $pMap] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
append line [lindex $pMap $i]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The groupMap is indexed by combining the alternate page number with
|
|
||||||
* the page offset and returns a group number that identifies a unique
|
|
||||||
* set of character attributes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned short int groupMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set lasti [expr {[llength $pages] - 1}]
|
|
||||||
for {set i 0} {$i <= $lasti} {incr i} {
|
|
||||||
set page [lindex $pages $i]
|
|
||||||
set lastj [expr {[llength $page] - 1}]
|
|
||||||
for {set j 0} {$j <= $lastj} {incr j} {
|
|
||||||
append line [lindex $page $j]
|
|
||||||
if {$j != $lastj || $i != $lasti} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Each group represents a unique set of character attributes. The attributes
|
|
||||||
* are encoded into a 32-bit value as follows:
|
|
||||||
*
|
|
||||||
* Bit 0 A.1 | C.1.2 | C.2.2 | C.3 -- C.9
|
|
||||||
*
|
|
||||||
* Bit 1 C.1.1
|
|
||||||
*
|
|
||||||
* Bit 2 C.2.1
|
|
||||||
*
|
|
||||||
* Bit 3 B.1
|
|
||||||
*
|
|
||||||
* Bit 4 D.1
|
|
||||||
*
|
|
||||||
* Bit 5 D.2
|
|
||||||
*
|
|
||||||
* Bit 6 XNP
|
|
||||||
*
|
|
||||||
* Bit 7 Case maps to several characters
|
|
||||||
*
|
|
||||||
* Bits 8-10 Reserved for future use.
|
|
||||||
*
|
|
||||||
* Bits 11-31 Case delta: delta for case conversions. This should be the
|
|
||||||
* highest field so we can easily sign extend.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int groups\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $groups] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
set val [lindex $groups $i]
|
|
||||||
|
|
||||||
append line [format "%d" $val]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 65} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table for characters that lowercased to multiple ones
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int multiCaseTable\[\]\[4\] = {"
|
|
||||||
set last [expr {[llength $multicasemap] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
set val [lindex $multicasemap $i]
|
|
||||||
|
|
||||||
set line " "
|
|
||||||
append line [format "{%d, %s}" [llength $val] [join $val ", "]]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
}
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following constants are used to determine the category of a
|
|
||||||
* Unicode character.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ACMask (1 << 0)
|
|
||||||
#define C11Mask (1 << 1)
|
|
||||||
#define C21Mask (1 << 2)
|
|
||||||
#define B1Mask (1 << 3)
|
|
||||||
#define D1Mask (1 << 4)
|
|
||||||
#define D2Mask (1 << 5)
|
|
||||||
#define XNPMask (1 << 6)
|
|
||||||
#define MCMask (1 << 7)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following macros extract the fields of the character info. The
|
|
||||||
* GetDelta() macro is complicated because we can't rely on the C compiler
|
|
||||||
* to do sign extension on right shifts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GetCaseType(info) (((info) & 0xE0) >> 5)
|
|
||||||
#define GetCategory(info) ((info) & 0x1F)
|
|
||||||
#define GetDelta(info) (((info) > 0) ? ((info) >> 11) : (~(~((info)) >> 11)))
|
|
||||||
#define GetMC(info) (multiCaseTable\[GetDelta(info)\])
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This macro extracts the information about a character from the
|
|
||||||
* Unicode character tables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GetUniCharInfo(ch) (groups\[groupMap\[(pageMap\[(((int)(ch)) & 0x1fffff) >> OFFSET_BITS\] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))\]\])
|
|
||||||
"
|
|
||||||
|
|
||||||
close $f
|
|
||||||
}
|
|
||||||
|
|
||||||
uni::main
|
|
||||||
|
|
||||||
return
|
|
@ -1,702 +0,0 @@
|
|||||||
# uni_parse2.tcl --
|
|
||||||
#
|
|
||||||
# This program parses the UnicodeData file and generates the
|
|
||||||
# corresponding uni_norm.c file with compressed character
|
|
||||||
# data tables. The input to this program should be
|
|
||||||
# UnicodeData-3.2.0.txt and CompositionExclusions-3.2.0.txt files from:
|
|
||||||
# ftp://ftp.unicode.org/Public/UNIDATA/
|
|
||||||
#
|
|
||||||
# Copyright (c) 1998-1999 by Scriptics Corporation.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Modified for ejabberd by Alexey Shchepin
|
|
||||||
#
|
|
||||||
# RCS: @(#) $Id$
|
|
||||||
|
|
||||||
|
|
||||||
namespace eval uni {
|
|
||||||
set cclass_shift 8
|
|
||||||
set decomp_shift 8
|
|
||||||
set comp_shift 8
|
|
||||||
set shift 5; # number of bits of data within a page
|
|
||||||
# This value can be adjusted to find the
|
|
||||||
# best split to minimize table size
|
|
||||||
|
|
||||||
variable pMap; # map from page to page index, each entry is
|
|
||||||
# an index into the pages table, indexed by
|
|
||||||
# page number
|
|
||||||
variable pages; # map from page index to page info, each
|
|
||||||
# entry is a list of indices into the groups
|
|
||||||
# table, the list is indexed by the offset
|
|
||||||
variable groups; # list of character info values, indexed by
|
|
||||||
# group number, initialized with the
|
|
||||||
# unassigned character group
|
|
||||||
|
|
||||||
variable categories {
|
|
||||||
Cn Lu Ll Lt Lm Lo Mn Me Mc Nd Nl No Zs Zl Zp
|
|
||||||
Cc Cf Co Cs Pc Pd Ps Pe Pi Pf Po Sm Sc Sk So
|
|
||||||
}; # Ordered list of character categories, must
|
|
||||||
# match the enumeration in the header file.
|
|
||||||
|
|
||||||
variable titleCount 0; # Count of the number of title case
|
|
||||||
# characters. This value is used in the
|
|
||||||
# regular expression code to allocate enough
|
|
||||||
# space for the title case variants.
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::getValue {items index} {
|
|
||||||
variable categories
|
|
||||||
variable titleCount
|
|
||||||
|
|
||||||
# Extract character info
|
|
||||||
|
|
||||||
set category [lindex $items 2]
|
|
||||||
if {[scan [lindex $items 12] %4x toupper] == 1} {
|
|
||||||
set toupper [expr {$index - $toupper}]
|
|
||||||
} else {
|
|
||||||
set toupper {}
|
|
||||||
}
|
|
||||||
if {[scan [lindex $items 13] %4x tolower] == 1} {
|
|
||||||
set tolower [expr {$tolower - $index}]
|
|
||||||
} else {
|
|
||||||
set tolower {}
|
|
||||||
}
|
|
||||||
if {[scan [lindex $items 14] %4x totitle] == 1} {
|
|
||||||
set totitle [expr {$index - $totitle}]
|
|
||||||
} else {
|
|
||||||
set totitle {}
|
|
||||||
}
|
|
||||||
|
|
||||||
set categoryIndex [lsearch -exact $categories $category]
|
|
||||||
if {$categoryIndex < 0} {
|
|
||||||
puts "Unexpected character category: $index($category)"
|
|
||||||
set categoryIndex 0
|
|
||||||
} elseif {$category == "Lt"} {
|
|
||||||
incr titleCount
|
|
||||||
}
|
|
||||||
|
|
||||||
return "$categoryIndex,$toupper,$tolower,$totitle"
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::getGroup {value} {
|
|
||||||
variable groups
|
|
||||||
|
|
||||||
set gIndex [lsearch -exact $groups $value]
|
|
||||||
if {$gIndex == -1} {
|
|
||||||
set gIndex [llength $groups]
|
|
||||||
lappend groups $value
|
|
||||||
}
|
|
||||||
return $gIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::addPage {info} {
|
|
||||||
variable pMap
|
|
||||||
variable pages
|
|
||||||
|
|
||||||
set pIndex [lsearch -exact $pages $info]
|
|
||||||
if {$pIndex == -1} {
|
|
||||||
set pIndex [llength $pages]
|
|
||||||
lappend pages $info
|
|
||||||
}
|
|
||||||
lappend pMap $pIndex
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::addPage {map_var pages_var info} {
|
|
||||||
variable $map_var
|
|
||||||
variable $pages_var
|
|
||||||
|
|
||||||
set pIndex [lsearch -exact [set $pages_var] $info]
|
|
||||||
if {$pIndex == -1} {
|
|
||||||
set pIndex [llength [set $pages_var]]
|
|
||||||
lappend $pages_var $info
|
|
||||||
}
|
|
||||||
lappend $map_var $pIndex
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::load_exclusions {data} {
|
|
||||||
variable exclusions
|
|
||||||
|
|
||||||
foreach line [split $data \n] {
|
|
||||||
if {$line == ""} continue
|
|
||||||
|
|
||||||
set items [split $line " "]
|
|
||||||
|
|
||||||
if {[lindex $items 0] == "#"} continue
|
|
||||||
|
|
||||||
scan [lindex $items 0] %x index
|
|
||||||
|
|
||||||
set exclusions($index) ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::load_tables {data} {
|
|
||||||
variable cclass_map
|
|
||||||
variable decomp_map
|
|
||||||
variable comp_map
|
|
||||||
variable comp_first
|
|
||||||
variable comp_second
|
|
||||||
variable exclusions
|
|
||||||
|
|
||||||
foreach line [split $data \n] {
|
|
||||||
if {$line == ""} continue
|
|
||||||
|
|
||||||
set items [split $line \;]
|
|
||||||
|
|
||||||
scan [lindex $items 0] %x index
|
|
||||||
set cclass [lindex $items 3]
|
|
||||||
set decomp [lindex $items 5]
|
|
||||||
|
|
||||||
set cclass_map($index) $cclass
|
|
||||||
#set decomp_map($index) $cclass
|
|
||||||
|
|
||||||
if {$decomp != ""} {
|
|
||||||
if {[string index [lindex $decomp 0] 0] == "<"} {
|
|
||||||
set decomp1 [lreplace $decomp 0 0]
|
|
||||||
set decomp {}
|
|
||||||
foreach ch $decomp1 {
|
|
||||||
scan $ch %x ch
|
|
||||||
lappend decomp $ch
|
|
||||||
}
|
|
||||||
set decomp_map($index) $decomp
|
|
||||||
} else {
|
|
||||||
switch -- [llength $decomp] {
|
|
||||||
1 {
|
|
||||||
scan $decomp %x ch
|
|
||||||
set decomp_map($index) $ch
|
|
||||||
}
|
|
||||||
2 {
|
|
||||||
scan $decomp "%x %x" ch1 ch2
|
|
||||||
set decomp [list $ch1 $ch2]
|
|
||||||
set decomp_map($index) $decomp
|
|
||||||
# hackish
|
|
||||||
if {(![info exists cclass_map($ch1)] || \
|
|
||||||
$cclass_map($ch1) == 0) && \
|
|
||||||
![info exists exclusions($index)]} {
|
|
||||||
if {[info exists comp_first($ch1)]} {
|
|
||||||
incr comp_first($ch1)
|
|
||||||
} else {
|
|
||||||
set comp_first($ch1) 1
|
|
||||||
}
|
|
||||||
if {[info exists comp_second($ch2)]} {
|
|
||||||
incr comp_second($ch2)
|
|
||||||
} else {
|
|
||||||
set comp_second($ch2) 1
|
|
||||||
}
|
|
||||||
set comp_map($decomp) $index
|
|
||||||
} else {
|
|
||||||
puts "Excluded $index"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default {
|
|
||||||
puts "Bad canonical decomposition: $line"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#puts "[format 0x%0.4x $index]\t$cclass\t$decomp_map($index)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#puts [array get comp_first]
|
|
||||||
#puts [array get comp_second]
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::buildTables {} {
|
|
||||||
variable cclass_shift
|
|
||||||
variable decomp_shift
|
|
||||||
variable comp_shift
|
|
||||||
|
|
||||||
variable cclass_map
|
|
||||||
variable cclass_pmap {}
|
|
||||||
variable cclass_pages {}
|
|
||||||
variable decomp_map
|
|
||||||
variable decomp_pmap {}
|
|
||||||
variable decomp_pages {}
|
|
||||||
variable decomp_list {}
|
|
||||||
variable comp_map
|
|
||||||
variable comp_pmap {}
|
|
||||||
variable comp_pages {}
|
|
||||||
variable comp_first
|
|
||||||
variable comp_second
|
|
||||||
variable comp_first_list {}
|
|
||||||
variable comp_second_list {}
|
|
||||||
variable comp_x_list {}
|
|
||||||
variable comp_y_list {}
|
|
||||||
variable comp_both_map {}
|
|
||||||
|
|
||||||
set cclass_info {}
|
|
||||||
set decomp_info {}
|
|
||||||
set comp_info {}
|
|
||||||
|
|
||||||
set cclass_mask [expr {(1 << $cclass_shift) - 1}]
|
|
||||||
set decomp_mask [expr {(1 << $decomp_shift) - 1}]
|
|
||||||
set comp_mask [expr {(1 << $comp_shift) - 1}]
|
|
||||||
|
|
||||||
foreach comp [array names comp_map] {
|
|
||||||
set ch1 [lindex $comp 0]
|
|
||||||
if {[info exists comp_first($ch1)] && $comp_first($ch1) > 0 && \
|
|
||||||
[info exists comp_second($ch1)] && $comp_second($ch1) > 0} {
|
|
||||||
if {[lsearch -exact $comp_x_list $ch1] < 0} {
|
|
||||||
set i [llength $comp_x_list]
|
|
||||||
lappend comp_x_list $ch1
|
|
||||||
set comp_info_map($ch1) $i
|
|
||||||
lappend comp_y_list $ch1
|
|
||||||
set comp_info_map($ch1) $i
|
|
||||||
puts "There should be no symbols which appears on"
|
|
||||||
puts "both first and second place in composition"
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach comp [array names comp_map] {
|
|
||||||
set ch1 [lindex $comp 0]
|
|
||||||
set ch2 [lindex $comp 1]
|
|
||||||
|
|
||||||
if {$comp_first($ch1) == 1 && ![info exists comp_second($ch1)]} {
|
|
||||||
set i [llength $comp_first_list]
|
|
||||||
lappend comp_first_list [list $ch2 $comp_map($comp)]
|
|
||||||
set comp_info_map($ch1) [expr {$i | (1 << 16)}]
|
|
||||||
} elseif {$comp_second($ch2) == 1 && ![info exists comp_first($ch2)]} {
|
|
||||||
set i [llength $comp_second_list]
|
|
||||||
lappend comp_second_list [list $ch1 $comp_map($comp)]
|
|
||||||
set comp_info_map($ch2) [expr {$i | (1 << 16) | (1 << 17)}]
|
|
||||||
} else {
|
|
||||||
if {[lsearch -exact $comp_x_list $ch1] < 0} {
|
|
||||||
set i [llength $comp_x_list]
|
|
||||||
lappend comp_x_list $ch1
|
|
||||||
set comp_info_map($ch1) $i
|
|
||||||
}
|
|
||||||
if {[lsearch -exact $comp_y_list $ch2] < 0} {
|
|
||||||
set i [llength $comp_y_list]
|
|
||||||
lappend comp_y_list $ch2
|
|
||||||
set comp_info_map($ch2) [expr {$i | (1 << 17)}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set next 0
|
|
||||||
|
|
||||||
for {set i 0} {$i <= 0x10ffff} {incr i} {
|
|
||||||
#set gIndex [getGroup [getValue $i]]
|
|
||||||
|
|
||||||
set cclass_offset [expr {$i & $cclass_mask}]
|
|
||||||
|
|
||||||
if {[info exists cclass_map($i)]} {
|
|
||||||
set cclass $cclass_map($i)
|
|
||||||
} else {
|
|
||||||
set cclass 0
|
|
||||||
}
|
|
||||||
lappend cclass_info $cclass
|
|
||||||
|
|
||||||
if {$cclass_offset == $cclass_mask} {
|
|
||||||
addPage cclass_pmap cclass_pages $cclass_info
|
|
||||||
set cclass_info {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
set decomp_offset [expr {$i & $decomp_mask}]
|
|
||||||
|
|
||||||
if {[info exists decomp_map($i)]} {
|
|
||||||
set decomp $decomp_map($i)
|
|
||||||
set b 1
|
|
||||||
while {$b} {
|
|
||||||
set b 0
|
|
||||||
for {set j 0} {$j < [llength $decomp]} {incr j} {
|
|
||||||
if {[info exists \
|
|
||||||
decomp_map([set ch1 [lindex $decomp $j]])]} {
|
|
||||||
#puts -$decomp
|
|
||||||
set decomp [eval [list lreplace $decomp $j $j] \
|
|
||||||
$decomp_map($ch1)]
|
|
||||||
#puts +$decomp
|
|
||||||
set b 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[info exists decomp_used($decomp)]} {
|
|
||||||
lappend decomp_info $decomp_used($decomp)
|
|
||||||
} else {
|
|
||||||
set val [expr {([llength $decomp] << 16) + \
|
|
||||||
[llength $decomp_list]}]
|
|
||||||
#set val [expr {[llength $decomp_list]}]
|
|
||||||
lappend decomp_info $val
|
|
||||||
set decomp_used($decomp) $val
|
|
||||||
#puts "$val $decomp"
|
|
||||||
foreach d $decomp {
|
|
||||||
lappend decomp_list $d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lappend decomp_info -1
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$decomp_offset == $decomp_mask} {
|
|
||||||
addPage decomp_pmap decomp_pages $decomp_info
|
|
||||||
set decomp_info {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
set comp_offset [expr {$i & $comp_mask}]
|
|
||||||
|
|
||||||
if {[info exists comp_info_map($i)]} {
|
|
||||||
set comp $comp_info_map($i)
|
|
||||||
} else {
|
|
||||||
set comp -1
|
|
||||||
}
|
|
||||||
lappend comp_info $comp
|
|
||||||
|
|
||||||
if {$comp_offset == $comp_mask} {
|
|
||||||
addPage comp_pmap comp_pages $comp_info
|
|
||||||
set comp_info {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#puts [array get decomp_map]
|
|
||||||
#puts $decomp_list
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proc uni::main {} {
|
|
||||||
global argc argv0 argv
|
|
||||||
variable cclass_shift
|
|
||||||
variable cclass_pmap
|
|
||||||
variable cclass_pages
|
|
||||||
variable decomp_shift
|
|
||||||
variable decomp_pmap
|
|
||||||
variable decomp_pages
|
|
||||||
variable decomp_list
|
|
||||||
variable comp_shift
|
|
||||||
variable comp_map
|
|
||||||
variable comp_pmap
|
|
||||||
variable comp_pages
|
|
||||||
variable comp_first_list
|
|
||||||
variable comp_second_list
|
|
||||||
variable comp_x_list
|
|
||||||
variable comp_y_list
|
|
||||||
variable pages
|
|
||||||
variable groups {}
|
|
||||||
variable titleCount
|
|
||||||
|
|
||||||
if {$argc != 3} {
|
|
||||||
puts stderr "\nusage: $argv0 <datafile> <exclusionsfile> <outdir>\n"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
set f [open [lindex $argv 1] r]
|
|
||||||
set data [read $f]
|
|
||||||
close $f
|
|
||||||
|
|
||||||
load_exclusions $data
|
|
||||||
|
|
||||||
set f [open [lindex $argv 0] r]
|
|
||||||
set data [read $f]
|
|
||||||
close $f
|
|
||||||
|
|
||||||
load_tables $data
|
|
||||||
buildTables
|
|
||||||
#puts "X = [llength $pMap] Y= [llength $pages] A= [llength $groups]"
|
|
||||||
#set size [expr {[llength $pMap] + [llength $pages]*(1<<$shift)}]
|
|
||||||
#puts "shift = 6, space = $size"
|
|
||||||
#puts "title case count = $titleCount"
|
|
||||||
|
|
||||||
set f [open [file join [lindex $argv 2] uni_norm.c] w]
|
|
||||||
fconfigure $f -translation lf
|
|
||||||
puts $f "/*
|
|
||||||
* uni_norm.c --
|
|
||||||
*
|
|
||||||
* Declarations of Unicode character information tables. This file is
|
|
||||||
* automatically generated by the uni_parse2.tcl script. Do not
|
|
||||||
* modify this file by hand.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1998 by Scriptics Corporation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Modified for ejabberd by Alexey Shchepin
|
|
||||||
*
|
|
||||||
* RCS: @(#) \$Id\$
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A 16-bit Unicode character is split into two parts in order to index
|
|
||||||
* into the following tables. The lower CCLASS_OFFSET_BITS comprise an offset
|
|
||||||
* into a page of characters. The upper bits comprise the page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CCLASS_OFFSET_BITS $cclass_shift
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The pageMap is indexed by page number and returns an alternate page number
|
|
||||||
* that identifies a unique page of characters. Many Unicode characters map
|
|
||||||
* to the same alternate page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char cclassPageMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $cclass_pmap] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
append line [lindex $cclass_pmap $i]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The cclassGroupMap is indexed by combining the alternate page number with
|
|
||||||
* the page offset and returns a combining class number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char cclassGroupMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set lasti [expr {[llength $cclass_pages] - 1}]
|
|
||||||
for {set i 0} {$i <= $lasti} {incr i} {
|
|
||||||
set page [lindex $cclass_pages $i]
|
|
||||||
set lastj [expr {[llength $page] - 1}]
|
|
||||||
for {set j 0} {$j <= $lastj} {incr j} {
|
|
||||||
append line [lindex $page $j]
|
|
||||||
if {$j != $lastj || $i != $lasti} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
#define GetUniCharCClass(ch) (cclassGroupMap\[(cclassPageMap\[(((int)(ch)) & 0x1fffff) >> CCLASS_OFFSET_BITS\] << CCLASS_OFFSET_BITS) | ((ch) & ((1 << CCLASS_OFFSET_BITS)-1))\])
|
|
||||||
|
|
||||||
|
|
||||||
#define DECOMP_OFFSET_BITS $decomp_shift
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The pageMap is indexed by page number and returns an alternate page number
|
|
||||||
* that identifies a unique page of characters. Many Unicode characters map
|
|
||||||
* to the same alternate page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char decompPageMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $decomp_pmap] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
append line [lindex $decomp_pmap $i]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The decompGroupMap is indexed by combining the alternate page number with
|
|
||||||
* the page offset and returns a group number that identifies a length and
|
|
||||||
* shift of decomposition sequence in decompList
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int decompGroupMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set lasti [expr {[llength $decomp_pages] - 1}]
|
|
||||||
for {set i 0} {$i <= $lasti} {incr i} {
|
|
||||||
set page [lindex $decomp_pages $i]
|
|
||||||
set lastj [expr {[llength $page] - 1}]
|
|
||||||
for {set j 0} {$j <= $lastj} {incr j} {
|
|
||||||
append line [lindex $page $j]
|
|
||||||
if {$j != $lastj || $i != $lasti} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List of decomposition sequences
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int decompList\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $decomp_list] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
set val [lindex $decomp_list $i]
|
|
||||||
|
|
||||||
append line [format "%d" $val]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This macro extracts the information about a character from the
|
|
||||||
* Unicode character tables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GetUniCharDecompInfo(ch) (decompGroupMap\[(decompPageMap\[(((int)(ch)) & 0x1fffff) >> DECOMP_OFFSET_BITS\] << DECOMP_OFFSET_BITS) | ((ch) & ((1 << DECOMP_OFFSET_BITS)-1))\])
|
|
||||||
|
|
||||||
#define GetDecompShift(info) ((info) & 0xffff)
|
|
||||||
#define GetDecompLen(info) ((info) >> 16)
|
|
||||||
|
|
||||||
|
|
||||||
#define COMP_OFFSET_BITS $comp_shift
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The pageMap is indexed by page number and returns an alternate page number
|
|
||||||
* that identifies a unique page of characters. Many Unicode characters map
|
|
||||||
* to the same alternate page number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char compPageMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $comp_pmap] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
append line [lindex $comp_pmap $i]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The groupMap is indexed by combining the alternate page number with
|
|
||||||
* the page offset and returns a group number that identifies a unique
|
|
||||||
* set of character attributes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int compGroupMap\[\] = {"
|
|
||||||
set line " "
|
|
||||||
set lasti [expr {[llength $comp_pages] - 1}]
|
|
||||||
for {set i 0} {$i <= $lasti} {incr i} {
|
|
||||||
set page [lindex $comp_pages $i]
|
|
||||||
set lastj [expr {[llength $page] - 1}]
|
|
||||||
for {set j 0} {$j <= $lastj} {incr j} {
|
|
||||||
append line [lindex $page $j]
|
|
||||||
if {$j != $lastj || $i != $lasti} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lists of compositions for characters that appears only in one composition
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int compFirstList\[\]\[2\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $comp_first_list] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
set val [lindex $comp_first_list $i]
|
|
||||||
|
|
||||||
append line [format "{%d, %d}" [lindex $val 0] [lindex $val 1]]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 60} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
static int compSecondList\[\]\[2\] = {"
|
|
||||||
set line " "
|
|
||||||
set last [expr {[llength $comp_second_list] - 1}]
|
|
||||||
for {set i 0} {$i <= $last} {incr i} {
|
|
||||||
set val [lindex $comp_second_list $i]
|
|
||||||
|
|
||||||
append line [format "{%d, %d}" [lindex $val 0] [lindex $val 1]]
|
|
||||||
if {$i != $last} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 60} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compositions matrix
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int compBothList\[[llength $comp_x_list]\]\[[llength $comp_y_list]\] = {"
|
|
||||||
set lastx [expr {[llength $comp_x_list] - 1}]
|
|
||||||
set lasty [expr {[llength $comp_y_list] - 1}]
|
|
||||||
for {set i 0} {$i <= $lastx} {incr i} {
|
|
||||||
puts $f " \{"
|
|
||||||
set line " "
|
|
||||||
for {set j 0} {$j <= $lasty} {incr j} {
|
|
||||||
set comp [list [lindex $comp_x_list $i] [lindex $comp_y_list $j]]
|
|
||||||
if {[info exists comp_map($comp)]} {
|
|
||||||
set val $comp_map($comp)
|
|
||||||
} else {
|
|
||||||
set val 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append line [format "%d" $val]
|
|
||||||
if {$j != $lasty} {
|
|
||||||
append line ", "
|
|
||||||
}
|
|
||||||
if {[string length $line] > 70} {
|
|
||||||
puts $f $line
|
|
||||||
set line " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f $line
|
|
||||||
if {$j != $lasty} {
|
|
||||||
puts $f " \},"
|
|
||||||
} else {
|
|
||||||
puts $f " \}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $f "};
|
|
||||||
|
|
||||||
|
|
||||||
#define GetUniCharCompInfo(ch) (compGroupMap\[(compPageMap\[(((int)(ch)) & 0x1fffff) >> COMP_OFFSET_BITS\] << COMP_OFFSET_BITS) | ((ch) & ((1 << COMP_OFFSET_BITS)-1))\])
|
|
||||||
|
|
||||||
#define CompSingleMask (1 << 16)
|
|
||||||
#define CompMask ((1 << 16) - 1)
|
|
||||||
#define CompSecondMask (1 << 17)
|
|
||||||
"
|
|
||||||
|
|
||||||
close $f
|
|
||||||
}
|
|
||||||
|
|
||||||
uni::main
|
|
||||||
|
|
||||||
return
|
|
234
src/xml.erl
234
src/xml.erl
@ -1,234 +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-2009 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_string/1,
|
|
||||||
crypt/1, make_text_node/1,
|
|
||||||
remove_cdata/1,
|
|
||||||
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,
|
|
||||||
get_path_s/2,
|
|
||||||
replace_tag_attr/3]).
|
|
||||||
|
|
||||||
%% 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.
|
|
||||||
|
|
||||||
element_to_string(El) ->
|
|
||||||
case El of
|
|
||||||
{xmlelement, Name, Attrs, Els} ->
|
|
||||||
if
|
|
||||||
Els /= [] ->
|
|
||||||
[$<, Name, attrs_to_list(Attrs), $>,
|
|
||||||
[element_to_string(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} when is_binary(CData) ->
|
|
||||||
?ESCAPE_BINARY(CData);
|
|
||||||
%% We crypt list and possibly binaries if full XML usage is
|
|
||||||
%% disabled unsupported (implies a conversion to list).
|
|
||||||
{xmlcdata, CData} ->
|
|
||||||
crypt(CData)
|
|
||||||
end.
|
|
||||||
|
|
||||||
attrs_to_list(Attrs) ->
|
|
||||||
[attr_to_list(A) || A <- Attrs].
|
|
||||||
|
|
||||||
attr_to_list({Name, Value}) ->
|
|
||||||
[$\s, crypt(Name), $=, $', crypt(Value), $'].
|
|
||||||
|
|
||||||
crypt(S) when is_list(S) ->
|
|
||||||
[case C of
|
|
||||||
$& -> "&";
|
|
||||||
$< -> "<";
|
|
||||||
$> -> ">";
|
|
||||||
$" -> """;
|
|
||||||
$' -> "'";
|
|
||||||
_ -> C
|
|
||||||
end || C <- S];
|
|
||||||
crypt(S) when is_binary(S) ->
|
|
||||||
crypt(binary_to_list(S)).
|
|
||||||
|
|
||||||
%% Make a cdata_binary depending on what characters it contains
|
|
||||||
make_text_node(CData) ->
|
|
||||||
case cdata_need_escape(CData) of
|
|
||||||
cdata ->
|
|
||||||
CDATA1 = <<"<![CDATA[">>,
|
|
||||||
CDATA2 = <<"]]>">>,
|
|
||||||
concat_binary([CDATA1, CData, CDATA2]);
|
|
||||||
none ->
|
|
||||||
CData;
|
|
||||||
{cdata, EndTokens} ->
|
|
||||||
EscapedCData = escape_cdata(CData, EndTokens),
|
|
||||||
concat_binary(EscapedCData)
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% Returns escape type needed for the text node
|
|
||||||
%% none, cdata, {cdata, [Positions]}
|
|
||||||
%% Positions is a list a integer containing positions of CDATA end
|
|
||||||
%% tokens, so that they can be escaped
|
|
||||||
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 that contain CDATA end tokens
|
|
||||||
%% EndTokens is a list of position of end tokens (integer)
|
|
||||||
%% This is supposed to be a very rare case: You need to generate several
|
|
||||||
%% fields, splitting it in the middle of the end token.
|
|
||||||
%% See example: http://en.wikipedia.org/wiki/CDATA#Uses_of_CDATA_sections
|
|
||||||
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),
|
|
||||||
%% Note: We build the list in reverse to optimize construction
|
|
||||||
escape_cdata(Rest, Pos+1, Positions, [CDATA2, Part, CDATA1|Acc]).
|
|
||||||
|
|
||||||
remove_cdata_p({xmlelement, _Name, _Attrs, _Els}) -> true;
|
|
||||||
remove_cdata_p(_) -> false.
|
|
||||||
|
|
||||||
remove_cdata(L) -> [E || E <- L, remove_cdata_p(E)].
|
|
||||||
|
|
||||||
get_cdata(L) ->
|
|
||||||
binary_to_list(list_to_binary(get_cdata(L, ""))).
|
|
||||||
|
|
||||||
get_cdata([{xmlcdata, CData} | L], S) ->
|
|
||||||
get_cdata(L, [S, CData]);
|
|
||||||
get_cdata([_ | L], S) ->
|
|
||||||
get_cdata(L, S);
|
|
||||||
get_cdata([], S) ->
|
|
||||||
S.
|
|
||||||
|
|
||||||
get_tag_cdata({xmlelement, _Name, _Attrs, Els}) ->
|
|
||||||
get_cdata(Els).
|
|
||||||
|
|
||||||
get_attr(AttrName, Attrs) ->
|
|
||||||
case lists:keysearch(AttrName, 1, Attrs) of
|
|
||||||
{value, {_, Val}} ->
|
|
||||||
{value, Val};
|
|
||||||
_ ->
|
|
||||||
false
|
|
||||||
end.
|
|
||||||
|
|
||||||
get_attr_s(AttrName, Attrs) ->
|
|
||||||
case lists:keysearch(AttrName, 1, Attrs) of
|
|
||||||
{value, {_, Val}} ->
|
|
||||||
Val;
|
|
||||||
_ ->
|
|
||||||
""
|
|
||||||
end.
|
|
||||||
|
|
||||||
get_tag_attr(AttrName, {xmlelement, _Name, Attrs, _Els}) ->
|
|
||||||
get_attr(AttrName, Attrs).
|
|
||||||
|
|
||||||
get_tag_attr_s(AttrName, {xmlelement, _Name, Attrs, _Els}) ->
|
|
||||||
get_attr_s(AttrName, Attrs).
|
|
||||||
|
|
||||||
|
|
||||||
get_subtag({xmlelement, _, _, Els}, Name) ->
|
|
||||||
get_subtag1(Els, Name).
|
|
||||||
|
|
||||||
get_subtag1([El | Els], Name) ->
|
|
||||||
case El of
|
|
||||||
{xmlelement, Name, _, _} ->
|
|
||||||
El;
|
|
||||||
_ ->
|
|
||||||
get_subtag1(Els, Name)
|
|
||||||
end;
|
|
||||||
get_subtag1([], _) ->
|
|
||||||
false.
|
|
||||||
|
|
||||||
get_subtag_cdata(Tag, Name) ->
|
|
||||||
case get_subtag(Tag, Name) of
|
|
||||||
false ->
|
|
||||||
"";
|
|
||||||
Subtag ->
|
|
||||||
get_tag_cdata(Subtag)
|
|
||||||
end.
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
|
|
||||||
replace_tag_attr(Attr, Value, {xmlelement, Name, Attrs, Els}) ->
|
|
||||||
Attrs1 = lists:keydelete(Attr, 1, Attrs),
|
|
||||||
Attrs2 = [{Attr, Value} | Attrs1],
|
|
||||||
{xmlelement, Name, Attrs2, Els}.
|
|
||||||
|
|
||||||
|
|
@ -1,190 +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-2009 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,
|
|
||||||
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, port, stack, size, maxsize}).
|
|
||||||
|
|
||||||
process_data(CallbackPid, Stack, Data) ->
|
|
||||||
case Data of
|
|
||||||
{?XML_START, {Name, Attrs}} ->
|
|
||||||
if
|
|
||||||
Stack == [] ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamstart, Name, Attrs});
|
|
||||||
true ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
[{xmlelement, Name, Attrs, []} | Stack];
|
|
||||||
{?XML_END, EndName} ->
|
|
||||||
case Stack of
|
|
||||||
[{xmlelement, Name, Attrs, Els} | Tail] ->
|
|
||||||
NewEl = {xmlelement, Name, Attrs, lists:reverse(Els)},
|
|
||||||
case Tail of
|
|
||||||
[] ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamend, EndName}),
|
|
||||||
Tail;
|
|
||||||
[_] ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid,
|
|
||||||
{xmlstreamelement, NewEl}),
|
|
||||||
Tail;
|
|
||||||
[{xmlelement, Name1, Attrs1, Els1} | Tail1] ->
|
|
||||||
[{xmlelement, Name1, Attrs1, [NewEl | Els1]} |
|
|
||||||
Tail1]
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
{?XML_CDATA, CData} ->
|
|
||||||
case Stack of
|
|
||||||
[El] ->
|
|
||||||
[El];
|
|
||||||
%% 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
|
|
||||||
[{xmlelement, Name, Attrs,
|
|
||||||
[{xmlcdata, PreviousCData}|Els]} | Tail] ->
|
|
||||||
[{xmlelement, Name, Attrs,
|
|
||||||
[{xmlcdata, concat_binary([PreviousCData, CData])} | Els]} | Tail];
|
|
||||||
%% No previous CDATA
|
|
||||||
[{xmlelement, Name, Attrs, Els} | Tail] ->
|
|
||||||
[{xmlelement, Name, Attrs, [{xmlcdata, CData} | Els]} |
|
|
||||||
Tail];
|
|
||||||
[] -> []
|
|
||||||
end;
|
|
||||||
{?XML_ERROR, Err} ->
|
|
||||||
catch gen_fsm:send_event(CallbackPid, {xmlstreamerror, Err})
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
new(CallbackPid) ->
|
|
||||||
new(CallbackPid, infinity).
|
|
||||||
|
|
||||||
new(CallbackPid, MaxSize) ->
|
|
||||||
Port = open_port({spawn, expat_erl}, [binary]),
|
|
||||||
#xml_stream_state{callback_pid = CallbackPid,
|
|
||||||
port = Port,
|
|
||||||
stack = [],
|
|
||||||
size = 0,
|
|
||||||
maxsize = MaxSize}.
|
|
||||||
|
|
||||||
|
|
||||||
parse(#xml_stream_state{callback_pid = CallbackPid,
|
|
||||||
port = Port,
|
|
||||||
stack = Stack,
|
|
||||||
size = Size,
|
|
||||||
maxsize = MaxSize} = State, Str) ->
|
|
||||||
StrSize = if
|
|
||||||
is_list(Str) -> length(Str);
|
|
||||||
is_binary(Str) -> size(Str)
|
|
||||||
end,
|
|
||||||
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}.
|
|
||||||
|
|
||||||
close(#xml_stream_state{port = Port}) ->
|
|
||||||
port_close(Port).
|
|
||||||
|
|
||||||
|
|
||||||
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, []).
|
|
||||||
|
|
||||||
process_element_events([], _Stack) ->
|
|
||||||
{error, parse_error};
|
|
||||||
process_element_events([Event | Events], Stack) ->
|
|
||||||
case Event of
|
|
||||||
{?XML_START, {Name, Attrs}} ->
|
|
||||||
process_element_events(
|
|
||||||
Events, [{xmlelement, Name, Attrs, []} | Stack]);
|
|
||||||
{?XML_END, _EndName} ->
|
|
||||||
case Stack of
|
|
||||||
[{xmlelement, Name, Attrs, Els} | Tail] ->
|
|
||||||
NewEl = {xmlelement, Name, Attrs, lists:reverse(Els)},
|
|
||||||
case Tail of
|
|
||||||
[] ->
|
|
||||||
if
|
|
||||||
Events == [] ->
|
|
||||||
NewEl;
|
|
||||||
true ->
|
|
||||||
{error, parse_error}
|
|
||||||
end;
|
|
||||||
[{xmlelement, Name1, Attrs1, Els1} | Tail1] ->
|
|
||||||
process_element_events(
|
|
||||||
Events,
|
|
||||||
[{xmlelement, Name1, Attrs1, [NewEl | Els1]} |
|
|
||||||
Tail1])
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
{?XML_CDATA, CData} ->
|
|
||||||
case Stack of
|
|
||||||
[{xmlelement, Name, Attrs, Els} | Tail] ->
|
|
||||||
process_element_events(
|
|
||||||
Events,
|
|
||||||
[{xmlelement, Name, Attrs, [{xmlcdata, CData} | Els]} |
|
|
||||||
Tail]);
|
|
||||||
[] ->
|
|
||||||
process_element_events(Events, [])
|
|
||||||
end;
|
|
||||||
{?XML_ERROR, Err} ->
|
|
||||||
{error, Err}
|
|
||||||
end.
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user