# HG changeset patch # User franky # Date 1255268312 -7200 # Node ID a087125d8fc849564e10d46f8eef3639fb3dd3e6 # Parent 4f59a414217e7c043efc7baa7e84b2faa5d66250 Replace libjabber with loudmouth diff -r 4f59a414217e -r a087125d8fc8 mcabber/Makefile.am --- a/mcabber/Makefile.am Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/Makefile.am Sun Oct 11 15:38:32 2009 +0200 @@ -1,2 +1,2 @@ -SUBDIRS = connwrap libjabber src doc +SUBDIRS = src doc ACLOCAL_AMFLAGS = -I macros diff -r 4f59a414217e -r a087125d8fc8 mcabber/configure.ac --- a/mcabber/configure.ac Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/configure.ac Sun Oct 11 15:38:32 2009 +0200 @@ -138,6 +138,12 @@ [g_list_append])], [g_regex_new]) +dnl AC_CHECK_LIB([loudmouth1],[lm_session_is_open],,AC_MSG_ERROR([ERROR! loudmouth1 not found...])) +LOUDMOUTH_CFLAGS=`pkg-config --cflags loudmouth-1.0` +LOUDMOUTH_LIBS=`pkg-config --libs loudmouth-1.0` +AC_SUBST(LOUDMOUTH_CFLAGS) +AC_SUBST(LOUDMOUTH_LIBS) + # Check for gpgme AC_ARG_ENABLE(gpgme, AC_HELP_STRING([--disable-gpgme], [disable GPGME support]), [ if test x"$enableval" = x"no"; then @@ -162,48 +168,6 @@ ) fi -AC_ARG_WITH(ssl, [ --with-ssl enable SSL secured connections using either OpenSSL - or GnuTLS], - [with_ssl=$withval]) - -if test "$with_ssl" != "no"; then - AC_ARG_WITH(openssl, - [ --with-openssl=[DIR] enable SSL secured connections using the OpenSSL - library in DIR (optional)], - [with_openssl=$withval]) - - if test -z "$with_openssl"; then - for ac_dir in /usr/local /usr; do - if test -f "$ac_dir/include/openssl/ssl.h"; then - with_openssl=$ac_dir - break; - fi - done - fi - - AC_MSG_CHECKING(for OpenSSL) - - if test -n "$with_openssl" -a "$with_openssl" != "no"; then - if test "$with_openssl" = "yes"; then with_openssl="/usr"; fi - CFLAGS="$CFLAGS -I${with_openssl}" - AC_DEFINE([HAVE_OPENSSL], [], [OpenSSL]) - AC_MSG_RESULT([found in $with_openssl]) - AC_CHECK_LIB(crypto, main) - AC_CHECK_LIB(ssl, main) - else - AC_MSG_RESULT([not found or disabled]) - - PKG_PROG_PKG_CONFIG - PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 1.0.0], - have_gnutls=yes, have_gnutls=no) - if test "$have_gnutls" = "yes"; then - AC_DEFINE([HAVE_GNUTLS], 1, [GNU TLS]) - CXXFLAGS="$CXXFLAGS $LIBGNUTLS_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_LIBS" - fi - fi -fi - # Check for Enchant stuff AC_ARG_ENABLE(enchant, [ --enable-enchant enable enchant support], enable_enchant=$enableval, enchant="") @@ -270,9 +234,7 @@ # We need _GNU_SOURCE for strptime() and strcasestr() CFLAGS="$CFLAGS -D_GNU_SOURCE" -AC_CONFIG_FILES([connwrap/Makefile - libjabber/Makefile - src/Makefile +AC_CONFIG_FILES([src/Makefile doc/Makefile doc/guide/Makefile doc/help/Makefile diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/Makefile.am --- a/mcabber/connwrap/Makefile.am Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -EXTRA_DIST = connwrap.c md5.c connwrap.h md5.h connwrap.spec -SUBDIRS = -INCLUDES = -CPPFLAGS = -noinst_LIBRARIES = libconnwrap.a -libconnwrap_a_SOURCES = connwrap.c md5.c -AUTOMAKE_OPTIONS = foreign diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/aclocal.m4 --- a/mcabber/connwrap/aclocal.m4 Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -dnl aclocal.m4 generated automatically by aclocal 1.4-p6 - -dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without -dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A -dnl PARTICULAR PURPOSE. - -# Do all the work for Automake. This macro actually does too much -- -# some checks are only needed if your package does certain things. -# But this isn't really a big deal. - -# serial 1 - -dnl Usage: -dnl AM_INIT_AUTOMAKE(package,version, [no-define]) - -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL]) -PACKAGE=[$1] -AC_SUBST(PACKAGE) -VERSION=[$2] -AC_SUBST(VERSION) -dnl test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) -fi -ifelse([$3],, -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) -AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) -AC_REQUIRE([AM_SANITY_CHECK]) -AC_REQUIRE([AC_ARG_PROGRAM]) -dnl FIXME This is truly gross. -missing_dir=`cd $ac_aux_dir && pwd` -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) -AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) -AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) -AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) -AC_REQUIRE([AC_PROG_MAKE_SET])]) - -# Copyright 2002 Free Software Foundation, Inc. - -# 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, 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 - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.4-p6])]) - -# -# Check to make sure that the build environment is sane. -# - -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftestfile -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` - if test "[$]*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftestfile` - fi - if test "[$]*" != "X $srcdir/configure conftestfile" \ - && test "[$]*" != "X conftestfile $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "[$]2" = conftestfile - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -rm -f conftest* -AC_MSG_RESULT(yes)]) - -dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) -dnl The program must properly implement --version. -AC_DEFUN([AM_MISSING_PROG], -[AC_MSG_CHECKING(for working $2) -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if ($2 --version) < /dev/null > /dev/null 2>&1; then - $1=$2 - AC_MSG_RESULT(found) -else - $1="$3/missing $2" - AC_MSG_RESULT(missing) -fi -AC_SUBST($1)]) - -dnl Autoconf macros for libgnutls-extra -dnl $id$ - -# Modified for LIBGNUTLS_EXTRA -- nmav -# Configure paths for LIBGCRYPT -# Shamelessly stolen from the one of XDELTA by Owen Taylor -# Werner Koch 99-12-09 - -dnl AM_PATH_LIBGNUTLS_EXTRA([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for libgnutls-extra, and define LIBGNUTLS_EXTRA_CFLAGS and LIBGNUTLS_EXTRA_LIBS -dnl -AC_DEFUN(AM_PATH_LIBGNUTLS_EXTRA, -[dnl -dnl Get the cflags and libraries from the libgnutls-extra-config script -dnl -AC_ARG_WITH(libgnutls-extra-prefix, - [ --with-libgnutls-extra-prefix=PFX Prefix where libgnutls-extra is installed (optional)], - libgnutls_extra_config_prefix="$withval", libgnutls_extra_config_prefix="") - - if test x$libgnutls_extra_config_prefix != x ; then - libgnutls_extra_config_args="$libgnutls_extra_config_args --prefix=$libgnutls_extra_config_prefix" - if test x${LIBGNUTLS_EXTRA_CONFIG+set} != xset ; then - LIBGNUTLS_EXTRA_CONFIG=$libgnutls_extra_config_prefix/bin/libgnutls-extra-config - fi - fi - - AC_PATH_PROG(LIBGNUTLS_EXTRA_CONFIG, libgnutls-extra-config, no) - min_libgnutls_version=ifelse([$1], ,0.1.0,$1) - AC_MSG_CHECKING(for libgnutls - version >= $min_libgnutls_version) - no_libgnutls="" - if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then - no_libgnutls=yes - else - LIBGNUTLS_EXTRA_CFLAGS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --cflags` - LIBGNUTLS_EXTRA_LIBS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --libs` - libgnutls_extra_config_version=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --version` - - - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" -dnl -dnl Now check if the installed libgnutls is sufficiently new. Also sanity -dnl checks the results of libgnutls-extra-config to some extent -dnl - rm -f conf.libgnutlstest - AC_TRY_RUN([ -#include -#include -#include -#include - -int -main () -{ - system ("touch conf.libgnutlstest"); - - if( strcmp( gnutls_extra_check_version(NULL), "$libgnutls_extra_config_version" ) ) - { - printf("\n*** 'libgnutls-extra-config --version' returned %s, but LIBGNUTLS_EXTRA (%s)\n", - "$libgnutls_extra_config_version", gnutls_extra_check_version(NULL) ); - printf("*** was found! If libgnutls-extra-config was correct, then it is best\n"); - printf("*** to remove the old version of LIBGNUTLS_EXTRA. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If libgnutls-extra-config was wrong, set the environment variable LIBGNUTLS_EXTRA_CONFIG\n"); - printf("*** to point to the correct copy of libgnutls-extra-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } - else if ( strcmp(gnutls_extra_check_version(NULL), LIBGNUTLS_EXTRA_VERSION ) ) - { - printf("\n*** LIBGNUTLS_EXTRA header file (version %s) does not match\n", LIBGNUTLS_EXTRA_VERSION); - printf("*** library (version %s). This is may be due to a different version of gnutls\n", gnutls_extra_check_version(NULL) ); - printf("*** and gnutls-extra.\n"); - } - else - { - if ( gnutls_extra_check_version( "$min_libgnutls_version" ) ) - { - return 0; - } - else - { - printf("no\n*** An old version of LIBGNUTLS_EXTRA (%s) was found.\n", - gnutls_extra_check_version(NULL) ); - printf("*** You need a version of LIBGNUTLS_EXTRA newer than %s. The latest version of\n", - "$min_libgnutls_version" ); - printf("*** LIBGNUTLS_EXTRA is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n"); - printf("*** \n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the libgnutls-extra-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of LIBGNUTLS_EXTRA, but you can also set the LIBGNUTLS_EXTRA_CONFIG environment to point to the\n"); - printf("*** correct copy of libgnutls-extra-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -],, no_libgnutls=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_libgnutls" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - if test -f conf.libgnutlstest ; then - : - else - AC_MSG_RESULT(no) - fi - if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then - echo "*** The libgnutls-extra-config script installed by LIBGNUTLS_EXTRA could not be found" - echo "*** If LIBGNUTLS_EXTRA was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the LIBGNUTLS_EXTRA_CONFIG environment variable to the" - echo "*** full path to libgnutls-extra-config." - else - if test -f conf.libgnutlstest ; then - : - else - echo "*** Could not run libgnutls test program, checking why..." - CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" - AC_TRY_LINK([ -#include -#include -#include -#include -], [ return !!gnutls_extra_check_version(NULL); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding LIBGNUTLS_EXTRA or finding the wrong" - echo "*** version of LIBGNUTLS_EXTRA. If it is not finding LIBGNUTLS_EXTRA, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means LIBGNUTLS_EXTRA was incorrectly installed" - echo "*** or that you have moved LIBGNUTLS_EXTRA since it was installed. In the latter case, you" - echo "*** may want to edit the libgnutls-extra-config script: $LIBGNUTLS_EXTRA_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - LIBGNUTLS_EXTRA_CFLAGS="" - LIBGNUTLS_EXTRA_LIBS="" - ifelse([$3], , :, [$3]) - fi - rm -f conf.libgnutlstest - AC_SUBST(LIBGNUTLS_EXTRA_CFLAGS) - AC_SUBST(LIBGNUTLS_EXTRA_LIBS) -]) - -dnl *-*wedit:notab*-* Please keep this as the last line. - diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/configure --- a/mcabber/connwrap/configure Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1893 +0,0 @@ -#! /bin/sh - -# Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.13 -# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. - -# Defaults: -ac_help= -ac_default_prefix=/usr/local -# Any additions from configure.in: -ac_help="$ac_help - --with-ssl enable SSL secured connections using either OpenSSL - or GnuTLS" -ac_help="$ac_help - --with-openssl=[DIR] enable SSL secured connections using the OpenSSL - library in DIR (optional)" -ac_help="$ac_help - --with-libgnutls-extra-prefix=PFX Prefix where libgnutls-extra is installed (optional)" - -# Initialize some variables set by options. -# The variables have the same names as the options, with -# dashes changed to underlines. -build=NONE -cache_file=./config.cache -exec_prefix=NONE -host=NONE -no_create= -nonopt=NONE -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -target=NONE -verbose= -x_includes=NONE -x_libraries=NONE -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -# Initialize some other variables. -subdirs= -MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} -# Maximum number of lines to put in a shell here document. -ac_max_here_lines=12 - -ac_prev= -for ac_option -do - - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - case "$ac_option" in - -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) ac_optarg= ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case "$ac_option" in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - eval "enable_${ac_feature}=no" ;; - - -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "enable_${ac_feature}='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he) - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat << EOF -Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] -Configuration: - --cache-file=FILE cache test results in FILE - --help print this message - --no-create do not create output files - --quiet, --silent do not print \`checking...' messages - --version print the version of autoconf that created configure -Directory and file names: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [same as prefix] - --bindir=DIR user executables in DIR [EPREFIX/bin] - --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] - --libexecdir=DIR program executables in DIR [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data in DIR - [PREFIX/share] - --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data in DIR - [PREFIX/com] - --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] - --libdir=DIR object code libraries in DIR [EPREFIX/lib] - --includedir=DIR C header files in DIR [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - --srcdir=DIR find the sources in DIR [configure dir or ..] - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM - run sed PROGRAM on installed program names -EOF - cat << EOF -Host type: - --build=BUILD configure for building on BUILD [BUILD=HOST] - --host=HOST configure for HOST [guessed] - --target=TARGET configure for TARGET [TARGET=HOST] -Features and packages: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR -EOF - if test -n "$ac_help"; then - echo "--enable and --with options recognized:$ac_help" - fi - exit 0 ;; - - -host | --host | --hos | --ho) - ac_prev=host ;; - -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix="$ac_optarg" ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix="$ac_optarg" ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.13" - exit 0 ;; - - -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "with_${ac_package}='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - eval "with_${ac_package}=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes="$ac_optarg" ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries="$ac_optarg" ;; - - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } - ;; - - *) - if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" 1>&2 - fi - if test "x$nonopt" != xNONE; then - { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } - fi - nonopt="$ac_option" - ;; - - esac -done - -if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } -fi - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 6 checking for... messages and results -# 5 compiler messages saved in config.log -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>./config.log - -echo "\ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. -" 1>&5 - -# Strip out --no-create and --no-recursion so they do not pile up. -# Also quote any args containing shell metacharacters. -ac_configure_args= -for ac_arg -do - case "$ac_arg" in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ac_configure_args="$ac_configure_args '$ac_arg'" ;; - *) ac_configure_args="$ac_configure_args $ac_arg" ;; - esac -done - -# NLS nuisances. -# Only set these to C if already set. These must not be set unconditionally -# because not all systems understand e.g. LANG=C (notably SCO). -# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! -# Non-C LC_CTYPE values break the ctype check. -if test "${LANG+set}" = set; then LANG=C; export LANG; fi -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi -if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi -if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo > confdefs.h - -# A filename unique to this package, relative to the directory that -# configure is in, which we can look for to find out if srcdir is correct. -ac_unique_file=aclocal.m4 - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_prog=$0 - ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` - test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } - else - { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } - fi -fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` - -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - echo "loading site script $ac_site_file" - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - echo "loading cache $cache_file" - . $cache_file -else - echo "creating cache $cache_file" - > $cache_file -fi - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -ac_exeext= -ac_objext=o -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - - -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } -fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. - -am__api_version="1.4" -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# ./install, which can be erroneously created by make from ./install.sh. -echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:565: checking for a BSD compatible install" >&5 -if test -z "$INSTALL"; then -if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" - for ac_dir in $PATH; do - # Account for people who put trailing slashes in PATH elements. - case "$ac_dir/" in - /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - if test -f $ac_dir/$ac_prog; then - if test $ac_prog = install && - grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - else - ac_cv_path_install="$ac_dir/$ac_prog -c" - break 2 - fi - fi - done - ;; - esac - done - IFS="$ac_save_IFS" - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL="$ac_cv_path_install" - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL="$ac_install_sh" - fi -fi -echo "$ac_t""$INSTALL" 1>&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:618: checking whether build environment is sane" >&5 -# Just in case -sleep 1 -echo timestamp > conftestfile -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftestfile` - fi - if test "$*" != "X $srcdir/configure conftestfile" \ - && test "$*" != "X conftestfile $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - { echo "configure: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" 1>&2; exit 1; } - fi - - test "$2" = conftestfile - ) -then - # Ok. - : -else - { echo "configure: error: newly created file is older than distributed files! -Check your system clock" 1>&2; exit 1; } -fi -rm -f conftest* -echo "$ac_t""yes" 1>&6 -if test "$program_transform_name" = s,x,x,; then - program_transform_name= -else - # Double any \ or $. echo might interpret backslashes. - cat <<\EOF_SED > conftestsed -s,\\,\\\\,g; s,\$,$$,g -EOF_SED - program_transform_name="`echo $program_transform_name|sed -f conftestsed`" - rm -f conftestsed -fi -test "$program_prefix" != NONE && - program_transform_name="s,^,${program_prefix},; $program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" - -# sed with no file args requires a program. -test "$program_transform_name" = "" && program_transform_name="s,x,x," - -echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:675: checking whether ${MAKE-make} sets \${MAKE}" >&5 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftestmake <<\EOF -all: - @echo 'ac_maketemp="${MAKE}"' -EOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi -rm -f conftestmake -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$ac_t""yes" 1>&6 - SET_MAKE= -else - echo "$ac_t""no" 1>&6 - SET_MAKE="MAKE=${MAKE-make}" -fi - - -PACKAGE=connwrap - -VERSION=0.1 - -if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then - { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } -fi -cat >> confdefs.h <> confdefs.h <&6 -echo "configure:721: checking for working aclocal-${am__api_version}" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then - ACLOCAL=aclocal-${am__api_version} - echo "$ac_t""found" 1>&6 -else - ACLOCAL="$missing_dir/missing aclocal-${am__api_version}" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 -echo "configure:734: checking for working autoconf" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (autoconf --version) < /dev/null > /dev/null 2>&1; then - AUTOCONF=autoconf - echo "$ac_t""found" 1>&6 -else - AUTOCONF="$missing_dir/missing autoconf" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working automake-${am__api_version}""... $ac_c" 1>&6 -echo "configure:747: checking for working automake-${am__api_version}" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then - AUTOMAKE=automake-${am__api_version} - echo "$ac_t""found" 1>&6 -else - AUTOMAKE="$missing_dir/missing automake-${am__api_version}" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 -echo "configure:760: checking for working autoheader" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (autoheader --version) < /dev/null > /dev/null 2>&1; then - AUTOHEADER=autoheader - echo "$ac_t""found" 1>&6 -else - AUTOHEADER="$missing_dir/missing autoheader" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 -echo "configure:773: checking for working makeinfo" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (makeinfo --version) < /dev/null > /dev/null 2>&1; then - MAKEINFO=makeinfo - echo "$ac_t""found" 1>&6 -else - MAKEINFO="$missing_dir/missing makeinfo" - echo "$ac_t""missing" 1>&6 -fi - - - -# Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:790: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_RANLIB="ranlib" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" -fi -fi -RANLIB="$ac_cv_prog_RANLIB" -if test -n "$RANLIB"; then - echo "$ac_t""$RANLIB" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - -# Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:821: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="gcc" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:851: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_prog_rejected=no - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - break - fi - done - IFS="$ac_save_ifs" -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - set dummy "$ac_dir/$ac_word" "$@" - shift - ac_cv_prog_CC="$@" - fi -fi -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - if test -z "$CC"; then - case "`uname -s`" in - *win32* | *WIN32*) - # Extract the first word of "cl", so it can be a program name with args. -set dummy cl; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:902: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="cl" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - ;; - esac - fi - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } -fi - -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:934: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -cat > conftest.$ac_ext << EOF - -#line 945 "configure" -#include "confdefs.h" - -main(){return(0);} -EOF -if { (eval echo configure:950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - ac_cv_prog_cc_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cc_cross=no - else - ac_cv_prog_cc_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cc_works=no -fi -rm -fr conftest* -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 -if test $ac_cv_prog_cc_works = no; then - { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:976: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 -cross_compiling=$ac_cv_prog_cc_cross - -echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:981: checking whether we are using GNU C" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes -else - ac_cv_prog_gcc=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then - GCC=yes -else - GCC= -fi - -ac_test_CFLAGS="${CFLAGS+set}" -ac_save_CFLAGS="$CFLAGS" -CFLAGS= -echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1009: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_cc_g=yes -else - ac_cv_prog_cc_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi - -for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1045: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CXX="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CXX="$ac_cv_prog_CXX" -if test -n "$CXX"; then - echo "$ac_t""$CXX" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -test -n "$CXX" && break -done -test -n "$CXX" || CXX="gcc" - - -echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1077: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 - -ac_ext=C -# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cxx_cross - -cat > conftest.$ac_ext << EOF - -#line 1088 "configure" -#include "confdefs.h" - -int main(){return(0);} -EOF -if { (eval echo configure:1093: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - ac_cv_prog_cxx_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cxx_cross=no - else - ac_cv_prog_cxx_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cxx_works=no -fi -rm -fr conftest* -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 -if test $ac_cv_prog_cxx_works = no; then - { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1119: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 -cross_compiling=$ac_cv_prog_cxx_cross - -echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:1124: checking whether we are using GNU C++" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gxx=yes -else - ac_cv_prog_gxx=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gxx" 1>&6 - -if test $ac_cv_prog_gxx = yes; then - GXX=yes -else - GXX= -fi - -ac_test_CXXFLAGS="${CXXFLAGS+set}" -ac_save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS= -echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:1152: checking whether ${CXX-g++} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.cc -if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then - ac_cv_prog_cxx_g=yes -else - ac_cv_prog_cxx_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS="$ac_save_CXXFLAGS" -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi - - -### -### SSL libs -### - -# Check whether --with-ssl or --without-ssl was given. -if test "${with_ssl+set}" = set; then - withval="$with_ssl" - with_ssl=$withval -fi - - -if test "$with_ssl" != "no"; then - # Check whether --with-openssl or --without-openssl was given. -if test "${with_openssl+set}" = set; then - withval="$with_openssl" - with_openssl=$withval -fi - - - if test -z "$with_openssl"; then - for ac_dir in /usr/local /usr; do - if test -f "$ac_dir/include/openssl/ssl.h"; then - with_openssl=$ac_dir - break; - fi - done - fi - - echo $ac_n "checking for OpenSSL""... $ac_c" 1>&6 -echo "configure:1213: checking for OpenSSL" >&5 - - if test -n "$with_openssl" -a "$with_openssl" != "no"; then - if test "$with_openssl" = "yes"; then with_openssl="/usr"; fi - CFLAGS="$CFLAGS -I${with_openssl}" - cat >> confdefs.h <<\EOF -#define HAVE_OPENSSL 1 -EOF - - echo "$ac_t""found in $with_openssl" 1>&6 - echo $ac_n "checking for main in -lcrypto""... $ac_c" 1>&6 -echo "configure:1224: checking for main in -lcrypto" >&5 -ac_lib_var=`echo crypto'_'main | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lcrypto $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - - echo $ac_n "checking for SSLeay_add_all_algorithms in -lcrypto""... $ac_c" 1>&6 -echo "configure:1256: checking for SSLeay_add_all_algorithms in -lcrypto" >&5 -ac_lib_var=`echo crypto'_'SSLeay_add_all_algorithms | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lcrypto $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - - cat >> confdefs.h <<\EOF -#define HAVE_SSLEAY 1 -EOF - - -else - echo "$ac_t""no" 1>&6 -fi - - -else - echo "$ac_t""no" 1>&6 -fi - - echo $ac_n "checking for main in -lssl""... $ac_c" 1>&6 -echo "configure:1306: checking for main in -lssl" >&5 -ac_lib_var=`echo ssl'_'main | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lssl $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_lib=HAVE_LIB`echo ssl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <&6 -fi - - else - echo "$ac_t""not found or disabled" 1>&6 - - # Check whether --with-libgnutls-extra-prefix or --without-libgnutls-extra-prefix was given. -if test "${with_libgnutls_extra_prefix+set}" = set; then - withval="$with_libgnutls_extra_prefix" - libgnutls_extra_config_prefix="$withval" -else - libgnutls_extra_config_prefix="" -fi - - - if test x$libgnutls_extra_config_prefix != x ; then - libgnutls_extra_config_args="$libgnutls_extra_config_args --prefix=$libgnutls_extra_config_prefix" - if test x${LIBGNUTLS_EXTRA_CONFIG+set} != xset ; then - LIBGNUTLS_EXTRA_CONFIG=$libgnutls_extra_config_prefix/bin/libgnutls-extra-config - fi - fi - - # Extract the first word of "libgnutls-extra-config", so it can be a program name with args. -set dummy libgnutls-extra-config; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1370: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_path_LIBGNUTLS_EXTRA_CONFIG'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - case "$LIBGNUTLS_EXTRA_CONFIG" in - /*) - ac_cv_path_LIBGNUTLS_EXTRA_CONFIG="$LIBGNUTLS_EXTRA_CONFIG" # Let the user override the test with a path. - ;; - ?:/*) - ac_cv_path_LIBGNUTLS_EXTRA_CONFIG="$LIBGNUTLS_EXTRA_CONFIG" # Let the user override the test with a dos path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_path_LIBGNUTLS_EXTRA_CONFIG="$ac_dir/$ac_word" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_LIBGNUTLS_EXTRA_CONFIG" && ac_cv_path_LIBGNUTLS_EXTRA_CONFIG="no" - ;; -esac -fi -LIBGNUTLS_EXTRA_CONFIG="$ac_cv_path_LIBGNUTLS_EXTRA_CONFIG" -if test -n "$LIBGNUTLS_EXTRA_CONFIG"; then - echo "$ac_t""$LIBGNUTLS_EXTRA_CONFIG" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - min_libgnutls_version=0.0.1 - echo $ac_n "checking for libgnutls - version >= $min_libgnutls_version""... $ac_c" 1>&6 -echo "configure:1405: checking for libgnutls - version >= $min_libgnutls_version" >&5 - no_libgnutls="" - if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then - no_libgnutls=yes - else - LIBGNUTLS_EXTRA_CFLAGS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --cflags` - LIBGNUTLS_EXTRA_LIBS=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --libs` - libgnutls_extra_config_version=`$LIBGNUTLS_EXTRA_CONFIG $libgnutls_extra_config_args --version` - - - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" - rm -f conf.libgnutlstest - if test "$cross_compiling" = yes; then - echo $ac_n "cross compiling; assumed OK... $ac_c" -else - cat > conftest.$ac_ext < -#include -#include -#include - -int -main () -{ - system ("touch conf.libgnutlstest"); - - if( strcmp( gnutls_extra_check_version(NULL), "$libgnutls_extra_config_version" ) ) - { - printf("\n*** 'libgnutls-extra-config --version' returned %s, but LIBGNUTLS_EXTRA (%s)\n", - "$libgnutls_extra_config_version", gnutls_extra_check_version(NULL) ); - printf("*** was found! If libgnutls-extra-config was correct, then it is best\n"); - printf("*** to remove the old version of LIBGNUTLS_EXTRA. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If libgnutls-extra-config was wrong, set the environment variable LIBGNUTLS_EXTRA_CONFIG\n"); - printf("*** to point to the correct copy of libgnutls-extra-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } - else if ( strcmp(gnutls_extra_check_version(NULL), LIBGNUTLS_EXTRA_VERSION ) ) - { - printf("\n*** LIBGNUTLS_EXTRA header file (version %s) does not match\n", LIBGNUTLS_EXTRA_VERSION); - printf("*** library (version %s). This is may be due to a different version of gnutls\n", gnutls_extra_check_version(NULL) ); - printf("*** and gnutls-extra.\n"); - } - else - { - if ( gnutls_extra_check_version( "$min_libgnutls_version" ) ) - { - return 0; - } - else - { - printf("no\n*** An old version of LIBGNUTLS_EXTRA (%s) was found.\n", - gnutls_extra_check_version(NULL) ); - printf("*** You need a version of LIBGNUTLS_EXTRA newer than %s. The latest version of\n", - "$min_libgnutls_version" ); - printf("*** LIBGNUTLS_EXTRA is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n"); - printf("*** \n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the libgnutls-extra-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of LIBGNUTLS_EXTRA, but you can also set the LIBGNUTLS_EXTRA_CONFIG environment to point to the\n"); - printf("*** correct copy of libgnutls-extra-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} - -EOF -if { (eval echo configure:1483: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - : -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - no_libgnutls=yes -fi -rm -fr conftest* -fi - - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_libgnutls" = x ; then - echo "$ac_t""yes" 1>&6 - - CXXFLAGS="$CXXFLAGS $LIBGNUTLS_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_LIBS -lgnutls-extra" - cat >> confdefs.h <<\EOF -#define HAVE_GNUTLS 1 -EOF - - - else - if test -f conf.libgnutlstest ; then - : - else - echo "$ac_t""no" 1>&6 - fi - if test "$LIBGNUTLS_EXTRA_CONFIG" = "no" ; then - echo "*** The libgnutls-extra-config script installed by LIBGNUTLS_EXTRA could not be found" - echo "*** If LIBGNUTLS_EXTRA was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the LIBGNUTLS_EXTRA_CONFIG environment variable to the" - echo "*** full path to libgnutls-extra-config." - else - if test -f conf.libgnutlstest ; then - : - else - echo "*** Could not run libgnutls test program, checking why..." - CFLAGS="$CFLAGS $LIBGNUTLS_EXTRA_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_EXTRA_LIBS" - cat > conftest.$ac_ext < -#include -#include -#include - -int main() { - return !!gnutls_extra_check_version(NULL); -; return 0; } -EOF -if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding LIBGNUTLS_EXTRA or finding the wrong" - echo "*** version of LIBGNUTLS_EXTRA. If it is not finding LIBGNUTLS_EXTRA, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means LIBGNUTLS_EXTRA was incorrectly installed" - echo "*** or that you have moved LIBGNUTLS_EXTRA since it was installed. In the latter case, you" - echo "*** may want to edit the libgnutls-extra-config script: $LIBGNUTLS_EXTRA_CONFIG" -fi -rm -f conftest* - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - LIBGNUTLS_EXTRA_CFLAGS="" - LIBGNUTLS_EXTRA_LIBS="" - : - fi - rm -f conf.libgnutlstest - - - - fi -fi - -echo $ac_n "checking for inet_aton() presence""... $ac_c" 1>&6 -echo "configure:1578: checking for inet_aton() presence" >&5 - -cat > conftest.$ac_ext < -#include -#include -#include - - -int main() { - - -struct in_addr inp; -inet_aton("address", &inp); - - -; return 0; } -EOF -if { (eval echo configure:1600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - have_aton=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - have_aton=no -fi -rm -f conftest* - -if test "$have_aton" = "yes"; then - cat >> confdefs.h <<\EOF -#define HAVE_INET_ATON 1 -EOF - - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Any assignment to VPATH causes Sun make to only execute -# the first set of double-colon rules, so remove it if not needed. -# If there is a colon in the path, we need to keep it. -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' -fi - -trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -cat > conftest.defs <<\EOF -s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g -s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g -s%\[%\\&%g -s%\]%\\&%g -s%\$%$$%g -EOF -DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` -rm -f conftest.defs - - -# Without the "./", some shells look in PATH for config.status. -: ${CONFIG_STATUS=./config.status} - -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS </dev/null | sed 1q`: -# -# $0 $ac_configure_args -# -# Compiler output produced by configure, useful for debugging -# configure, is in ./config.log if it exists. - -ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" -for ac_option -do - case "\$ac_option" in - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" - exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; - -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.13" - exit 0 ;; - -help | --help | --hel | --he | --h) - echo "\$ac_cs_usage"; exit 0 ;; - *) echo "\$ac_cs_usage"; exit 1 ;; - esac -done - -ac_given_srcdir=$srcdir -ac_given_INSTALL="$INSTALL" - -trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF -$ac_vpsub -$extrasub -s%@SHELL@%$SHELL%g -s%@CFLAGS@%$CFLAGS%g -s%@CPPFLAGS@%$CPPFLAGS%g -s%@CXXFLAGS@%$CXXFLAGS%g -s%@FFLAGS@%$FFLAGS%g -s%@DEFS@%$DEFS%g -s%@LDFLAGS@%$LDFLAGS%g -s%@LIBS@%$LIBS%g -s%@exec_prefix@%$exec_prefix%g -s%@prefix@%$prefix%g -s%@program_transform_name@%$program_transform_name%g -s%@bindir@%$bindir%g -s%@sbindir@%$sbindir%g -s%@libexecdir@%$libexecdir%g -s%@datadir@%$datadir%g -s%@sysconfdir@%$sysconfdir%g -s%@sharedstatedir@%$sharedstatedir%g -s%@localstatedir@%$localstatedir%g -s%@libdir@%$libdir%g -s%@includedir@%$includedir%g -s%@oldincludedir@%$oldincludedir%g -s%@infodir@%$infodir%g -s%@mandir@%$mandir%g -s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g -s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g -s%@INSTALL_DATA@%$INSTALL_DATA%g -s%@PACKAGE@%$PACKAGE%g -s%@VERSION@%$VERSION%g -s%@ACLOCAL@%$ACLOCAL%g -s%@AUTOCONF@%$AUTOCONF%g -s%@AUTOMAKE@%$AUTOMAKE%g -s%@AUTOHEADER@%$AUTOHEADER%g -s%@MAKEINFO@%$MAKEINFO%g -s%@SET_MAKE@%$SET_MAKE%g -s%@RANLIB@%$RANLIB%g -s%@CC@%$CC%g -s%@CXX@%$CXX%g -s%@LIBGNUTLS_EXTRA_CONFIG@%$LIBGNUTLS_EXTRA_CONFIG%g -s%@LIBGNUTLS_EXTRA_CFLAGS@%$LIBGNUTLS_EXTRA_CFLAGS%g -s%@LIBGNUTLS_EXTRA_LIBS@%$LIBGNUTLS_EXTRA_LIBS%g - -CEOF -EOF - -cat >> $CONFIG_STATUS <<\EOF - -# Split the substitutions into bite-sized pieces for seds with -# small command number limits, like on Digital OSF/1 and HP-UX. -ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. -ac_file=1 # Number of current file. -ac_beg=1 # First line for current file. -ac_end=$ac_max_sed_cmds # Line after last line for current file. -ac_more_lines=: -ac_sed_cmds="" -while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file - else - sed "${ac_end}q" conftest.subs > conftest.s$ac_file - fi - if test ! -s conftest.s$ac_file; then - ac_more_lines=false - rm -f conftest.s$ac_file - else - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f conftest.s$ac_file" - else - ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" - fi - ac_file=`expr $ac_file + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_cmds` - fi -done -if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat -fi -EOF - -cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF -for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; - esac - - # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. - - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" - # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` - else - ac_dir_suffix= ac_dots= - fi - - case "$ac_given_srcdir" in - .) srcdir=. - if test -z "$ac_dots"; then top_srcdir=. - else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; - /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; - *) # Relative path. - srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" - top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - - case "$ac_given_INSTALL" in - [/$]*) INSTALL="$ac_given_INSTALL" ;; - *) INSTALL="$ac_dots$ac_given_INSTALL" ;; - esac - - echo creating "$ac_file" - rm -f "$ac_file" - configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." - case "$ac_file" in - *Makefile*) ac_comsub="1i\\ -# $configure_input" ;; - *) ac_comsub= ;; - esac - - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - sed -e "$ac_comsub -s%@configure_input@%$configure_input%g -s%@srcdir@%$srcdir%g -s%@top_srcdir@%$top_srcdir%g -s%@INSTALL@%$INSTALL%g -" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file -fi; done -rm -f conftest.s* - -EOF -cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF - -exit 0 -EOF -chmod +x $CONFIG_STATUS -rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 - diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/configure.in --- a/mcabber/connwrap/configure.in Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -AC_INIT(aclocal.m4) -AM_INIT_AUTOMAKE(connwrap, 0.1) - -AC_PROG_RANLIB - -AC_PROG_CC -AC_PROG_CXX - -### -### SSL libs -### - -AC_ARG_WITH(ssl, [ --with-ssl enable SSL secured connections using either OpenSSL - or GnuTLS], - [with_ssl=$withval]) - -if test "$with_ssl" != "no"; then - AC_ARG_WITH(openssl, - [ --with-openssl=[DIR] enable SSL secured connections using the OpenSSL - library in DIR (optional)], - [with_openssl=$withval]) - - if test -z "$with_openssl"; then - for ac_dir in /usr/local /usr; do - if test -f "$ac_dir/include/openssl/ssl.h"; then - with_openssl=$ac_dir - break; - fi - done - fi - - AC_MSG_CHECKING(for OpenSSL) - - if test -n "$with_openssl" -a "$with_openssl" != "no"; then - if test "$with_openssl" = "yes"; then with_openssl="/usr"; fi - CFLAGS="$CFLAGS -I${with_openssl}" - AC_DEFINE(HAVE_OPENSSL) - AC_MSG_RESULT([found in $with_openssl]) - AC_CHECK_LIB(crypto, main, [ - AC_CHECK_LIB(crypto, SSLeay_add_all_algorithms, [ - AC_DEFINE(HAVE_SSLEAY) - ]) - ]) - AC_CHECK_LIB(ssl, main) - else - AC_MSG_RESULT([not found or disabled]) - - AM_PATH_LIBGNUTLS_EXTRA(0.0.1, [ - CXXFLAGS="$CXXFLAGS $LIBGNUTLS_CFLAGS" - LIBS="$LIBS $LIBGNUTLS_LIBS -lgnutls-extra" - AC_DEFINE(HAVE_GNUTLS) - ]) - fi -fi - -AC_MSG_CHECKING(for inet_aton() presence) - -AC_TRY_LINK([ - -#include -#include -#include -#include - -], [ - -struct in_addr inp; -inet_aton("address", &inp); - -], have_aton=yes, have_aton=no) - -if test "$have_aton" = "yes"; then - AC_DEFINE(HAVE_INET_ATON) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi - -AC_OUTPUT(Makefile) diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/connwrap.c --- a/mcabber/connwrap/connwrap.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,641 +0,0 @@ -#include "connwrap.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PROXY_TIMEOUT 10 - // HTTP proxy timeout in seconds (for the CONNECT method) - -#ifdef HAVE_OPENSSL -# define OPENSSL_NO_KRB5 1 -# include -# include -# define HAVE_SSL -# undef HAVE_GNUTLS // Can't use both... -#elif defined HAVE_GNUTLS -# include -# define HAVE_SSL -#endif - -static int in_http_connect = 0; - -#ifdef HAVE_OPENSSL -static SSL_CTX *ctx = NULL; -typedef struct { int fd; SSL *ssl; } sslsock; -#elif defined HAVE_GNUTLS -typedef struct { int fd; gnutls_session_t session; } sslsock; -#endif - - -#ifdef HAVE_SSL - -/* verify > 0 indicates verify depth as well */ -static int verify = -1; -static const char *cafile = NULL; -static const char *capath = NULL; -static const char *cipherlist = NULL; -static const char *peer = NULL; -static const char *sslerror = NULL; - -#ifdef HAVE_OPENSSL -static int verify_cb(int preverify_ok, X509_STORE_CTX *cx) -{ - X509 *cert; - X509_NAME *nm; - int lastpos; - - if(!preverify_ok) { - long err = X509_STORE_CTX_get_error(cx); - - sslerror = X509_verify_cert_error_string(err); - return 0; - } - - if (peer == NULL) - return 1; - - if ((cert = X509_STORE_CTX_get_current_cert(cx)) == NULL) { - sslerror = "internal SSL error"; - return 0; - } - - /* We only want to look at the peername if we're working on the peer - * certificate. */ - if (cert != cx->cert) - return 1; - - if ((nm = X509_get_subject_name (cert)) == NULL) { - sslerror = "internal SSL error"; - return 0; - } - - for(lastpos = -1; ; ) { - X509_NAME_ENTRY *e; - ASN1_STRING *a; - ASN1_STRING *p; - int match; - - lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos); - if (lastpos == -1) - break; - if ((e = X509_NAME_get_entry(nm, lastpos)) == NULL) { - sslerror = "internal SSL error"; - return 0; - } - if ((a = X509_NAME_ENTRY_get_data(e)) == NULL) { - sslerror = "internal SSL error"; - return 0; - } - if ((p = ASN1_STRING_type_new(ASN1_STRING_type(a))) == NULL) { - sslerror = "internal SSL error"; - return 0; - } - (void) ASN1_STRING_set(p, peer, -1); - match = !ASN1_STRING_cmp(a, p); - ASN1_STRING_free(p); - if(match) - return 1; - } - - sslerror = "server certificate cn mismatch"; - return 0; -} -#endif - -static void init(int fd, sslsock *p) { -#ifdef HAVE_GNUTLS - gnutls_certificate_credentials_t xcred; -#endif - -#ifdef HAVE_OPENSSL - if(ctx) - return; - SSL_library_init(); - SSL_load_error_strings(); - -#ifdef HAVE_SSLEAY - SSLeay_add_all_algorithms(); -#else - OpenSSL_add_all_algorithms(); -#endif - - /* May need to use distinct SSLEAY bindings below... */ - - ctx = SSL_CTX_new(SSLv23_client_method()); - if(cipherlist) - (void)SSL_CTX_set_cipher_list(ctx, cipherlist); - if(cafile || capath) - (void)SSL_CTX_load_verify_locations(ctx, cafile, capath); - if(verify) { - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); - if(verify > 0) - SSL_CTX_set_verify_depth(ctx, verify); - } else - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); - - p->ssl = SSL_new(ctx); - SSL_set_fd(p->ssl, p->fd = fd); - -#elif defined HAVE_GNUTLS - gnutls_global_init(); - gnutls_certificate_allocate_credentials(&xcred); - gnutls_init(&(p->session), GNUTLS_CLIENT); - gnutls_set_default_priority(p->session); - gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, xcred); - p->fd = fd; - gnutls_transport_set_ptr(p->session,(gnutls_transport_ptr_t)fd); -#endif -} - -static sslsock *socks = NULL; -static int sockcount = 0; - -static sslsock *getsock(int fd) { - int i; - - for(i = 0; i < sockcount; i++) - if(socks[i].fd == fd) - return &socks[i]; - - return NULL; -} - -static sslsock *addsock(int fd) { - sslsock *p; - - sockcount++; - - if (socks) - socks = (sslsock *) realloc(socks, sizeof(sslsock)*sockcount); - else - socks = (sslsock *) malloc(sizeof(sslsock)*sockcount); - - p = &socks[sockcount-1]; - - init(fd, p); - - sslerror = NULL; - - return p; -} - -static void delsock(int fd) { - int i, nsockcount; - sslsock *nsocks; - - nsockcount = 0; - - if (sockcount > 1) { - nsocks = (sslsock *) malloc(sizeof(sslsock)*(sockcount-1)); - - for(i = 0; i < sockcount; i++) { - if(socks[i].fd != fd) { - nsocks[nsockcount++] = socks[i]; - } else { -#ifdef HAVE_OPENSSL - SSL_free(socks[i].ssl); -#elif defined HAVE_GNUTLS - gnutls_bye(socks[i].session, GNUTLS_SHUT_WR); - gnutls_deinit(socks[i].session); -#endif - } - } - - } else { -#ifdef HAVE_OPENSSL - if (ctx) - SSL_CTX_free(ctx); - ctx = 0; -#endif - nsocks = NULL; - } - - if (socks) - free(socks); - socks = nsocks; - sockcount = nsockcount; -} - -void cw_set_ssl_options(int sslverify, - const char *sslcafile, const char *sslcapath, - const char *sslciphers, const char *sslpeer) { - verify = sslverify; - cafile = sslcafile; - capath = sslcapath; - cipherlist = sslciphers; - peer = sslpeer; -} - -const char *cw_get_ssl_error(void) { - return sslerror; -} - -#else // HAVE_SSL - -void cw_set_ssl_options(int sslverify, - const char *sslcafile, const char *sslcapath, - const char *sslciphers, const char *sslpeer) { } - -const char *cw_get_ssl_error(void) { - return NULL; -} - -#endif // HAVE_SSL - -static char *bindaddr = 0, *proxyhost = 0, *proxyuser = 0, *proxypass = 0; -static int proxyport = 3128; -static int proxy_ssl = 0; - -#define SOCKOUT(s) write(sockfd, s, strlen(s)) - -int cw_http_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen) { - int err, pos, fl; - struct hostent *server; - struct sockaddr_in paddr; - char buf[512]; - fd_set rfds; - - fl = 0; - err = 0; - in_http_connect = 1; - - if(!(server = gethostbyname(proxyhost))) { - errno = h_errno; - err = -1; - } - - if(!err) { - memset(&paddr, 0, sizeof(paddr)); - paddr.sin_family = AF_INET; - memcpy(&paddr.sin_addr.s_addr, *server->h_addr_list, server->h_length); - paddr.sin_port = htons(proxyport); - - fl = fcntl(sockfd, F_GETFL); - fcntl(sockfd, F_SETFL, fl & ~O_NONBLOCK); - - buf[0] = 0; - - err = cw_connect(sockfd, (struct sockaddr *) &paddr, sizeof(paddr), - proxy_ssl); - } - - errno = ECONNREFUSED; - - if(!err) { - struct sockaddr_in *sin = (struct sockaddr_in *) serv_addr; - char *ip = inet_ntoa(sin->sin_addr), c; - struct timeval tv; - - snprintf(buf, sizeof(buf), "%d", ntohs(sin->sin_port)); - SOCKOUT("CONNECT "); - SOCKOUT(ip); - SOCKOUT(":"); - SOCKOUT(buf); - SOCKOUT(" HTTP/1.0\r\n"); - - if(proxyuser) { - char *b; - SOCKOUT("Proxy-Authorization: Basic "); - - snprintf(buf, sizeof(buf), "%s:%s", proxyuser, proxypass); - b = cw_base64_encode(buf); - SOCKOUT(b); - free(b); - - SOCKOUT("\r\n"); - } - - SOCKOUT("\r\n"); - - buf[0] = 0; - - while(err != -1) { - FD_ZERO(&rfds); - FD_SET(sockfd, &rfds); - - tv.tv_sec = PROXY_TIMEOUT; - tv.tv_usec = 0; - - err = select(sockfd+1, &rfds, 0, 0, &tv); - - if(err < 1) err = -1; - - if(err != -1 && FD_ISSET(sockfd, &rfds)) { - err = read(sockfd, &c, 1); - if(!err) err = -1; - - if(err != -1) { - pos = strlen(buf); - buf[pos] = c; - buf[pos+1] = 0; - - if(strlen(buf) > 4) - if(!strcmp(buf+strlen(buf)-4, "\r\n\r\n")) - break; - } - } - } - } - - if(err != -1 && strlen(buf)) { - char *p = strstr(buf, " "); - - err = -1; - - if(p) - if(atoi(++p) == 200) - err = 0; - - fcntl(sockfd, F_SETFL, fl); - if(fl & O_NONBLOCK) { - errno = EINPROGRESS; - err = -1; - } - } - - in_http_connect = 0; - - return err; -} - -int cw_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, - int ssl) { - int rc; - struct sockaddr_in ba; - - if(bindaddr) - if(strlen(bindaddr)) { -#ifdef HAVE_INET_ATON - struct in_addr addr; - rc = inet_aton(bindaddr, &addr); - ba.sin_addr.s_addr = addr.s_addr; -#else - rc = inet_pton(AF_INET, bindaddr, &ba); -#endif - - if(rc) { - ba.sin_port = 0; - rc = bind(sockfd, (struct sockaddr *) &ba, sizeof(ba)); - } else { - rc = -1; - } - - if(rc) return rc; - } - - if(proxyhost && !in_http_connect) - rc = cw_http_connect(sockfd, serv_addr, addrlen); - else - rc = connect(sockfd, serv_addr, addrlen); - -#ifdef HAVE_OPENSSL - if(ssl && !rc) { - sslsock *p = addsock(sockfd); - if(SSL_connect(p->ssl) != 1) - return -1; // XXX "Can't connect to SSL" - } -#endif - - return rc; -} - -int cw_nb_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, - int ssl, int *state) { - int rc = 0; - struct sockaddr_in ba; - - if(bindaddr) - if(strlen(bindaddr)) { -#ifdef HAVE_INET_ATON - struct in_addr addr; - rc = inet_aton(bindaddr, &addr); - ba.sin_addr.s_addr = addr.s_addr; -#else - rc = inet_pton(AF_INET, bindaddr, &ba); -#endif - - if(rc) { - ba.sin_port = 0; - rc = bind(sockfd, (struct sockaddr *) &ba, sizeof(ba)); - } else { - rc = -1; - } - - if(rc) return rc; - } - -#ifdef HAVE_SSL - if(ssl) { - if ( !(*state & CW_CONNECT_WANT_SOMETHING)) { - rc = cw_connect(sockfd, serv_addr, addrlen, 0); - } else { /* check if the socket is connected correctly */ - int optlen = sizeof(int), optval; - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, - (socklen_t*)&optlen) || optval) - return -1; - } - - if(!rc) { -#ifdef HAVE_GNUTLS - int ret; -#endif - sslsock *p; - if (*state & CW_CONNECT_SSL) - p = getsock(sockfd); - else - p = addsock(sockfd); - -#ifdef HAVE_GNUTLS - do { - ret = gnutls_handshake(p->session); - } while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)); - if (ret < 0) { - gnutls_deinit(p->session); - gnutls_perror(ret); - return -1; - } - else{ - *state = 1; - return 0; - } -#elif defined HAVE_OPENSSL - rc = SSL_connect(p->ssl); - switch(rc){ - case 1: - *state = 0; - return 0; - case 0: - return -1; - default: - switch (SSL_get_error(p->ssl, rc)){ - case SSL_ERROR_WANT_READ: - *state = CW_CONNECT_SSL | CW_CONNECT_WANT_READ; - return 0; - case SSL_ERROR_WANT_WRITE: - *state = CW_CONNECT_SSL | CW_CONNECT_WANT_WRITE; - return 0; - default: - return -1; - } - } -#endif - } else { /* catch EINPROGRESS error from the connect call */ - if (errno == EINPROGRESS){ - *state = CW_CONNECT_STARTED | CW_CONNECT_WANT_WRITE; - return 0; - } - } - - return rc; - } -#endif - if ( !(*state & CW_CONNECT_WANT_SOMETHING)) { - rc = cw_connect(sockfd, serv_addr, addrlen, 0); - } else { /* check if the socket is connected correctly */ - int optlen = sizeof(int), optval; - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, - (socklen_t*)&optlen) || optval) - return -1; - *state = 0; - return 0; - } - if (rc) - if (errno == EINPROGRESS){ - *state = CW_CONNECT_STARTED | CW_CONNECT_WANT_WRITE; - return 0; - } - return rc; -} - -int cw_accept(int s, struct sockaddr *addr, int *addrlen, int ssl) { -#ifdef HAVE_OPENSSL - int rc; - - if(ssl) { - rc = accept(s, addr, (socklen_t*)addrlen); - - if(!rc) { - sslsock *p = addsock(s); - if(SSL_accept(p->ssl) != 1) - return -1; - } - return rc; - } -#endif - return accept(s, addr, (socklen_t*)addrlen); -} - -int cw_write(int fd, const void *buf, int count, int ssl) { -#ifdef HAVE_SSL - sslsock *p; - - if(ssl) { -#ifdef HAVE_GNUTLS - p = getsock(fd); - if(p) { - int ret; - if((ret = gnutls_record_send( p->session, buf, count) < 0)) - fprintf(stderr, "Can't write to server"); - return ret; - } -#elif defined HAVE_OPENSSL - if((p = getsock(fd)) != NULL) - return SSL_write(p->ssl, buf, count); -#endif - } -#endif // HAVE_SSL - return write(fd, buf, count); -} - -int cw_read(int fd, void *buf, int count, int ssl) { -#ifdef HAVE_SSL - sslsock *p; - - if(ssl) { -#ifdef HAVE_GNUTLS - p = getsock(fd); - if(p) { - int ret; - do { - ret = gnutls_record_recv(p->session, buf, count); - } while (ret < 0 && - (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)); - return ret; - } -#elif defined HAVE_OPENSSL - if((p = getsock(fd)) != NULL) - return SSL_read(p->ssl, buf, count); -#endif - } -#endif // HAVE_SSL - return read(fd, buf, count); -} - -void cw_close(int fd) { -#ifdef HAVE_SSL - delsock(fd); -#endif - close(fd); -} - -#define FREEVAR(v) if(v) free(v), v = 0; - -void cw_setbind(const char *abindaddr) { - FREEVAR(bindaddr); - bindaddr = strdup(abindaddr); -} - -void cw_setproxy(const char *aproxyhost, int aproxyport, - const char *aproxyuser, const char *aproxypass) { - FREEVAR(proxyhost); - FREEVAR(proxyuser); - FREEVAR(proxypass); - - if(aproxyhost && strlen(aproxyhost)) proxyhost = strdup(aproxyhost); - if(aproxyuser && strlen(aproxyuser)) proxyuser = strdup(aproxyuser); - if(aproxypass && strlen(aproxypass)) proxypass = strdup(aproxypass); - proxyport = aproxyport; -} - -char *cw_base64_encode(const char *in) { - static char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._"; - - int j = 0; - int inlen = strlen(in); - char *out = (char *) malloc(inlen*4+1), c; - - for(out[0] = 0; inlen >= 3; inlen -= 3) { - strncat(out, &base64digits[ in[j] >> 2 ], 1); - strncat(out, &base64digits[ ((in[j] << 4) & 0x30) | (in[j+1] >> 4) ], 1); - strncat(out, &base64digits[ ((in[j+1] << 2) & 0x3c) | (in[j+2] >> 6) ], 1); - strncat(out, &base64digits[ in[j+2] & 0x3f ], 1); - j += 3; - } - - if(inlen > 0) { - unsigned char fragment; - - strncat(out, &base64digits[in[j] >> 2], 1); - fragment = (in[j] << 4) & 0x30; - - if(inlen > 1) - fragment |= in[j+1] >> 4; - - strncat(out, &base64digits[fragment], 1); - - c = (inlen < 2) ? '-' : base64digits[ (in[j+1] << 2) & 0x3c ]; - strncat(out, &c, 1); - c = '-'; - strncat(out, &c, 1); - } - - return out; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/connwrap.h --- a/mcabber/connwrap/connwrap.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -#ifndef __CONNWRAP_H__ -#define __CONNWRAP_H__ - -#if HAVE_CONFIG_H -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -int cw_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, int ssl); - -#define CW_CONNECT_STARTED 0x1 -#define CW_CONNECT_SSL 0x2 -#define CW_CONNECT_WANT_READ 0x4 -#define CW_CONNECT_WANT_WRITE 0x8 -#define CW_CONNECT_WANT_SOMETHING 0xC -#define CW_CONNECT_BLOCKING 0x10 - -/* non-blocking socket - state should be initialized with 0, subsequent calls should keep the - modified state (state is a bitwise OR between CW_CONNECT_XXX) - returns 0 for OK, or if it wants subsequent calls - -1 for a fatal error - */ -int cw_nb_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, int ssl, int *state); -int cw_accept(int s, struct sockaddr *addr, int *addrlen, int ssl); - -int cw_write(int fd, const void *buf, int count, int ssl); -int cw_read(int fd, void *buf, int count, int ssl); - -void cw_close(int fd); - -void cw_set_ssl_options(int sslverify, const char *sslcafile, const char *sslcapath, const char *sslciphers, const char *sslpeer); -const char *cw_get_ssl_error(void); -void cw_setproxy(const char *aproxyhost, int aproxyport, const char *aproxyuser, const char *aproxypass); -void cw_setbind(const char *abindaddr); - -char *cw_base64_encode(const char *in); - -#ifdef __cplusplus -} -#endif - -#endif diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/connwrap.spec --- a/mcabber/connwrap/connwrap.spec Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -Summary: A static library made in motor IDE -Name: connwrap -Version: 0.1 -Release: 1 -Copyright: GPL -Group: Development/Libraries -URL: http://konst.org.ua/motor/ -Packager: Konstantin Klyagin -Source: %{name}-%{version}.tar.gz -BuildRoot: /var/tmp/%{name}-buildroot/ - -%description -Motor is a text mode based programming environment for Linux. It -consists of a powerful editor with syntax highlight feature, project -manager, makefile generator, gdb front-end, etc. Deep CVS integration is -also provided. - -%prep -%setup - -%build -./configure --prefix=/usr -make - -%install -rm -rf $RPM_BUILD_ROOT -make prefix=$RPM_BUILD_ROOT/usr sysconfdir=$RPM_BUILD_ROOT/etc install - -find $RPM_BUILD_ROOT/usr/ -type f -print | \ - grep -v '\/(README|COPYING|INSTALL|TODO|ChangeLog)$' | \ - sed "s@^$RPM_BUILD_ROOT@@g" | \ - sed 's/^\(.\+\/man.\+\)$/\1*/g' \ - > %{name}-%{version}-filelist - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -f %{name}-%{version}-filelist -%defattr(-, root, root) - -%doc README COPYING INSTALL TODO ChangeLog - -%changelog diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/md5.c --- a/mcabber/connwrap/md5.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -#if HAVE_CONFIG_H -# include -#endif - -#include "md5.h" - -#if STDC_HEADERS -# include -#else -# if !HAVE_STRCHR -# define strchr index -# define strrchr rindex -# endif -char *strchr (), *strrchr (); -# if !HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# define memmove(d, s, n) bcopy ((s), (d), (n)) -# endif -#endif - -#ifdef TEST -/* - * Compile with -DTEST to create a self-contained executable test program. - * The test program should print out the same values as given in section - * A.5 of RFC 1321, reproduced below. - */ -main() -{ - static const char *const test[7] = { - "", /*d41d8cd98f00b204e9800998ecf8427e*/ - "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ - "abc", /*900150983cd24fb0d6963f7d28e17f72*/ - "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ - "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - /*d174ab98d277d9f5a5611c2c9f419d9f*/ - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ - }; - int i; - - for (i = 0; i < 7; ++i) { - md5_state_t state; - md5_byte_t digest[16]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); - md5_finish(&state, digest); - printf("MD5 (\"%s\") = ", test[i]); - for (di = 0; di < 16; ++di) - printf("%02x", digest[di]); - printf("\n"); - } - return 0; -} -#endif /* TEST */ - - -/* - * For reference, here is the program that computed the T values. - */ -#if 0 -#include -main() -{ - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - printf("#define T%d 0x%08lx\n", i, v); - } - return 0; -} -#endif -/* - * End of T computation program. - */ -#define T1 0xd76aa478 -#define T2 0xe8c7b756 -#define T3 0x242070db -#define T4 0xc1bdceee -#define T5 0xf57c0faf -#define T6 0x4787c62a -#define T7 0xa8304613 -#define T8 0xfd469501 -#define T9 0x698098d8 -#define T10 0x8b44f7af -#define T11 0xffff5bb1 -#define T12 0x895cd7be -#define T13 0x6b901122 -#define T14 0xfd987193 -#define T15 0xa679438e -#define T16 0x49b40821 -#define T17 0xf61e2562 -#define T18 0xc040b340 -#define T19 0x265e5a51 -#define T20 0xe9b6c7aa -#define T21 0xd62f105d -#define T22 0x02441453 -#define T23 0xd8a1e681 -#define T24 0xe7d3fbc8 -#define T25 0x21e1cde6 -#define T26 0xc33707d6 -#define T27 0xf4d50d87 -#define T28 0x455a14ed -#define T29 0xa9e3e905 -#define T30 0xfcefa3f8 -#define T31 0x676f02d9 -#define T32 0x8d2a4c8a -#define T33 0xfffa3942 -#define T34 0x8771f681 -#define T35 0x6d9d6122 -#define T36 0xfde5380c -#define T37 0xa4beea44 -#define T38 0x4bdecfa9 -#define T39 0xf6bb4b60 -#define T40 0xbebfbc70 -#define T41 0x289b7ec6 -#define T42 0xeaa127fa -#define T43 0xd4ef3085 -#define T44 0x04881d05 -#define T45 0xd9d4d039 -#define T46 0xe6db99e5 -#define T47 0x1fa27cf8 -#define T48 0xc4ac5665 -#define T49 0xf4292244 -#define T50 0x432aff97 -#define T51 0xab9423a7 -#define T52 0xfc93a039 -#define T53 0x655b59c3 -#define T54 0x8f0ccc92 -#define T55 0xffeff47d -#define T56 0x85845dd1 -#define T57 0x6fa87e4f -#define T58 0xfe2ce6e0 -#define T59 0xa3014314 -#define T60 0x4e0811a1 -#define T61 0xf7537e82 -#define T62 0xbd3af235 -#define T63 0x2ad7d2bb -#define T64 0xeb86d391 - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - -#ifndef ARCH_IS_BIG_ENDIAN -# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ -#endif -#if ARCH_IS_BIG_ENDIAN - - /* - * On big-endian machines, we must arrange the bytes in the right - * order. (This also works on machines of unknown byte order.) - */ - md5_word_t X[16]; - const md5_byte_t *xp = data; - int i; - - for (i = 0; i < 16; ++i, xp += 4) - X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - -#else /* !ARCH_IS_BIG_ENDIAN */ - - /* - * On little-endian machines, we can process properly aligned data - * without copying it. - */ - md5_word_t xbuf[16]; - const md5_word_t *X; - - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } -#endif - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = 0xefcdab89; - pms->abcd[2] = 0x98badcfe; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/connwrap/md5.h --- a/mcabber/connwrap/md5.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.h is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . - 1999-05-03 lpd Original version. - */ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This code has some adaptations for the Ghostscript environment, but it - * will compile and run correctly in any environment with 8-bit chars and - * 32-bit ints. Specifically, it assumes that if the following are - * defined, they have the same meaning as in Ghostscript: P1, P2, P3, - * ARCH_IS_BIG_ENDIAN. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -#ifdef P1 -void md5_init(P1(md5_state_t *pms)); -#else -void md5_init(md5_state_t *pms); -#endif - -/* Append a string to the message. */ -#ifdef P3 -void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); -#else -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); -#endif - -/* Finish the message and return the digest. */ -#ifdef P2 -void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); -#else -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); -#endif - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* md5_INCLUDED */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/Makefile.am --- a/mcabber/libjabber/Makefile.am Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -noinst_LIBRARIES = liblibjabber.a -EXTRA_DIST = jid.c log.c jutil.c str.c expat.c hashtable.c genhash.c pproxy.c pool.c rate.c xmlparse.c xstream.c xmltok.c xmlnode.c jconn.c xmlrole.c jpacket.c snprintf.c socket.c sha.c xmltok_impl_c.h latin1tab.h log.h asciitab.h libxode.h jabber.h hashtable.h xmlparse.h iasciitab.h xmldef.h xmltok.h utf8tab.h xmltok_impl.h xmlrole.h nametab.h xmltok_ns_c.h -AUTOMAKE_OPTIONS = foreign - -liblibjabber_a_SOURCES = jid.c log.c jutil.c str.c expat.c hashtable.c genhash.c pproxy.c pool.c rate.c xmlparse.c xstream.c xmltok.c xmlnode.c jconn.c xmlrole.c jpacket.c snprintf.c socket.c sha.c - -SUBDIRS = -INCLUDES = -I$(top_srcdir)/connwrap -CPPFLAGS = diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/aclocal.m4 --- a/mcabber/libjabber/aclocal.m4 Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -dnl aclocal.m4 generated automatically by aclocal 1.4-p6 - -dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without -dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A -dnl PARTICULAR PURPOSE. - -# Do all the work for Automake. This macro actually does too much -- -# some checks are only needed if your package does certain things. -# But this isn't really a big deal. - -# serial 1 - -dnl Usage: -dnl AM_INIT_AUTOMAKE(package,version, [no-define]) - -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL]) -PACKAGE=[$1] -AC_SUBST(PACKAGE) -VERSION=[$2] -AC_SUBST(VERSION) -dnl test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) -fi -ifelse([$3],, -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) -AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) -AC_REQUIRE([AM_SANITY_CHECK]) -AC_REQUIRE([AC_ARG_PROGRAM]) -dnl FIXME This is truly gross. -missing_dir=`cd $ac_aux_dir && pwd` -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) -AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) -AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) -AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) -AC_REQUIRE([AC_PROG_MAKE_SET])]) - -# Copyright 2002 Free Software Foundation, Inc. - -# 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, 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 - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.4-p6])]) - -# -# Check to make sure that the build environment is sane. -# - -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftestfile -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` - if test "[$]*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftestfile` - fi - if test "[$]*" != "X $srcdir/configure conftestfile" \ - && test "[$]*" != "X conftestfile $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "[$]2" = conftestfile - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -rm -f conftest* -AC_MSG_RESULT(yes)]) - -dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) -dnl The program must properly implement --version. -AC_DEFUN([AM_MISSING_PROG], -[AC_MSG_CHECKING(for working $2) -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if ($2 --version) < /dev/null > /dev/null 2>&1; then - $1=$2 - AC_MSG_RESULT(found) -else - $1="$3/missing $2" - AC_MSG_RESULT(missing) -fi -AC_SUBST($1)]) - -# Define a conditional. - -AC_DEFUN([AM_CONDITIONAL], -[AC_SUBST($1_TRUE) -AC_SUBST($1_FALSE) -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi]) - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/asciitab.h --- a/mcabber/libjabber/asciitab.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/config.h.in --- a/mcabber/libjabber/config.h.in Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* include/config.h.in. Generated automatically from configure.in by autoheader. */ - -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define if your processor stores words with the most significant - byte first (like Motorola and SPARC, unlike Intel and VAX). */ -#undef WORDS_BIGENDIAN - -#undef POOL_NO_HEAP -#undef HAVE_LIBSOCKET -#undef HAVE_SNPRINTF - -/* The number of bytes in a int. */ -#undef SIZEOF_INT - -/* The number of bytes in a short. */ -#undef SIZEOF_SHORT - -/* Define if you have the nsl library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Name of package */ -#undef PACKAGE - -/* Version number of package */ -#undef VERSION - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/configure --- a/mcabber/libjabber/configure Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1469 +0,0 @@ -#! /bin/sh - -# Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.13 -# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. - -# Defaults: -ac_help= -ac_default_prefix=/usr/local -# Any additions from configure.in: -ac_help="$ac_help - --disable-jabber Build without Jabber" - -# Initialize some variables set by options. -# The variables have the same names as the options, with -# dashes changed to underlines. -build=NONE -cache_file=./config.cache -exec_prefix=NONE -host=NONE -no_create= -nonopt=NONE -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -target=NONE -verbose= -x_includes=NONE -x_libraries=NONE -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -# Initialize some other variables. -subdirs= -MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} -# Maximum number of lines to put in a shell here document. -ac_max_here_lines=12 - -ac_prev= -for ac_option -do - - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - case "$ac_option" in - -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) ac_optarg= ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case "$ac_option" in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - eval "enable_${ac_feature}=no" ;; - - -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "enable_${ac_feature}='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he) - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat << EOF -Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] -Configuration: - --cache-file=FILE cache test results in FILE - --help print this message - --no-create do not create output files - --quiet, --silent do not print \`checking...' messages - --version print the version of autoconf that created configure -Directory and file names: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [same as prefix] - --bindir=DIR user executables in DIR [EPREFIX/bin] - --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] - --libexecdir=DIR program executables in DIR [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data in DIR - [PREFIX/share] - --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data in DIR - [PREFIX/com] - --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] - --libdir=DIR object code libraries in DIR [EPREFIX/lib] - --includedir=DIR C header files in DIR [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - --srcdir=DIR find the sources in DIR [configure dir or ..] - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM - run sed PROGRAM on installed program names -EOF - cat << EOF -Host type: - --build=BUILD configure for building on BUILD [BUILD=HOST] - --host=HOST configure for HOST [guessed] - --target=TARGET configure for TARGET [TARGET=HOST] -Features and packages: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR -EOF - if test -n "$ac_help"; then - echo "--enable and --with options recognized:$ac_help" - fi - exit 0 ;; - - -host | --host | --hos | --ho) - ac_prev=host ;; - -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix="$ac_optarg" ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix="$ac_optarg" ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.13" - exit 0 ;; - - -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "with_${ac_package}='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - eval "with_${ac_package}=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes="$ac_optarg" ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries="$ac_optarg" ;; - - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } - ;; - - *) - if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" 1>&2 - fi - if test "x$nonopt" != xNONE; then - { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } - fi - nonopt="$ac_option" - ;; - - esac -done - -if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } -fi - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 6 checking for... messages and results -# 5 compiler messages saved in config.log -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>./config.log - -echo "\ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. -" 1>&5 - -# Strip out --no-create and --no-recursion so they do not pile up. -# Also quote any args containing shell metacharacters. -ac_configure_args= -for ac_arg -do - case "$ac_arg" in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ac_configure_args="$ac_configure_args '$ac_arg'" ;; - *) ac_configure_args="$ac_configure_args $ac_arg" ;; - esac -done - -# NLS nuisances. -# Only set these to C if already set. These must not be set unconditionally -# because not all systems understand e.g. LANG=C (notably SCO). -# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! -# Non-C LC_CTYPE values break the ctype check. -if test "${LANG+set}" = set; then LANG=C; export LANG; fi -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi -if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi -if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo > confdefs.h - -# A filename unique to this package, relative to the directory that -# configure is in, which we can look for to find out if srcdir is correct. -ac_unique_file=aclocal.m4 - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_prog=$0 - ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` - test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } - else - { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } - fi -fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` - -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - echo "loading site script $ac_site_file" - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - echo "loading cache $cache_file" - . $cache_file -else - echo "creating cache $cache_file" - > $cache_file -fi - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -ac_exeext= -ac_objext=o -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - - -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } -fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. - -am__api_version="1.4" -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# ./install, which can be erroneously created by make from ./install.sh. -echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:559: checking for a BSD compatible install" >&5 -if test -z "$INSTALL"; then -if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" - for ac_dir in $PATH; do - # Account for people who put trailing slashes in PATH elements. - case "$ac_dir/" in - /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - if test -f $ac_dir/$ac_prog; then - if test $ac_prog = install && - grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - else - ac_cv_path_install="$ac_dir/$ac_prog -c" - break 2 - fi - fi - done - ;; - esac - done - IFS="$ac_save_IFS" - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL="$ac_cv_path_install" - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL="$ac_install_sh" - fi -fi -echo "$ac_t""$INSTALL" 1>&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 -echo "configure:612: checking whether build environment is sane" >&5 -# Just in case -sleep 1 -echo timestamp > conftestfile -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftestfile` - fi - if test "$*" != "X $srcdir/configure conftestfile" \ - && test "$*" != "X conftestfile $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - { echo "configure: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" 1>&2; exit 1; } - fi - - test "$2" = conftestfile - ) -then - # Ok. - : -else - { echo "configure: error: newly created file is older than distributed files! -Check your system clock" 1>&2; exit 1; } -fi -rm -f conftest* -echo "$ac_t""yes" 1>&6 -if test "$program_transform_name" = s,x,x,; then - program_transform_name= -else - # Double any \ or $. echo might interpret backslashes. - cat <<\EOF_SED > conftestsed -s,\\,\\\\,g; s,\$,$$,g -EOF_SED - program_transform_name="`echo $program_transform_name|sed -f conftestsed`" - rm -f conftestsed -fi -test "$program_prefix" != NONE && - program_transform_name="s,^,${program_prefix},; $program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" - -# sed with no file args requires a program. -test "$program_transform_name" = "" && program_transform_name="s,x,x," - -echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:669: checking whether ${MAKE-make} sets \${MAKE}" >&5 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftestmake <<\EOF -all: - @echo 'ac_maketemp="${MAKE}"' -EOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi -rm -f conftestmake -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$ac_t""yes" 1>&6 - SET_MAKE= -else - echo "$ac_t""no" 1>&6 - SET_MAKE="MAKE=${MAKE-make}" -fi - - -PACKAGE=libjabber - -VERSION=0.1 - -if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then - { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } -fi -cat >> confdefs.h <> confdefs.h <&6 -echo "configure:715: checking for working aclocal-${am__api_version}" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then - ACLOCAL=aclocal-${am__api_version} - echo "$ac_t""found" 1>&6 -else - ACLOCAL="$missing_dir/missing aclocal-${am__api_version}" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 -echo "configure:728: checking for working autoconf" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (autoconf --version) < /dev/null > /dev/null 2>&1; then - AUTOCONF=autoconf - echo "$ac_t""found" 1>&6 -else - AUTOCONF="$missing_dir/missing autoconf" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working automake-${am__api_version}""... $ac_c" 1>&6 -echo "configure:741: checking for working automake-${am__api_version}" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then - AUTOMAKE=automake-${am__api_version} - echo "$ac_t""found" 1>&6 -else - AUTOMAKE="$missing_dir/missing automake-${am__api_version}" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 -echo "configure:754: checking for working autoheader" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (autoheader --version) < /dev/null > /dev/null 2>&1; then - AUTOHEADER=autoheader - echo "$ac_t""found" 1>&6 -else - AUTOHEADER="$missing_dir/missing autoheader" - echo "$ac_t""missing" 1>&6 -fi - -echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 -echo "configure:767: checking for working makeinfo" >&5 -# Run test in a subshell; some versions of sh will print an error if -# an executable is not found, even if stderr is redirected. -# Redirect stdin to placate older versions of autoconf. Sigh. -if (makeinfo --version) < /dev/null > /dev/null 2>&1; then - MAKEINFO=makeinfo - echo "$ac_t""found" 1>&6 -else - MAKEINFO="$missing_dir/missing makeinfo" - echo "$ac_t""missing" 1>&6 -fi - - - -# Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:784: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_RANLIB="ranlib" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" -fi -fi -RANLIB="$ac_cv_prog_RANLIB" -if test -n "$RANLIB"; then - echo "$ac_t""$RANLIB" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -# Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:814: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="gcc" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:844: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_prog_rejected=no - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - break - fi - done - IFS="$ac_save_ifs" -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - set dummy "$ac_dir/$ac_word" "$@" - shift - ac_cv_prog_CC="$@" - fi -fi -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - if test -z "$CC"; then - case "`uname -s`" in - *win32* | *WIN32*) - # Extract the first word of "cl", so it can be a program name with args. -set dummy cl; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:895: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="cl" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - ;; - esac - fi - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } -fi - -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:927: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -cat > conftest.$ac_ext << EOF - -#line 938 "configure" -#include "confdefs.h" - -main(){return(0);} -EOF -if { (eval echo configure:943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - ac_cv_prog_cc_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cc_cross=no - else - ac_cv_prog_cc_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cc_works=no -fi -rm -fr conftest* -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 -if test $ac_cv_prog_cc_works = no; then - { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:969: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 -cross_compiling=$ac_cv_prog_cc_cross - -echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:974: checking whether we are using GNU C" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes -else - ac_cv_prog_gcc=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then - GCC=yes -else - GCC= -fi - -ac_test_CFLAGS="${CFLAGS+set}" -ac_save_CFLAGS="$CFLAGS" -CFLAGS= -echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1002: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_cc_g=yes -else - ac_cv_prog_cc_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi - - -# Check whether --enable-jabber or --disable-jabber was given. -if test "${enable_jabber+set}" = set; then - enableval="$enable_jabber" - build_jabber="$enableval" -else - build_jabber="yes" -fi - - - -if test "x$build_jabber" = xyes; then - BUILD_JABBER_TRUE= - BUILD_JABBER_FALSE='#' -else - BUILD_JABBER_TRUE='#' - BUILD_JABBER_FALSE= -fi - -if test "$build_jabber" = "yes"; then - for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1058: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CXX="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CXX="$ac_cv_prog_CXX" -if test -n "$CXX"; then - echo "$ac_t""$CXX" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -test -n "$CXX" && break -done -test -n "$CXX" || CXX="gcc" - - -echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1090: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 - -ac_ext=C -# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cxx_cross - -cat > conftest.$ac_ext << EOF - -#line 1101 "configure" -#include "confdefs.h" - -int main(){return(0);} -EOF -if { (eval echo configure:1106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - ac_cv_prog_cxx_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cxx_cross=no - else - ac_cv_prog_cxx_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cxx_works=no -fi -rm -fr conftest* -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 -if test $ac_cv_prog_cxx_works = no; then - { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1132: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 -cross_compiling=$ac_cv_prog_cxx_cross - -echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:1137: checking whether we are using GNU C++" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gxx=yes -else - ac_cv_prog_gxx=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gxx" 1>&6 - -if test $ac_cv_prog_gxx = yes; then - GXX=yes -else - GXX= -fi - -ac_test_CXXFLAGS="${CXXFLAGS+set}" -ac_save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS= -echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:1165: checking whether ${CXX-g++} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.cc -if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then - ac_cv_prog_cxx_g=yes -else - ac_cv_prog_cxx_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS="$ac_save_CXXFLAGS" -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi - -fi - -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Any assignment to VPATH causes Sun make to only execute -# the first set of double-colon rules, so remove it if not needed. -# If there is a colon in the path, we need to keep it. -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' -fi - -trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -cat > conftest.defs <<\EOF -s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g -s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g -s%\[%\\&%g -s%\]%\\&%g -s%\$%$$%g -EOF -DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` -rm -f conftest.defs - - -# Without the "./", some shells look in PATH for config.status. -: ${CONFIG_STATUS=./config.status} - -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS </dev/null | sed 1q`: -# -# $0 $ac_configure_args -# -# Compiler output produced by configure, useful for debugging -# configure, is in ./config.log if it exists. - -ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" -for ac_option -do - case "\$ac_option" in - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" - exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; - -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.13" - exit 0 ;; - -help | --help | --hel | --he | --h) - echo "\$ac_cs_usage"; exit 0 ;; - *) echo "\$ac_cs_usage"; exit 1 ;; - esac -done - -ac_given_srcdir=$srcdir -ac_given_INSTALL="$INSTALL" - -trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF -$ac_vpsub -$extrasub -s%@SHELL@%$SHELL%g -s%@CFLAGS@%$CFLAGS%g -s%@CPPFLAGS@%$CPPFLAGS%g -s%@CXXFLAGS@%$CXXFLAGS%g -s%@FFLAGS@%$FFLAGS%g -s%@DEFS@%$DEFS%g -s%@LDFLAGS@%$LDFLAGS%g -s%@LIBS@%$LIBS%g -s%@exec_prefix@%$exec_prefix%g -s%@prefix@%$prefix%g -s%@program_transform_name@%$program_transform_name%g -s%@bindir@%$bindir%g -s%@sbindir@%$sbindir%g -s%@libexecdir@%$libexecdir%g -s%@datadir@%$datadir%g -s%@sysconfdir@%$sysconfdir%g -s%@sharedstatedir@%$sharedstatedir%g -s%@localstatedir@%$localstatedir%g -s%@libdir@%$libdir%g -s%@includedir@%$includedir%g -s%@oldincludedir@%$oldincludedir%g -s%@infodir@%$infodir%g -s%@mandir@%$mandir%g -s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g -s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g -s%@INSTALL_DATA@%$INSTALL_DATA%g -s%@PACKAGE@%$PACKAGE%g -s%@VERSION@%$VERSION%g -s%@ACLOCAL@%$ACLOCAL%g -s%@AUTOCONF@%$AUTOCONF%g -s%@AUTOMAKE@%$AUTOMAKE%g -s%@AUTOHEADER@%$AUTOHEADER%g -s%@MAKEINFO@%$MAKEINFO%g -s%@SET_MAKE@%$SET_MAKE%g -s%@RANLIB@%$RANLIB%g -s%@CC@%$CC%g -s%@BUILD_JABBER_TRUE@%$BUILD_JABBER_TRUE%g -s%@BUILD_JABBER_FALSE@%$BUILD_JABBER_FALSE%g -s%@CXX@%$CXX%g - -CEOF -EOF - -cat >> $CONFIG_STATUS <<\EOF - -# Split the substitutions into bite-sized pieces for seds with -# small command number limits, like on Digital OSF/1 and HP-UX. -ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. -ac_file=1 # Number of current file. -ac_beg=1 # First line for current file. -ac_end=$ac_max_sed_cmds # Line after last line for current file. -ac_more_lines=: -ac_sed_cmds="" -while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file - else - sed "${ac_end}q" conftest.subs > conftest.s$ac_file - fi - if test ! -s conftest.s$ac_file; then - ac_more_lines=false - rm -f conftest.s$ac_file - else - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f conftest.s$ac_file" - else - ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" - fi - ac_file=`expr $ac_file + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_cmds` - fi -done -if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat -fi -EOF - -cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF -for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; - esac - - # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. - - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" - # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` - else - ac_dir_suffix= ac_dots= - fi - - case "$ac_given_srcdir" in - .) srcdir=. - if test -z "$ac_dots"; then top_srcdir=. - else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; - /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; - *) # Relative path. - srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" - top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - - case "$ac_given_INSTALL" in - [/$]*) INSTALL="$ac_given_INSTALL" ;; - *) INSTALL="$ac_dots$ac_given_INSTALL" ;; - esac - - echo creating "$ac_file" - rm -f "$ac_file" - configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." - case "$ac_file" in - *Makefile*) ac_comsub="1i\\ -# $configure_input" ;; - *) ac_comsub= ;; - esac - - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - sed -e "$ac_comsub -s%@configure_input@%$configure_input%g -s%@srcdir@%$srcdir%g -s%@top_srcdir@%$top_srcdir%g -s%@INSTALL@%$INSTALL%g -" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file -fi; done -rm -f conftest.s* - -EOF -cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF - -exit 0 -EOF -chmod +x $CONFIG_STATUS -rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/configure.in --- a/mcabber/libjabber/configure.in Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -AC_INIT(aclocal.m4) -AM_INIT_AUTOMAKE(libjabber, 0.1) - -AC_PROG_RANLIB -AC_PROG_CC - -AC_ARG_ENABLE(jabber, [ --disable-jabber Build without Jabber], build_jabber="$enableval", build_jabber="yes") -AM_CONDITIONAL(BUILD_JABBER, test "x$build_jabber" = xyes) - -if test "$build_jabber" = "yes"; then - AC_PROG_CXX -fi - -AC_OUTPUT(Makefile) diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/expat.c --- a/mcabber/libjabber/expat.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include - -/** - * callback function used for start elements - * - * This function is used internally by expat.c as a callback function - * given to expat. It will create a new xmlnode and add it to the - * already created xmlnode tree. - * - * @param userdata pointer to the parent xmlnode instance (NULL if this function is called for the root note) - * @param name name of the starting element - * @param atts attributes that are contained in the start element - */ -void expat_startElement(void* userdata, const char* name, const char** atts) -{ - /* get the xmlnode pointed to by the userdata */ - xmlnode *x = userdata; - xmlnode current = *x; - - if (current == NULL) - { - /* allocate a base node */ - current = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(current, atts); - *x = current; - } - else - { - *x = xmlnode_insert_tag(current, name); - xmlnode_put_expat_attribs(*x, atts); - } -} - -/** - * callback function used for end elements - * - * This function is used internally by expat.c as a callback function - * given to expat. It will complete an xmlnode and update the userdata pointer - * to point to the node that is parent of the next starting element. - * - * @param userdata pointer to the current xmlnode - * @param name name of the ending element (ignored by this function) - */ -void expat_endElement(void* userdata, const char* name) -{ - xmlnode *x = userdata; - xmlnode current = *x; - - current->complete = 1; - current = xmlnode_get_parent(current); - - /* if it's NULL we've hit the top folks, otherwise back up a level */ - if(current != NULL) - *x = current; -} - -/** - * callback function for CDATA nodes - * - * This function will insert CDATA in an xmlnode - * - * @param userdata pointer to the current xmlnode - * @param s pointer to the CDATA string (not zero terminated!) - * @param len length of the CDATA string - */ -void expat_charData(void* userdata, const char* s, int len) -{ - xmlnode *x = userdata; - xmlnode current = *x; - - xmlnode_insert_cdata(current, s, len); -} - -/** - * create an xmlnode instance (possibly including other xmlnode instances) by parsing a string - * - * This function will parse a string containing an XML document and create an xmlnode graph - * - * @param str the string containing the XML document (not necessarily zero terminated) - * @param len the length of the string (without the zero byte, if present) - * @return the graph of xmlnodes that represent the parsed document, NULL on failure - */ -xmlnode xmlnode_str(char *str, int len) -{ - XML_Parser p; - xmlnode *x, node; /* pointer to an xmlnode */ - - if(NULL == str) - return NULL; - - x = malloc(sizeof(void *)); - - *x = NULL; /* pointer to NULL */ - p = XML_ParserCreate(NULL); - XML_SetUserData(p, x); - XML_SetElementHandler(p, expat_startElement, expat_endElement); - XML_SetCharacterDataHandler(p, expat_charData); - if(!XML_Parse(p, str, len, 1)) - { - /* jdebug(ZONE,"xmlnode_str_error: %s",(char *)XML_ErrorString(XML_GetErrorCode(p)));*/ - xmlnode_free(*x); - *x = NULL; - } - node = *x; - free(x); - XML_ParserFree(p); - return node; /* return the xmlnode x points to */ -} - -/** - * create an xmlnode instance (possibly including other xmlnode instances) by parsing a file - * - * This function will parse a file containing an XML document and create an xmlnode graph - * - * @param file the filename - * @return the graph of xmlnodes that represent the parsed document, NULL on failure - */ -xmlnode xmlnode_file(char *file) -{ - XML_Parser p; - xmlnode *x, node; /* pointer to an xmlnode */ - char buf[BUFSIZ]; - int done, fd, len; - - if(NULL == file) - return NULL; - - fd = open(file,O_RDONLY); - if(fd < 0) - return NULL; - - x = malloc(sizeof(void *)); - - *x = NULL; /* pointer to NULL */ - p = XML_ParserCreate(NULL); - XML_SetUserData(p, x); - XML_SetElementHandler(p, expat_startElement, expat_endElement); - XML_SetCharacterDataHandler(p, expat_charData); - do{ - len = read(fd, buf, BUFSIZ); - done = len < BUFSIZ; - if(!XML_Parse(p, buf, len, done)) - { - /* jdebug(ZONE,"xmlnode_file_parseerror: %s",(char *)XML_ErrorString(XML_GetErrorCode(p)));*/ - xmlnode_free(*x); - *x = NULL; - done = 1; - } - }while(!done); - - node = *x; - XML_ParserFree(p); - free(x); - close(fd); - return node; /* return the xmlnode x points to */ -} - -/** - * write an xmlnode to a file (without a size limit) - * - * @param file the target file - * @param node the xmlnode that should be written - * @return 1 on success, -1 on failure - */ -int xmlnode2file(char *file, xmlnode node) -{ - return xmlnode2file_limited(file, node, 0); -} - -/** - * write an xmlnode to a file, limited by size - * - * @param file the target file - * @param node the xmlnode that should be written - * @param sizelimit the maximum length of the file to be written - * @return 1 on success, 0 if failed due to size limit, -1 on failure - */ -int xmlnode2file_limited(char *file, xmlnode node, size_t sizelimit) -{ - char *doc, *ftmp; - int fd, i; - size_t doclen; - - if(file == NULL || node == NULL) - return -1; - - ftmp = spools(xmlnode_pool(node),file,".t.m.p",xmlnode_pool(node)); - fd = open(ftmp, O_CREAT | O_WRONLY | O_TRUNC, 0600); - if(fd < 0) - return -1; - - doc = xmlnode2str(node); - doclen = strlen(doc); - - if (sizelimit > 0 && doclen > sizelimit) - { - close(fd); - return 0; - } - - i = write(fd,doc,doclen); - if(i < 0) - return -1; - - close(fd); - - if(rename(ftmp,file) < 0) - { - unlink(ftmp); - return -1; - } - return 1; -} - -/** - * append attributes in the expat format to an existing xmlnode - * - * @param owner where to add the attributes - * @param atts the attributes in expat format (even indexes are the attribute names, odd indexes the values) - */ -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts) -{ - int i = 0; - if (atts == NULL) return; - while (atts[i] != '\0') - { - xmlnode_put_attrib(owner, atts[i], atts[i+1]); - i += 2; - } -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/genhash.c --- a/mcabber/libjabber/genhash.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,501 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ -#include - -/***************************************************************************** - * Internal type definitions - */ - -typedef struct tagHNODE -{ - struct tagHNODE *next; /* next node in list */ - const void *key; /* key pointer */ - void *value; /* value pointer */ -} HNODE; - -#define SLAB_NUM_NODES 64 /* allocate this many nodes per slab */ - -typedef struct tagHSLAB -{ - struct tagHSLAB *next; /* next slab pointer */ - HNODE nodes[SLAB_NUM_NODES]; /* the actual nodes */ -} HSLAB; - -#define HASH_NUM_BUCKETS 509 /* should be a prime number; see Knuth */ - -typedef struct tagHASHTABLE_INTERNAL -{ - unsigned long sig1; /* first signature word */ - KEYHASHFUNC hash; /* hash function */ - KEYCOMPAREFUNC cmp; /* comparison function */ - int count; /* table entry count */ - int bcount; /* bucket count */ - HNODE **buckets; /* the hash buckets */ - unsigned long sig2; /* second signature word */ - -} HASHTABLE_INTERNAL; - -#define HASH_SIG1 0x68736148UL /* "Hash" */ -#define HASH_SIG2 0x6F627245UL /* "Erbo" */ - -#define do_hash(tb,key) ((*((tb)->hash))(key) % ((tb)->bcount)) - -static HNODE *s_free_nodes = NULL; /* free nodes list */ -static HSLAB *s_slabs = NULL; /* node slabs list */ - -/***************************************************************************** - * Internal functions - */ - -static HNODE *allocate_node( - const void *key, /* key pointer for this node */ - void *value) /* value pointer for this node */ -/* - allocate_node allocates a new hash node and fills it. Returns NULL if the - node could not be allocated. -*/ -{ - HNODE *rc; /* return from this function */ - - if (!s_free_nodes) - { /* allocate a new slabful of nodes and chain them to make a new free list */ - register int i; /* loop counter */ - HSLAB *slab = (HSLAB *)malloc(sizeof(HSLAB)); - if (!slab) - return NULL; - memset(slab,0,sizeof(HSLAB)); - slab->next = s_slabs; - for (i=0; i<(SLAB_NUM_NODES-1); i++) - slab->nodes[i].next = &(slab->nodes[i+1]); - s_free_nodes = &(slab->nodes[0]); - s_slabs = slab; - - } /* end if */ - - /* grab a node off the fron of the free list and fill it */ - rc = s_free_nodes; - s_free_nodes = rc->next; - rc->next = NULL; - rc->key = key; - rc->value = value; - return rc; - -} /* end allocate_node */ - -static void free_node( - HNODE *node) /* node to be freed */ -/* - free_node returns a hash node to the list. -*/ -{ - /* zap the node contents to avoid problems later */ - memset(node,0,sizeof(HNODE)); - - /* chain it onto the free list */ - node->next = s_free_nodes; - s_free_nodes = node; - -} /* end free_node */ - -static HNODE *find_node( - HASHTABLE_INTERNAL *tab, /* pointer to hash table */ - const void *key, /* key value to look up */ - int bucket) /* bucket number (-1 to have function compute it) */ -/* - find_node walks a hash bucket to find a node whose key matches the named key value. - Returns the node pointer, or NULL if it's not found. -*/ -{ - register HNODE *p; /* search pointer/return from this function */ - - if (bucket<0) /* compute hash value if we don't know it already */ - bucket = do_hash(tab,key); - - /* search through the bucket contents */ - for (p=tab->buckets[bucket]; p; p=p->next) - if ((*(tab->cmp))(key,p->key)==0) - return p; /* found! */ - - return NULL; /* not found */ - -} /* end find_node */ - -static HASHTABLE_INTERNAL *handle2ptr( - HASHTABLE tbl) /* hash table handle */ -/* - handle2ptr converts a hash table handle into a pointer and checks its signatures - to make sure someone's not trying to pull a whizzer on this module. -*/ -{ - register HASHTABLE_INTERNAL *rc = (HASHTABLE_INTERNAL *)tbl; - if ((rc->sig1==HASH_SIG1) && (rc->sig2==HASH_SIG2)) - return rc; /* signatures match */ - else - return NULL; /* yIkes! */ -} - -/***************************************************************************** - * External functions - */ - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp) -/* - Description: - Creates a new hash table. - - Input: - Parameters: - buckets - Number of buckets to allocate for the hash table; this value - should be a prime number for maximum efficiency. - hash - Key hash code function to use. - cmp - Key comparison function to use. - - Output: - Returns: - NULL - Table could not be allocated. - Other - Handle to the new hashtable. -*/ -{ - HASHTABLE_INTERNAL *tab; /* new table structure */ - char *allocated; - - if (!hash || !cmp) - return NULL; /* bogus! */ - - if (buckets<=0) - buckets = HASH_NUM_BUCKETS; - - /* allocate a hash table structure */ - allocated = malloc(sizeof(HASHTABLE_INTERNAL) + (buckets * sizeof(HNODE *))); - if (!allocated) - return NULL; /* memory error */ - - /* fill the fields of the hash table */ - tab = (HASHTABLE_INTERNAL *)allocated; - allocated += sizeof(HASHTABLE_INTERNAL); - memset(tab,0,sizeof(HASHTABLE_INTERNAL)); - memset(allocated,0,buckets * sizeof(HNODE *)); - tab->sig1 = HASH_SIG1; - tab->hash = hash; - tab->cmp = cmp; - tab->bcount = buckets; - tab->buckets = (HNODE **)allocated; - tab->sig2 = HASH_SIG2; - - return (HASHTABLE)tab; /* Qa'pla! */ - -} /* end ghash_create */ - -void ghash_destroy(HASHTABLE tbl) -/* - Description: - Destroys a hash table. - - Input: - Parameters: - tbl - Table to be destroyed. - - Output: - Returns: - Nothing. -*/ -{ - HASHTABLE_INTERNAL *tab; /* new table structure */ - int i; /* loop counter */ - HNODE *p, *p2; /* temporary pointers */ - - if (!tbl) - return; /* bogus! */ - - /* Convert the handle to a table pointer. */ - tab = handle2ptr(tbl); - if (!tab) - return; - - /* Nuke the nodes it contains. */ - for (i=0; ibcount; i++) - { /* free the contents of each bucket */ - p = tab->buckets[i]; - while (p) - { /* free each node in turn */ - p2 = p->next; - free_node(p); - p = p2; - - } /* end while */ - - } /* end for */ - - free(tab); /* bye bye now! */ - -} /* end ghash_destroy */ - -void *ghash_get(HASHTABLE tbl, const void *key) -/* - Description: - Retrieves a value stored in the hash table. - - Input: - Parameters: - tbl - The hash table to look in. - key - The key value to search on. - - Output: - Returns: - NULL - Value not found. - Other - Value corresponding to the specified key. -*/ -{ - HASHTABLE_INTERNAL *tab; /* internal table pointer */ - HNODE *node; /* hash node */ - void *rc = NULL; /* return from this function */ - - if (!tbl || !key) - return NULL; /* bogus! */ - - /* Convert the handle to a table pointer. */ - tab = handle2ptr(tbl); - if (!tab) - return NULL; /* error */ - - /* Attempt to find the node. */ - node = find_node(tab,key,-1); - if (node) - rc = node->value; /* found it! */ - - return rc; - -} /* end ghash_get */ - -int ghash_put(HASHTABLE tbl, const void *key, void *value) -/* - Description: - Associates a key with a value in this hash table. - - Input: - Parameters: - tbl - Hash table to add. - key - Key to use for the value in the table. - value - Value to add for this key. - - Output: - Returns: - 1 - Success. - 0 - Failure. - - Notes: - If the specified key is already in the hashtable, its value will be replaced. -*/ -{ - HASHTABLE_INTERNAL *tab; /* internal table pointer */ - int bucket; /* bucket value goes into */ - HNODE *node; /* hash node */ - int rc = 1; /* return from this function */ - - if (!tbl || !key || !value) - return 0; /* bogus! */ - - /* Convert the handle to a table pointer. */ - tab = handle2ptr(tbl); - if (!tab) - return 0; /* error */ - - - /* Compute the hash bucket and try to find an existing node. */ - bucket = do_hash(tab,key); - node = find_node(tab,key,bucket); - if (!node) - { /* OK, try to allocate a new node. */ - node = allocate_node(key,value); - if (node) - { /* Chain the new node into the hash table. */ - node->next = tab->buckets[bucket]; - tab->buckets[bucket] = node; - tab->count++; - - } /* end if */ - else /* allocation error */ - rc = 0; - - } /* end if */ - else /* already in table - just reassign value */ - node->value = value; - - return rc; - -} /* end ghash_put */ - -int ghash_remove(HASHTABLE tbl, const void *key) -/* - Description: - Removes an entry from a hash table, given its key. - - Input: - Parameters: - tbl - Hash table to remove from. - key - Key of value to remove. - - Output: - Returns: - 1 - Success. - 0 - Failure; key not present in hash table. -*/ -{ - HASHTABLE_INTERNAL *tab; /* internal table pointer */ - int bucket; /* bucket value goes into */ - HNODE *node; /* hash node */ - register HNODE *p; /* removal pointer */ - int rc = 1; /* return from this function */ - - if (!tbl || !key) - return 0; /* bogus! */ - - /* Convert the handle to a table pointer. */ - tab = handle2ptr(tbl); - if (!tab) - return 0; /* error */ - - - /* Compute the hash bucket and try to find an existing node. */ - bucket = do_hash(tab,key); - node = find_node(tab,key,bucket); - if (node) - { /* look to unchain it from the bucket it's in */ - if (node==tab->buckets[bucket]) - tab->buckets[bucket] = node->next; /* unchain at head */ - else - { /* unchain in middle of list */ - for (p=tab->buckets[bucket]; p->next!=node; p=p->next) ; - p->next = node->next; - - } /* end else */ - - free_node(node); /* bye bye now! */ - tab->count--; - - } /* end if */ - else /* node not found */ - rc = 0; - - return rc; - -} /* end ghash_remove */ - -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data) -/* - Description: - "Walks" through a hash table, calling a callback function for each element - stored in it. - - Input: - Parameters: - tbl - Hash table to walk. - func - Function to be called for each node. It takes three parameters, - a user data pointer, a key value pointer, and a data value pointer. - It returns 0 to stop the enumeration or 1 to keep it going. - user_data - Value to use as the first parameter for the callback - function. - - Output: - Returns: - 0 - Error occurred. - Other - Number of nodes visited up to and including the one for which - the callback function returned 0, if it did; ranges from 1 - to the number of nodes in the hashtable. -*/ -{ - HASHTABLE_INTERNAL *tab; /* internal table pointer */ - int i; /* loop counter */ - int running = 1; /* we're still running */ - int count = 0; /* number of nodes visited before stop node */ - register HNODE *p, *p2; /* loop pointer */ - - if (!tbl || !func) - return -1; /* bogus values! */ - - /* Convert the handle to a table pointer. */ - tab = handle2ptr(tbl); - if (!tab) - return -1; /* error */ - - - for (i=0; running && (ibcount); i++) - { /* visit the contents of each bucket */ - p = tab->buckets[i]; - while (running && p) - { /* visit each node in turn */ - p2 = p->next; - count++; - running = (*func)(user_data,p->key,p->value); - p = p2; - - } /* end while */ - - } /* end for */ - - return count; - -} /* end ghash_walk */ - -int str_hash_code(const char *s) -/* - Description: - Generates a hash code for a string. This function uses the ELF hashing - algorithm as reprinted in Andrew Binstock, "Hashing Rehashed," _Dr. - Dobb's Journal_, April 1996. - - Input: - Parameters: - s - The string to be hashed. - - Output: - Returns: - A hash code for the string. -*/ -{ - /* ELF hash uses unsigned chars and unsigned arithmetic for portability */ - const unsigned char *name = (const unsigned char *)s; - unsigned long h = 0, g; - - if (!name) - return 0; /* anti-NULL guard not in the original */ - - while (*name) - { /* do some fancy bitwanking on the string */ - h = (h << 4) + (unsigned long)(*name++); - if ((g = (h & 0xF0000000UL))!=0) - h ^= (g >> 24); - h &= ~g; - - } /* end while */ - - return (int)h; - -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/hashtable.c --- a/mcabber/libjabber/hashtable.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -csompliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include "xmldef.h" - -#ifdef XML_UNICODE_WCHAR_T -#ifndef XML_UNICODE -#define XML_UNICODE -#endif -#endif - -#include "hashtable.h" - -#define INIT_SIZE 64 - -static -int keyeq(KEY s1, KEY s2) -{ - for (; *s1 == *s2; s1++, s2++) - if (*s1 == 0) - return 1; - return 0; -} - -static -unsigned long hash(KEY s) -{ - unsigned long h = 0; - while (*s) - h = (h << 5) + h + (unsigned char)*s++; - return h; -} - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) -{ - size_t i; - if (table->size == 0) { - if (!createSize) - return 0; - table->v = calloc(INIT_SIZE, sizeof(NAMED *)); - if (!table->v) - return 0; - table->size = INIT_SIZE; - table->usedLim = INIT_SIZE / 2; - i = hash(name) & (table->size - 1); - } - else { - unsigned long h = hash(name); - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) { - if (keyeq(name, table->v[i]->name)) - return table->v[i]; - } - if (!createSize) - return 0; - if (table->used == table->usedLim) { - /* check for overflow */ - size_t newSize = table->size * 2; - NAMED **newV = calloc(newSize, sizeof(NAMED *)); - if (!newV) - return 0; - for (i = 0; i < table->size; i++) - if (table->v[i]) { - size_t j; - for (j = hash(table->v[i]->name) & (newSize - 1); - newV[j]; - j == 0 ? j = newSize - 1 : --j) - ; - newV[j] = table->v[i]; - } - free(table->v); - table->v = newV; - table->size = newSize; - table->usedLim = newSize/2; - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) - ; - } - } - table->v[i] = calloc(1, createSize); - if (!table->v[i]) - return 0; - table->v[i]->name = name; - (table->used)++; - return table->v[i]; -} - -void hashTableDestroy(HASH_TABLE *table) -{ - size_t i; - for (i = 0; i < table->size; i++) { - NAMED *p = table->v[i]; - if (p) - free(p); - } - free(table->v); -} - -void hashTableInit(HASH_TABLE *p) -{ - p->size = 0; - p->usedLim = 0; - p->used = 0; - p->v = 0; -} - -void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) -{ - iter->p = table->v; - iter->end = iter->p + table->size; -} - -NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) -{ - while (iter->p != iter->end) { - NAMED *tem = *(iter->p)++; - if (tem) - return tem; - } - return 0; -} - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/hashtable.h --- a/mcabber/libjabber/hashtable.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -#include - -#ifdef XML_UNICODE - -#ifdef XML_UNICODE_WCHAR_T -typedef const wchar_t *KEY; -#else /* not XML_UNICODE_WCHAR_T */ -typedef const unsigned short *KEY; -#endif /* not XML_UNICODE_WCHAR_T */ - -#else /* not XML_UNICODE */ - -typedef const char *KEY; - -#endif /* not XML_UNICODE */ - -typedef struct { - KEY name; -} NAMED; - -typedef struct { - NAMED **v; - size_t size; - size_t used; - size_t usedLim; -} HASH_TABLE; - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize); -void hashTableInit(HASH_TABLE *); -void hashTableDestroy(HASH_TABLE *); - -typedef struct { - NAMED **p; - NAMED **end; -} HASH_TABLE_ITER; - -void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); -NAMED *hashTableIterNext(HASH_TABLE_ITER *); diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/iasciitab.h --- a/mcabber/libjabber/iasciitab.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/jabber.h --- a/mcabber/libjabber/jabber.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,403 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libxode.h" -#include "../connwrap/connwrap.h" - -#ifndef INCL_JABBER_H -#define INCL_JABBER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* --------------------------------------------------------- */ -/* */ -/* JID structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JID_RESOURCE 1 -#define JID_USER 2 -#define JID_SERVER 4 - -typedef struct jid_struct -{ - pool p; - char* resource; - char* user; - char* server; - char* full; - struct jid_struct *next; /* for lists of jids */ -} *jid; - -jid jid_new(pool p, char *idstr); /* Creates a jabber id from the idstr */ - -void jid_set(jid id, char *str, int item); /* Individually sets jid components */ -char* jid_full(jid id); /* Builds a string type=user/resource@server from the jid data */ -int jid_cmp(jid a, jid b); /* Compares two jid's, returns 0 for perfect match */ -int jid_cmpx(jid a, jid b, int parts); /* Compares just the parts specified as JID_|JID_ */ -jid jid_append(jid a, jid b); /* Appending b to a (list), no dups */ -xmlnode jid_xres(jid id); /* Returns xmlnode representation of the resource?query=string */ -xmlnode jid_nodescan(jid id, xmlnode x); /* Scans the children of the node for a matching jid attribute */ -jid jid_user(jid a); /* returns the same jid but just of the user@host part */ - - -/* --------------------------------------------------------- */ -/* */ -/* JPacket structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JPACKET_UNKNOWN 0x00 -#define JPACKET_MESSAGE 0x01 -#define JPACKET_PRESENCE 0x02 -#define JPACKET_IQ 0x04 -#define JPACKET_S10N 0x08 - -#define JPACKET__UNKNOWN 0 -#define JPACKET__NONE 1 -#define JPACKET__ERROR 2 -#define JPACKET__CHAT 3 -#define JPACKET__GROUPCHAT 4 -#define JPACKET__GET 5 -#define JPACKET__SET 6 -#define JPACKET__RESULT 7 -#define JPACKET__SUBSCRIBE 8 -#define JPACKET__SUBSCRIBED 9 -#define JPACKET__UNSUBSCRIBE 10 -#define JPACKET__UNSUBSCRIBED 11 -#define JPACKET__AVAILABLE 12 -#define JPACKET__UNAVAILABLE 13 -#define JPACKET__PROBE 14 -#define JPACKET__HEADLINE 15 -#define JPACKET__INVISIBLE 16 - -typedef struct jpacket_struct -{ - unsigned char type; /**< stanza type (JPACKET_*) */ - int subtype; /**< subtype of a stanza */ - int flag; /**< used by the session manager to flag messages, that are read from offline storage */ - void* aux1; /**< pointer to data passed around with a jpacket, multiple use inside jsm */ - xmlnode x; /**< xmlnode containing the stanza inside the jpacket */ - jid to; /**< destination of the stanza */ - jid from; /**< source address for the stanza */ - char* iqns; /**< pointer to the namespace inside an IQ stanza */ - xmlnode iq; /**< "content" of an iq stanza, pointer to the element in its own namespace */ - pool p; /**< memory pool used for this stanza */ -} *jpacket, _jpacket; - -jpacket jpacket_new(xmlnode x); /* Creates a jabber packet from the xmlnode */ -jpacket jpacket_reset(jpacket p); /* Resets the jpacket values based on the xmlnode */ -int jpacket_subtype(jpacket p); /* Returns the subtype value (looks at xmlnode for it) */ - - -/* --------------------------------------------------------- */ -/* */ -/* Presence Proxy DB structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct ppdb_struct -{ - jid id; /* entry data */ - int pri; - xmlnode x; - struct ppdb_struct* user; /* linked list for user@server */ - pool p; /* db-level data */ - struct ppdb_struct* next; -} _ppdb, *ppdb; - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x); /* Inserts presence into the proxy */ -xmlnode ppdb_primary(ppdb db, jid id); /* Fetches the matching primary presence for the id */ -void ppdb_free(ppdb db); /* Frees the db and all entries */ -xmlnode ppdb_get(ppdb db, jid id); /* Called successively to return each presence xmlnode */ - /* for the id and children, returns NULL at the end */ - - -/* --------------------------------------------------------- */ -/* */ -/* Simple Jabber Rate limit functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct jlimit_struct -{ - char *key; - int start; - int points; - int maxt, maxp; - pool p; -} *jlimit, _jlimit; - -jlimit jlimit_new(int maxt, int maxp); -void jlimit_free(jlimit r); -int jlimit_check(jlimit r, char *key, int points); - - -/* --------------------------------------------------------- */ -/* */ -/* Error structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct terror_struct -{ - int code; - char msg[64]; -} terror; - -#define TERROR_BAD (terror){400,"Bad Request"} -#define TERROR_AUTH (terror){401,"Unauthorized"} -#define TERROR_PAY (terror){402,"Payment Required"} -#define TERROR_FORBIDDEN (terror){403,"Forbidden"} -#define TERROR_NOTFOUND (terror){404,"Not Found"} -#define TERROR_NOTALLOWED (terror){405,"Not Allowed"} -#define TERROR_NOTACCEPTABLE (terror){406,"Not Acceptable"} -#define TERROR_REGISTER (terror){407,"Registration Required"} -#define TERROR_REQTIMEOUT (terror){408,"Request Timeout"} -#define TERROR_CONFLICT (terror){409,"Conflict"} - -#define TERROR_INTERNAL (terror){500,"Internal Server Error"} -#define TERROR_NOTIMPL (terror){501,"Not Implemented"} -#define TERROR_EXTERNAL (terror){502,"Remote Server Error"} -#define TERROR_UNAVAIL (terror){503,"Service Unavailable"} -#define TERROR_EXTTIMEOUT (terror){504,"Remote Server Timeout"} -#define TERROR_DISCONNECTED (terror){510,"Disconnected"} - -/* we define this to signal that we support xterror */ -#define HAS_XTERROR - -typedef struct xterror_struct -{ - int code; - char msg[256]; - char type[9]; - char condition[64]; -} xterror; - -#define XTERROR_BAD (xterror){400,"Bad Request","modify","bad-request"} -#define XTERROR_CONFLICT (xterror){409,"Conflict","cancel","conflict"} -#define XTERROR_NOTIMPL (xterror){501,"Not Implemented","cancel","feature-not-implemented"} -#define XTERROR_FORBIDDEN (xterror){403,"Forbidden","auth","forbidden"} -#define XTERROR_GONE (xterror){302,"Gone","modify","gone"} -#define XTERROR_INTERNAL (xterror){500,"Internal Server Error","wait","internal-server-error"} -#define XTERROR_NOTFOUND (xterror){404,"Not Found","cancel","item-not-found"} -#define XTERROR_JIDMALFORMED (xterror){400,"Bad Request","modify","jid-malformed"} -#define XTERROR_NOTACCEPTABLE (xterror){406,"Not Acceptable","modify","not-acceptable"} -#define XTERROR_NOTALLOWED (xterror){405,"Not Allowed","cancel","not-allowed"} -#define XTERROR_AUTH (xterror){401,"Unauthorized","auth","not-authorized"} -#define XTERROR_PAY (xterror){402,"Payment Required","auth","payment-required"} -#define XTERROR_RECIPIENTUNAVAIL (xterror){404,"Receipient Is Unavailable","wait","recipient-unavailable"} -#define XTERROR_REDIRECT (xterror){302,"Redirect","modify","redirect"} -#define XTERROR_REGISTER (xterror){407,"Registration Required","auth","registration-required"} -#define XTERROR_REMOTENOTFOUND (xterror){404,"Remote Server Not Found","cancel","remote-server-not-found"} -#define XTERROR_REMOTETIMEOUT (xterror){504,"Remote Server Timeout","wait","remote-server-timeout"} -#define XTERROR_RESCONSTRAINT (xterror){500,"Resource Constraint","wait","resource-constraint"} -#define XTERROR_UNAVAIL (xterror){503,"Service Unavailable","cancel","service-unavailable"} -#define XTERROR_SUBSCRIPTIONREQ (xterror){407,"Subscription Required","auth","subscription-required"} -#define XTERROR_UNDEF_CANCEL (xterror){500,NULL,"cancel","undefined-condition"} -#define XTERROR_UNDEF_CONTINUE (xterror){500,NULL,"continue","undefined-condition"} -#define XTERROR_UNDEF_MODIFY (xterror){500,NULL,"modify","undefined-condition"} -#define XTERROR_UNDEF_AUTH (xterror){500,NULL,"auth","undefined-condition"} -#define XTERROR_UNDEF_WAIT (xterror){500,NULL,"wait","undefined-condition"} -#define XTERROR_UNEXPECTED (xterror){400,"Unexpected Request","wait","unexpected-request"} - -#define XTERROR_REQTIMEOUT (xterror){408,"Request Timeout","wait","remote-server-timeout"} -#define XTERROR_EXTERNAL (xterror){502,"Remote Server Error","wait","service-unavailable"} -#define XTERROR_EXTTIMEOUT (xterror){504,"Remote Server Timeout","wait","remote-server-timeout"} -#define XTERROR_DISCONNECTED (xterror){510,"Disconnected","cancel","service-unavailable"} - -/* --------------------------------------------------------- */ -/* */ -/* Namespace constants */ -/* */ -/* --------------------------------------------------------- */ -#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0) - -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" -#define NS_DIALBACK "jabber:server:dialback" -#define NS_AUTH "jabber:iq:auth" -#define NS_AUTH_CRYPT "jabber:iq:auth:crypt" -#define NS_REGISTER "jabber:iq:register" -#define NS_ROSTER "jabber:iq:roster" -#define NS_OFFLINE "jabber:x:offline" -#define NS_AGENT "jabber:iq:agent" -#define NS_AGENTS "jabber:iq:agents" -#define NS_DELAY "jabber:x:delay" -#define NS_VERSION "jabber:iq:version" -#define NS_TIME "jabber:iq:time" -#define NS_VCARD "vcard-temp" -#define NS_PRIVATE "jabber:iq:private" -#define NS_SEARCH "jabber:iq:search" -#define NS_OOB "jabber:iq:oob" -#define NS_XOOB "jabber:x:oob" -#define NS_ADMIN "jabber:iq:admin" -#define NS_FILTER "jabber:iq:filter" -#define NS_AUTH_0K "jabber:iq:auth:0k" -#define NS_BROWSE "jabber:iq:browse" -#define NS_EVENT "jabber:x:event" -#define NS_CONFERENCE "jabber:iq:conference" -#define NS_SIGNED "jabber:x:signed" -#define NS_ENCRYPTED "jabber:x:encrypted" -#define NS_GATEWAY "jabber:iq:gateway" -#define NS_LAST "jabber:iq:last" -#define NS_ENVELOPE "jabber:x:envelope" -#define NS_EXPIRE "jabber:x:expire" -#define NS_XHTML "http://www.w3.org/1999/xhtml" -#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info" -#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" -#define NS_IQ_AUTH "http://jabber.org/features/iq-auth" -#define NS_REGISTER_FEATURE "http://jabber.org/features/iq-register" - -#define NS_CAPS "http://jabber.org/protocol/caps" -#define NS_CHATSTATES "http://jabber.org/protocol/chatstates" -#define NS_COMMANDS "http://jabber.org/protocol/commands" -#define NS_MUC "http://jabber.org/protocol/muc" - -#define NS_XDBGINSERT "jabber:xdb:ginsert" -#define NS_XDBNSLIST "jabber:xdb:nslist" - -#define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" -#define NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls" -#define NS_XMPP_STREAMS "urn:ietf:params:xml:ns:xmpp-streams" - -#define NS_XMPP_DELAY "urn:xmpp:delay" -#define NS_XMPP_TIME "urn:xmpp:time" -#define NS_PING "urn:xmpp:ping" - -#define NS_JABBERD_STOREDPRESENCE "http://jabberd.org/ns/storedpresence" -#define NS_JABBERD_HISTORY "http://jabberd.org/ns/history" - -/* --------------------------------------------------------- */ -/* */ -/* Message Types */ -/* */ -/* --------------------------------------------------------- */ -#define TMSG_NORMAL "normal" -#define TMSG_ERROR "error" -#define TMSG_CHAT "chat" -#define TMSG_GROUPCHAT "groupchat" -#define TMSG_HEADLINE "headline" - - -/* --------------------------------------------------------- */ -/* */ -/* JUtil functions */ -/* */ -/* --------------------------------------------------------- */ -xmlnode jutil_presnew(int type, char *to, char *status); /* Create a skeleton presence packet */ -xmlnode jutil_iqnew(int type, char *ns); /* Create a skeleton iq packet */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body); - /* Create a skeleton message packet */ -xmlnode jutil_header(char* xmlns, char* server); /* Create a skeleton stream packet */ -int jutil_priority(xmlnode x); /* Determine priority of this packet */ -void jutil_tofrom(xmlnode x); /* Swaps to/from fields on a packet */ -xmlnode jutil_iqresult(xmlnode x); /* Generate a skeleton iq/result, given a iq/query */ -char* jutil_timestamp(void); /* Get stringified timestamp */ -void jutil_error(xmlnode x, terror E); /* Append an node to x */ -void jutil_delay(xmlnode msg, char *reason); /* Append a delay packet to msg */ -char* jutil_regkey(char *key, char *seed); /* pass a seed to generate a key, pass the key again to validate (returns it) */ - - -/* --------------------------------------------------------- */ -/* */ -/* JConn structures & functions */ -/* */ -/* --------------------------------------------------------- */ -#define JCONN_STATE_OFF 0 -#define JCONN_STATE_CONNECTED 1 -#define JCONN_STATE_ON 2 -#define JCONN_STATE_AUTH 3 -#define JCONN_STATE_CONNECTING 4 - -typedef struct jconn_struct -{ - /* Core structure */ - pool p; /* Memory allocation pool */ - int state; /* Connection state flag */ - int cw_state; /* Low level connection state flag */ - int fd; /* Connection file descriptor */ - char *server; /* The server we'll connect too */ - int port; - int ssl; - jid user; /* User info */ - char *pass; /* User passwd */ - - /* Stream stuff */ - int id; /* id counter for jab_getid() function */ - char idbuf[9]; /* temporary storage for jab_getid() */ - char *sid; /* stream id from server, for digest auth */ - XML_Parser parser; /* Parser instance */ - xmlnode current; /* Current node in parsing instance.. */ - - /* Event callback ptrs */ - void (*on_state)(struct jconn_struct *j, int state); - void (*on_packet)(struct jconn_struct *j, jpacket p); - void (*logger)(struct jconn_struct *j, int inout, const char *p); - -} *jconn, jconn_struct; - -typedef void (*jconn_state_h)(jconn j, int state); -typedef void (*jconn_packet_h)(jconn j, jpacket p); -typedef void (*jconn_logger)(jconn j, int inout, const char *p); - -jconn jab_new(char *user, char *pass, char *server, int port, int ssl); -void jab_delete(jconn j); -void jab_state_handler(jconn j, jconn_state_h h); -void jab_packet_handler(jconn j, jconn_packet_h h); -void jab_logger(jconn j, jconn_logger h); -void jab_start(jconn j); -void jab_stop(jconn j); - -int jab_getfd(jconn j); -jid jab_getjid(jconn j); -char *jab_getsid(jconn j); -char *jab_getid(jconn j); - -void jab_send(jconn j, xmlnode x); -void jab_send_raw(jconn j, const char *str); -void jab_recv(jconn j); -void jab_poll(jconn j, int timeout); - -char *jab_auth(jconn j); -int jab_auth_mcabber(jconn j, xmlnode x); -char *jab_reg(jconn j); - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_JABBER_H */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/jconn.c --- a/mcabber/libjabber/jconn.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,601 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include "jabber.h" -#include "connwrap.h" - -#include "../src/logprint.h" /* For logging */ - -/* local macros for launching event handlers */ -#define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); } - -/* prototypes of the local functions */ -static void startElement(void *userdata, const char *name, const char **attribs); -static void endElement(void *userdata, const char *name); -static void charData(void *userdata, const char *s, int slen); - -/* - * jab_new -- initialize a new jabber connection - * - * parameters - * user -- jabber id of the user - * pass -- password of the user - * - * results - * a pointer to the connection structure - * or NULL if allocations failed - */ -jconn jab_new(char *user, char *pass, char *server, int port, int ssl) -{ - pool p; - jconn j; - - if(!user) return(NULL); - - p = pool_new(); - if(!p) return(NULL); - j = pmalloc_x(p, sizeof(jconn_struct), 0); - if(!j) return(NULL); - j->p = p; - - j->user = jid_new(p, user); - j->pass = pstrdup(p, pass); - j->port = port; - j->server = server; - - j->state = JCONN_STATE_OFF; - j->cw_state = 0; - j->id = 1; - j->fd = -1; - j->ssl = ssl; - - return j; -} - -/* - * jab_delete -- free a jabber connection - * - * parameters - * j -- connection - * - */ -void jab_delete(jconn j) -{ - if(!j) return; - - jab_stop(j); - pool_free(j->p); -} - -/* - * jab_state_handler -- set callback handler for state change - * - * parameters - * j -- connection - * h -- name of the handler function - */ -void jab_state_handler(jconn j, jconn_state_h h) -{ - if(!j) return; - - j->on_state = h; -} - -/* - * jab_packet_handler -- set callback handler for incoming packets - * - * parameters - * j -- connection - * h -- name of the handler function - */ -void jab_packet_handler(jconn j, jconn_packet_h h) -{ - if(!j) return; - - j->on_packet = h; -} - -void jab_logger(jconn j, jconn_logger h) -{ - if(!j) return; - - j->logger = h; -} - - -/* - * jab_start -- start connection - * - * parameters - * j -- connection - * - */ -void jab_start(jconn j) -{ - xmlnode x; - char *t,*t2; - - if(!j || (j->state != JCONN_STATE_OFF && j->state != JCONN_STATE_CONNECTING) ) return; - - if (!(j->cw_state & CW_CONNECT_WANT_SOMETHING)) { /* same as state != JCONN_STATE_CONNECTING */ - j->parser = XML_ParserCreate(NULL); - XML_SetUserData(j->parser, (void *)j); - XML_SetElementHandler(j->parser, startElement, endElement); - XML_SetCharacterDataHandler(j->parser, charData); - - if (j->cw_state & CW_CONNECT_BLOCKING) - j->fd = make_netsocket(j->port, j->server, NETSOCKET_CLIENT, j->ssl); - else - j->fd = make_nb_netsocket(j->port, j->server, NETSOCKET_CLIENT, j->ssl, &j->cw_state); - - if(j->fd < 0) { - STATE_EVT(JCONN_STATE_OFF); - return; - } - } - else { /* subsequent calls to cw_nb_connect until it finishes negociation */ - if (cw_nb_connect(j->fd, 0, 0, j->ssl, &j->cw_state)) { - if (cw_get_ssl_error()) - scr_LogPrint(LPRINT_LOGNORM, "jab_start: SSL negotiation failed: %s", cw_get_ssl_error()); - STATE_EVT(JCONN_STATE_OFF); - return; - } - } - if (j->cw_state & CW_CONNECT_WANT_SOMETHING){ /* check if it finished negociation */ - j->state = JCONN_STATE_CONNECTING; - STATE_EVT(JCONN_STATE_CONNECTING); - return; - } - change_socket_to_blocking(j->fd); - - j->state = JCONN_STATE_CONNECTED; - STATE_EVT(JCONN_STATE_CONNECTED) - - /* start stream */ - x = jutil_header(NS_CLIENT, j->user->server); - t = xmlnode2str(x); - /* this is ugly, we can create the string here instead of jutil_header */ - /* what do you think about it? -madcat */ - t2 = strstr(t,"/>"); - *t2++ = '>'; - *t2 = '\0'; - jab_send_raw(j,""); - jab_send_raw(j,t); - xmlnode_free(x); - - j->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON) - -} - -/* - * jab_stop -- stop connection - * - * parameters - * j -- connection - */ -void jab_stop(jconn j) -{ - if (!j) return; - if (j->parser) { - XML_ParserFree(j->parser); - j->parser = NULL; - } - j->state = JCONN_STATE_OFF; - if (j->fd >= 0) { - cw_close(j->fd); - j->fd = -1; - } -} - -/* - * jab_getfd -- get file descriptor of connection socket - * - * parameters - * j -- connection - * - * returns - * fd of the socket or -1 if socket was not connected - */ -int jab_getfd(jconn j) -{ - if(j) - return j->fd; - else - return -1; -} - -/* - * jab_getjid -- get jid structure of user - * - * parameters - * j -- connection - */ -jid jab_getjid(jconn j) -{ - if(j) - return(j->user); - else - return NULL; -} - -/* jab_getsid -- get stream id - * This is the id of server's tag and used for - * digest authorization. - * - * parameters - * j -- connection - */ -char *jab_getsid(jconn j) -{ - if(j) - return(j->sid); - else - return NULL; -} - -/* - * jab_getid -- get a unique id - * - * parameters - * j -- connection - */ -char *jab_getid(jconn j) -{ - snprintf(j->idbuf, 8, "%d", j->id++); - return &j->idbuf[0]; -} - -/* - * jab_send -- send xml data - * - * parameters - * j -- connection - * x -- xmlnode structure - */ -void jab_send(jconn j, xmlnode x) -{ - if (j && j->state != JCONN_STATE_OFF) - { - char *buf = xmlnode2str(x); - if (buf) { - cw_write(j->fd, buf, strlen(buf), j->ssl); - if (j->logger) - (j->logger)(j, 0, buf); - } - -#ifdef JDEBUG - printf ("out: %s\n", buf); -#endif - } -} - -/* - * jab_send_raw -- send a string - * - * parameters - * j -- connection - * str -- xml string - */ -void jab_send_raw(jconn j, const char *str) -{ - if (j && j->state != JCONN_STATE_OFF) { - cw_write(j->fd, str, strlen(str), j->ssl); - - if (j->logger) - (j->logger)(j, 0, str); - } - -#ifdef JDEBUG - printf ("out: %s\n", str); -#endif -} - -/* - * jab_recv -- read and parse incoming data - * - * parameters - * j -- connection - */ -void jab_recv(jconn j) -{ - static char buf[32768]; - int len; - - if(!j || j->state == JCONN_STATE_OFF) - return; - - len = cw_read(j->fd, buf, sizeof(buf)-1, j->ssl); - if(len>0) - { - buf[len] = '\0'; - - if (j->logger) - (j->logger)(j, 1, buf); - -#ifdef JDEBUG - printf (" in: %s\n", buf); -#endif - XML_Parse(j->parser, buf, len, 0); - } - else if(len<=0) - { - STATE_EVT(JCONN_STATE_OFF); - jab_stop(j); - } -} - -/* - * jab_poll -- check socket for incoming data - * - * parameters - * j -- connection - * timeout -- poll timeout - */ -void jab_poll(jconn j, int timeout) -{ - fd_set fds; - struct timeval tv; - int r; - - if (!j || j->state == JCONN_STATE_OFF) - return; - - if (j->fd == -1) { - STATE_EVT(JCONN_STATE_OFF); - return; - } - - FD_ZERO(&fds); - FD_SET(j->fd, &fds); - - if(timeout <= 0) { - r = select(j->fd + 1, &fds, NULL, NULL, NULL); - - } else { - tv.tv_sec = 0; - tv.tv_usec = timeout; - r = select(j->fd + 1, &fds, NULL, NULL, &tv); - - } - - if(r > 0) { - jab_recv(j); - - } else if(r) { - /* Don't disconnect for interrupted system call */ - if(errno == EINTR) return; - - scr_LogPrint(LPRINT_LOGNORM, "jab_poll: select returned errno=%d", - errno); - STATE_EVT(JCONN_STATE_OFF); - jab_stop(j); - - } -} - -/* - * jab_auth -- authorize user - * - * parameters - * j -- connection - * - * returns - * id of the iq packet - */ -char *jab_auth(jconn j) -{ - xmlnode x,y,z; - char *hash, *user, *id; - - if(!j) return(NULL); - - x = jutil_iqnew(JPACKET__SET, NS_AUTH); - id = jab_getid(j); - xmlnode_put_attrib(x, "id", id); - y = xmlnode_get_tag(x,"query"); - - user = j->user->user; - - if (user) - { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, j->user->resource, -1); - - if (j->sid) - { - z = xmlnode_insert_tag(y, "digest"); - hash = pmalloc(x->p, strlen(j->sid)+strlen(j->pass)+1); - strcpy(hash, j->sid); - strcat(hash, j->pass); - hash = shahash(hash); - xmlnode_insert_cdata(z, hash, 40); - } - else - { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, j->pass, -1); - } - - jab_send(j, x); - xmlnode_free(x); - return id; -} - -/* - * jab_auth_mcabber -- authorize user - * - * parameters - * j -- connection - * x -- xmlnode iq packet - * - * returns - * non-zero in case of failure - */ -int jab_auth_mcabber(jconn j, xmlnode x) -{ - xmlnode y,z; - char *hash, *user; - - if(!j) return -1; - - y = xmlnode_get_tag(x, "query"); - - user = j->user->user; - - if (user) - { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, j->user->resource, -1); - - if (j->sid) - { - z = xmlnode_insert_tag(y, "digest"); - hash = pmalloc(x->p, strlen(j->sid)+strlen(j->pass)+1); - strcpy(hash, j->sid); - strcat(hash, j->pass); - hash = shahash(hash); - xmlnode_insert_cdata(z, hash, 40); - } - else - { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, j->pass, -1); - } - return 0; -} - -/* - * jab_reg -- register user - * - * parameters - * j -- connection - * - * returns - * id of the iq packet - */ -char *jab_reg(jconn j) -{ - xmlnode x,y,z; - char *user, *id; - - if (!j) return(NULL); - - x = jutil_iqnew(JPACKET__SET, NS_REGISTER); - id = jab_getid(j); - xmlnode_put_attrib(x, "id", id); - y = xmlnode_get_tag(x,"query"); - - user = j->user->user; - - if (user) - { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, j->user->resource, -1); - - if (j->pass) - { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, j->pass, -1); - } - - jab_send(j, x); - xmlnode_free(x); - j->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON) - return id; -} - - -/* local functions */ - -static void startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - jconn j = (jconn)userdata; - - if(j->current) - { - /* Append the node to the current one */ - x = xmlnode_insert_tag(j->current, name); - xmlnode_put_expat_attribs(x, attribs); - - j->current = x; - } - else - { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - if(strcmp(name, "stream:stream") == 0) { - /* special case: name == stream:stream */ - /* id attrib of stream is stored for digest auth */ - j->sid = xmlnode_get_attrib(x, "id"); - /* STATE_EVT(JCONN_STATE_AUTH) */ - } else { - j->current = x; - } - } -} - -static void endElement(void *userdata, const char *name) -{ - jconn j = (jconn)userdata; - xmlnode x; - jpacket p; - - if(j->current == NULL) { - /* we got */ - STATE_EVT(JCONN_STATE_OFF) - return; - } - - x = xmlnode_get_parent(j->current); - - if(x == NULL) - { - /* it is time to fire the event */ - p = jpacket_new(j->current); - - if(j->on_packet) - (j->on_packet)(j, p); - xmlnode_free(j->current); - } - - j->current = x; -} - -static void charData(void *userdata, const char *s, int slen) -{ - jconn j = (jconn)userdata; - - if (j->current) - xmlnode_insert_cdata(j->current, s, slen); -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/jid.c --- a/mcabber/libjabber/jid.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,746 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -/** - * @file jid.c - * @brief representation and normalization of JabberIDs - */ - -#include "jabber.h" - -#ifdef LIBIDN - -# include - - -/** - * @brief datastructure to build the stringprep caches - */ -typedef struct _jid_prep_entry_st { - char *preped; /**< the result of the preparation, NULL if unchanged */ - time_t last_used; /**< when this result has last been successfully used */ - unsigned int used_count; /**< how often this result has been successfully used */ - int size; /**< the min buffer size needed to hold the result (strlen+1) */ -} *_jid_prep_entry_t; - -/** - * @brief string preparation cache - */ -typedef struct _jid_prep_cache_st { - xht hashtable; /**< the hash table containing the preped strings */ - pth_mutex_t mutex; /**< mutex controling the access to the hashtable */ - const Stringprep_profile *profile; - /**< the stringprep profile used for this cache */ -} *_jid_prep_cache_t; - -/** - * stringprep cache containging already preped nodes - * - * we are using global caches here for two reasons: - * - I do not see why different instances would want - * to have different caches as we are always doing - * the same - * - For per instance caches I would have to modify the - * interface of the jid_*() functions which would break - * compatibility with transports - */ -_jid_prep_cache_t _jid_prep_cache_node = NULL; - -/** - * stringprep cache containing already preped domains - */ -_jid_prep_cache_t _jid_prep_cache_domain = NULL; - -/** - * stringprep cache containing already preped resources - */ -_jid_prep_cache_t _jid_prep_cache_resource = NULL; - -/** - * walker for cleaning up stringprep caches - * - * @param h the hash we are walking through - * @param key the key of this item - * @param val the value of this item - * @param arg delete entries older as this unix timestamp - */ -void _jid_clean_walker(xht h, const char *key, void *val, void *arg) { - time_t *keep_newer_as = (time_t*)arg; - _jid_prep_entry_t entry = (_jid_prep_entry_t)val; - - if (entry == NULL) - return; - - if (entry->last_used <= *keep_newer_as) { - xhash_zap(h, key); - if (entry->preped != NULL) - free(entry->preped); - free(entry); - - /* sorry, I have to cast the const away */ - /* any idea how I could delete the key else? */ - if (key != NULL) - free((void*)key); - } -} - -/** - * walk through a single stringprep cache and check which entries have expired - */ -void _jid_clean_single_cache(_jid_prep_cache_t cache, time_t keep_newer_as) { - /* acquire the lock on the cache */ - pth_mutex_acquire(&(cache->mutex), FALSE, NULL); - - /* walk over all entries */ - xhash_walk(cache->hashtable, _jid_clean_walker, (void*)&keep_newer_as); - - /* we're done, release the lock on the cache */ - pth_mutex_release(&(cache->mutex)); -} - -/** - * walk through the stringprep caches and check which entries have expired - */ -void jid_clean_cache() { - /* XXX make this configurable? */ - time_t keep_newer_as = time(NULL) - 900; - - /* cleanup the nodeprep cache */ - _jid_clean_single_cache(_jid_prep_cache_node, keep_newer_as); - - /* cleanup the domain preparation cache */ - _jid_clean_single_cache(_jid_prep_cache_domain, keep_newer_as); - - /* cleanup the resourceprep cache */ - _jid_clean_single_cache(_jid_prep_cache_resource, keep_newer_as); -} - -/** - * caching wrapper around a stringprep function - * - * @param in_out_buffer buffer containing what has to be stringpreped and that gets the result - * @param max_len size of the buffer - * @param cache the used cache, defining also the used stringprep profile - * @return the return code of the stringprep call - */ -int _jid_cached_stringprep(char *in_out_buffer, int max_len, _jid_prep_cache_t cache) { - _jid_prep_entry_t preped; - int result = STRINGPREP_OK; - - /* check that the cache already exists - * we can not do anything as we don't know which profile has to be used */ - if (cache == NULL) { - return STRINGPREP_UNKNOWN_PROFILE; - } - - /* is there something that has to be stringpreped? */ - if (in_out_buffer == NULL) { - return STRINGPREP_OK; - } - - /* acquire the lock on the cache */ - pth_mutex_acquire(&(cache->mutex), FALSE, NULL); - - /* check if the requested preparation has already been done */ - preped = (_jid_prep_entry_t)xhash_get(cache->hashtable, in_out_buffer); - if (preped != NULL) { - /* we already prepared this argument */ - if (preped->size <= max_len) { - /* we can use the result */ - - /* update the statistic */ - preped->used_count++; - preped->last_used = time(NULL); - - /* do we need to copy the result? */ - if (preped->preped != NULL) { - /* copy the result */ - strcpy(in_out_buffer, preped->preped); - } - - result = STRINGPREP_OK; - } else { - /* we need a bigger buffer */ - result = STRINGPREP_TOO_SMALL_BUFFER; - } - - /* we're done, release the lock on the cache */ - pth_mutex_release(&(cache->mutex)); - } else { - char *original; - - /* stringprep needs time, release the lock on the cache for the meantime */ - pth_mutex_release(&(cache->mutex)); - - /* we have to keep the key */ - original = strdup(in_out_buffer); - - /* try to prepare the string */ - result = stringprep(in_out_buffer, max_len, STRINGPREP_NO_UNASSIGNED, cache->profile); - - /* did we manage to prepare the string? */ - if (result == STRINGPREP_OK && original != NULL) { - /* generate an entry for the cache */ - preped = (_jid_prep_entry_t)malloc(sizeof(struct _jid_prep_entry_st)); - if (preped != NULL) { - /* has there been modified something? */ - if (j_strcmp(in_out_buffer, original) == 0) { - /* no, we don't need to store a copy of the original string */ - preped->preped = NULL; - } else { - /* yes, store the stringpreped string */ - preped->preped = strdup(in_out_buffer); - } - preped->last_used = time(NULL); - preped->used_count = 1; - preped->size = strlen(in_out_buffer)+1; - - /* acquire the lock on the cache again */ - pth_mutex_acquire(&(cache->mutex), FALSE, NULL); - - /* store the entry in the cache */ - xhash_put(cache->hashtable, original, preped); - - /* we're done, release the lock on the cache */ - pth_mutex_release(&(cache->mutex)); - } else { - /* we don't need the copy of the key, if there is no memory to store it */ - free(original); - } - } else { - /* we don't need the copy of the original value */ - if (original != NULL) - free(original); - } - } - - return result; -} - -/** - * free a single stringprep cache - * - * @param cache the cache to free - */ -void _jid_stop_single_cache(_jid_prep_cache_t *cache) { - if (*cache == NULL) - return; - - _jid_clean_single_cache(*cache, time(NULL)); - - pth_mutex_acquire(&((*cache)->mutex), FALSE, NULL); - xhash_free((*cache)->hashtable); - - free(*cache); - - *cache = NULL; -} - -/** - * init a single stringprep cache - * - * @param cache the cache to init - * @param prime the prime used to init the hashtable - * @param profile profile used to prepare the strings - */ -void _jid_init_single_cache(_jid_prep_cache_t *cache, int prime, const Stringprep_profile *profile) { - /* do not init a cache twice */ - if (*cache == NULL) { - *cache = (_jid_prep_cache_t)malloc(sizeof(struct _jid_prep_cache_st)); - pth_mutex_init(&((*cache)->mutex)); - (*cache)->hashtable = xhash_new(prime); - (*cache)->profile = profile; - } -} - -/** - * free the stringprep caches - */ -void jid_stop_caching() { - _jid_stop_single_cache(&_jid_prep_cache_node); - _jid_stop_single_cache(&_jid_prep_cache_domain); - _jid_stop_single_cache(&_jid_prep_cache_resource); -} - -/** - * init the stringprep caches - * (do not call this twice at the same time, we do not have the mutexes yet) - */ -void jid_init_cache() { - /* init the nodeprep cache */ - _jid_init_single_cache(&_jid_prep_cache_node, 2003, stringprep_xmpp_nodeprep); - - /* init the nameprep cache (domains) */ - _jid_init_single_cache(&_jid_prep_cache_domain, 2003, stringprep_nameprep); - - /* init the resourceprep cache */ - _jid_init_single_cache(&_jid_prep_cache_resource, 2003, stringprep_xmpp_resourceprep); -} - -/** - * nameprep the domain identifier in a JID and check if it is valid - * - * @param jid data structure holding the JID - * @return 0 if JID is valid, non zero otherwise - */ -int _jid_safe_domain(jid id) { - int result=0; - - /* there must be a domain identifier */ - if (j_strlen(id->server) == 0) - return 1; - - /* nameprep the domain identifier */ - result = _jid_cached_stringprep(id->server, strlen(id->server)+1, _jid_prep_cache_domain); - if (result == STRINGPREP_TOO_SMALL_BUFFER) { - /* nameprep wants to expand the string, e.g. conversion from ß to ss */ - size_t biggerbuffersize = 1024; - char *biggerbuffer = pmalloc(id->p, biggerbuffersize); - if (biggerbuffer == NULL) - return 1; - strcpy(biggerbuffer, id->server); - result = _jid_cached_stringprep(biggerbuffer, biggerbuffersize, _jid_prep_cache_domain); - id->server = biggerbuffer; - } - if (result != STRINGPREP_OK) - return 1; - - /* the namepreped domain must not be longer than 1023 bytes */ - if (j_strlen(id->server) > 1023) - return 1; - - /* if nothing failed, the domain is valid */ - return 0; -} - -/** - * nodeprep the node identifier in a JID and check if it is valid - * - * @param jid data structure holding the JID - * @return 0 if JID is valid, non zero otherwise - */ -int _jid_safe_node(jid id) { - int result=0; - - /* it is valid to have no node identifier in the JID */ - if (id->user == NULL) - return 0; - - /* nodeprep */ - result = _jid_cached_stringprep(id->user, strlen(id->user)+1, _jid_prep_cache_node); - if (result == STRINGPREP_TOO_SMALL_BUFFER) { - /* nodeprep wants to expand the string, e.g. conversion from ß to ss */ - size_t biggerbuffersize = 1024; - char *biggerbuffer = pmalloc(id->p, biggerbuffersize); - if (biggerbuffer == NULL) - return 1; - strcpy(biggerbuffer, id->user); - result = _jid_cached_stringprep(biggerbuffer, biggerbuffersize, _jid_prep_cache_node); - id->user = biggerbuffer; - } - if (result != STRINGPREP_OK) - return 1; - - /* the nodepreped node must not be longer than 1023 bytes */ - if (j_strlen(id->user) > 1023) - return 1; - - /* if nothing failed, the node is valid */ - return 0; -} - -/** - * resourceprep the resource identifier in a JID and check if it is valid - * - * @param jid data structure holding the JID - * @return 0 if JID is valid, non zero otherwise - */ -int _jid_safe_resource(jid id) { - int result=0; - - /* it is valid to have no resource identifier in the JID */ - if (id->resource == NULL) - return 0; - - /* resource prep the resource identifier */ - result = _jid_cached_stringprep(id->resource, strlen(id->resource)+1, _jid_prep_cache_resource); - if (result == STRINGPREP_TOO_SMALL_BUFFER) { - /* resourceprep wants to expand the string, e.g. conversion from ß to ss */ - size_t biggerbuffersize = 1024; - char *biggerbuffer = pmalloc(id->p, biggerbuffersize); - if (biggerbuffer == NULL) - return 1; - strcpy(biggerbuffer, id->resource); - result = _jid_cached_stringprep(id->resource, strlen(id->resource)+1, _jid_prep_cache_resource); - id->resource = biggerbuffer; - } - if (result != STRINGPREP_OK) - return 1; - - /* the resourcepreped node must not be longer than 1023 bytes */ - if (j_strlen(id->resource) > 1023) - return 1; - - /* if nothing failed, the resource is valid */ - return 0; - -} - -#else /* no LIBIDN */ - -/** - * check if the domain identifier in a JID is valid - * - * @param jid data structure holding the JID - * @return 0 if domain is valid, non zero otherwise - */ -int _jid_safe_domain(jid id) { - char *str; - - /* there must be a domain identifier */ - if (j_strlen(id->server) == 0) - return 1; - - /* and it must not be longer than 1023 bytes */ - if (strlen(id->server) > 1023) - return 1; - - /* lowercase the hostname, make sure it's valid characters */ - for(str = id->server; *str != '\0'; str++) - { - *str = tolower(*str); - if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return 1; - } - - /* otherwise it's okay as far as we can tell without LIBIDN */ - return 0; -} - -/** - * check if the node identifier in a JID is valid - * - * @param jid data structure holding the JID - * @return 0 if node is valid, non zero otherwise - */ -int _jid_safe_node(jid id) { - char *str; - - /* node identifiers may not be longer than 1023 bytes */ - if (j_strlen(id->user) > 1023) - return 1; - - /* check for low and invalid ascii characters in the username */ - if(id->user != NULL) - for(str = id->user; *str != '\0'; str++) - if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return 1; - - /* otherwise it's okay as far as we can tell without LIBIDN */ - return 0; -} - -/** - * check if the resource identifier in a JID is valid - * - * @param jid data structure holding the JID - * @return 0 if resource is valid, non zero otherwise - */ -int _jid_safe_resource(jid id) { - /* resources may not be longer than 1023 bytes */ - if (j_strlen(id->resource) > 1023) - return 1; - - /* otherwise it's okay as far as we can tell without LIBIDN */ - return 0; -} - -#endif - -/** - * nodeprep/nameprep/resourceprep the JID and check if it is valid - * - * @param jid data structure holding the JID - * @return NULL if the JID is invalid, pointer to the jid otherwise - */ -jid jid_safe(jid id) -{ - if (_jid_safe_domain(id)) - return NULL; - if (_jid_safe_node(id)) - return NULL; - if (_jid_safe_resource(id)) - return NULL; - - return id; -} - -jid jid_new(pool p, char *idstr) -{ - char *server, *resource, *type, *str; - jid id; - - if(p == NULL || idstr == NULL || strlen(idstr) == 0) - return NULL; - - /* user@server/resource */ - - str = pstrdup(p, idstr); - - id = pmalloco(p,sizeof(struct jid_struct)); - id->p = p; - - resource = strstr(str,"/"); - if(resource != NULL) - { - *resource = '\0'; - ++resource; - if(strlen(resource) > 0) - id->resource = resource; - }else{ - resource = str + strlen(str); /* point to end */ - } - - type = strstr(str,":"); - if(type != NULL && type < resource) - { - *type = '\0'; - ++type; - str = type; /* ignore the type: prefix */ - } - - server = strstr(str,"@"); - if(server == NULL || server > resource) - { /* if there's no @, it's just the server address */ - id->server = str; - }else{ - *server = '\0'; - ++server; - id->server = server; - if(strlen(str) > 0) - id->user = str; - } - - return jid_safe(id); -} - -void jid_set(jid id, char *str, int item) -{ - char *old; - - if(id == NULL) - return; - - /* invalidate the cached copy */ - id->full = NULL; - - switch(item) - { - case JID_RESOURCE: - old = id->resource; - if(str != NULL && strlen(str) != 0) - id->resource = pstrdup(id->p, str); - else - id->resource = NULL; - if(_jid_safe_resource(id)) - id->resource = old; /* revert if invalid */ - break; - case JID_USER: - old = id->user; - if(str != NULL && strlen(str) != 0) - id->user = pstrdup(id->p, str); - else - id->user = NULL; - if(_jid_safe_node(id)) - id->user = old; /* revert if invalid */ - break; - case JID_SERVER: - old = id->server; - id->server = pstrdup(id->p, str); - if(_jid_safe_domain(id)) - id->server = old; /* revert if invalid */ - break; - } - -} - -char *jid_full(jid id) -{ - spool s; - - if(id == NULL) - return NULL; - - /* use cached copy */ - if(id->full != NULL) - return id->full; - - s = spool_new(id->p); - - if(id->user != NULL) - spooler(s, id->user,"@",s); - - spool_add(s, id->server); - - if(id->resource != NULL) - spooler(s, "/",id->resource,s); - - id->full = spool_print(s); - return id->full; -} - -/* parses a /resource?name=value&foo=bar into an xmlnode representing */ -xmlnode jid_xres(jid id) -{ - char *cur, *qmark, *amp, *eq; - xmlnode x; - - if(id == NULL || id->resource == NULL) return NULL; - - cur = pstrdup(id->p, id->resource); - qmark = strstr(cur, "?"); - if(qmark == NULL) return NULL; - *qmark = '\0'; - qmark++; - - x = _xmlnode_new(id->p, cur, NTYPE_TAG); - - cur = qmark; - while(cur != '\0') - { - eq = strstr(cur, "="); - if(eq == NULL) break; - *eq = '\0'; - eq++; - - amp = strstr(eq, "&"); - if(amp != NULL) - { - *amp = '\0'; - amp++; - } - - xmlnode_put_attrib(x,cur,eq); - - if(amp != NULL) - cur = amp; - else - break; - } - - return x; -} - -/* local utils */ -int _jid_nullstrcmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return strcmp(a,b); -} -int _jid_nullstrcasecmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return strcasecmp(a,b); -} - -int jid_cmp(jid a, jid b) -{ - if(a == NULL || b == NULL) - return -1; - - if(_jid_nullstrcmp(a->resource, b->resource) != 0) return -1; - if(_jid_nullstrcasecmp(a->user, b->user) != 0) return -1; - if(_jid_nullstrcmp(a->server, b->server) != 0) return -1; - - return 0; -} - -/* suggested by Anders Qvist */ -int jid_cmpx(jid a, jid b, int parts) -{ - if(a == NULL || b == NULL) - return -1; - - if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1; - if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1; - if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1; - - return 0; -} - -/* makes a copy of b in a's pool, requires a valid a first! */ -jid jid_append(jid a, jid b) -{ - jid next; - - if(a == NULL) - return NULL; - - if(b == NULL) - return a; - - next = a; - while(next != NULL) - { - /* check for dups */ - if(jid_cmp(next,b) == 0) - break; - if(next->next == NULL) - next->next = jid_new(a->p,jid_full(b)); - next = next->next; - } - return a; -} - -xmlnode jid_nodescan(jid id, xmlnode x) -{ - xmlnode cur; - pool p; - jid tmp; - - if(id == NULL || xmlnode_get_firstchild(x) == NULL) return NULL; - - p = pool_new(); - for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) - { - if(xmlnode_get_type(cur) != NTYPE_TAG) continue; - - tmp = jid_new(p,xmlnode_get_attrib(cur,"jid")); - if(tmp == NULL) continue; - - if(jid_cmp(tmp,id) == 0) break; - } - pool_free(p); - - return cur; -} - -jid jid_user(jid a) -{ - jid ret; - - if(a == NULL || a->resource == NULL) return a; - - ret = pmalloco(a->p,sizeof(struct jid_struct)); - ret->p = a->p; - ret->user = a->user; - ret->server = a->server; - - return ret; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/jpacket.c --- a/mcabber/libjabber/jpacket.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file jpacket.c - * @brief a jpacket is a wrapper around an xmlnode that contains an XMPP stanza - * - * A jpacket adds some variables to an xmlnode that contains a stanza, so that - * jabberd is able to cache information on the stanza type (message, presence, iq) - * that is contained in this jpacket and to further classify the presence stanzas. - * It also adds some pointers to important data inside the xmlnode, that has - * to be accessed often (e.g. sender and receiver of a stanza). - */ - -#include "jabber.h" - -/** - * create a new jpacket by wrapping an xmlnode - * - * @param x the xmlnode that should be wrapped - * @return the newly created jpacket (NULL on failure) - */ -jpacket jpacket_new(xmlnode x) -{ - jpacket p; - - if(x == NULL) - return NULL; - - p = pmalloc(xmlnode_pool(x),sizeof(_jpacket)); - p->x = x; - - return jpacket_reset(p); -} - -/** - * recalculate the information the jpacket holds about the stanza - * - * @param p the packet that should get its information recalculated - * @return the jpacket (as given as the p parameter) - */ -jpacket jpacket_reset(jpacket p) -{ - char *val; - xmlnode x; - - x = p->x; - memset(p,0,sizeof(_jpacket)); - p->x = x; - p->p = xmlnode_pool(x); - - if(strncmp(xmlnode_get_name(x),"message",7) == 0) { - p->type = JPACKET_MESSAGE; - } else if(strncmp(xmlnode_get_name(x),"presence",8) == 0) { - p->type = JPACKET_PRESENCE; - val = xmlnode_get_attrib(x, "type"); - if(val == NULL) - p->subtype = JPACKET__AVAILABLE; - else if(strcmp(val,"unavailable") == 0) - p->subtype = JPACKET__UNAVAILABLE; - else if(strcmp(val,"probe") == 0) - p->subtype = JPACKET__PROBE; - else if(strcmp(val,"error") == 0) - p->subtype = JPACKET__ERROR; - else if(strcmp(val,"invisible") == 0) - p->subtype = JPACKET__INVISIBLE; - else if(*val == 's' || *val == 'u') - p->type = JPACKET_S10N; - else if(strcmp(val,"available") == 0) { - /* someone is using type='available' which is frowned upon */ - /* XXX better reject this presence? */ - xmlnode_hide_attrib(x,"type"); - p->subtype = JPACKET__AVAILABLE; - } else - p->type = JPACKET_UNKNOWN; - } else if(strncmp(xmlnode_get_name(x),"iq",2) == 0) { - p->type = JPACKET_IQ; - p->iq = xmlnode_get_tag(x,"?xmlns"); - p->iqns = xmlnode_get_attrib(p->iq,"xmlns"); - } - - /* set up the jids if any, flag packet as unknown if they are unparseable */ - val = xmlnode_get_attrib(x,"to"); - if(val != NULL) - if((p->to = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - val = xmlnode_get_attrib(x,"from"); - if(val != NULL) - if((p->from = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - - return p; -} - -/** - * get the subtype of a jpacket - * - * @param p the jpacket for which the caller wants to know the subtype - * @return the subtype of the jpacket (one of the JPACKET__* constants) - */ -int jpacket_subtype(jpacket p) -{ - char *type; - int ret = p->subtype; - - if(ret != JPACKET__UNKNOWN) - return ret; - - ret = JPACKET__NONE; /* default, when no type attrib is specified */ - type = xmlnode_get_attrib(p->x, "type"); - if(j_strcmp(type,"error") == 0) - ret = JPACKET__ERROR; - else - switch(p->type) - { - case JPACKET_MESSAGE: - if(j_strcmp(type,"chat") == 0) - ret = JPACKET__CHAT; - else if(j_strcmp(type,"groupchat") == 0) - ret = JPACKET__GROUPCHAT; - else if(j_strcmp(type,"headline") == 0) - ret = JPACKET__HEADLINE; - break; - case JPACKET_S10N: - if(j_strcmp(type,"subscribe") == 0) - ret = JPACKET__SUBSCRIBE; - else if(j_strcmp(type,"subscribed") == 0) - ret = JPACKET__SUBSCRIBED; - else if(j_strcmp(type,"unsubscribe") == 0) - ret = JPACKET__UNSUBSCRIBE; - else if(j_strcmp(type,"unsubscribed") == 0) - ret = JPACKET__UNSUBSCRIBED; - break; - case JPACKET_IQ: - if(j_strcmp(type,"get") == 0) - ret = JPACKET__GET; - else if(j_strcmp(type,"set") == 0) - ret = JPACKET__SET; - else if(j_strcmp(type,"result") == 0) - ret = JPACKET__RESULT; - break; - } - - p->subtype = ret; - return ret; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/jutil.c --- a/mcabber/libjabber/jutil.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file jutil.c - * @brief various utilities mainly for handling xmlnodes containing stanzas - */ - -#include "jabber.h" - -/** - * utility for making presence stanzas - * - * @param type the type of the presence (one of the JPACKET__* contants) - * @param to to whom the presence should be sent, NULL for a broadcast presence - * @param status optional status (CDATA for the element, NULL for now element) - * @return the xmlnode containing the created presence stanza - */ -xmlnode jutil_presnew(int type, char *to, char *status) -{ - xmlnode pres; - - pres = xmlnode_new_tag("presence"); - switch(type) - { - case JPACKET__SUBSCRIBE: - xmlnode_put_attrib(pres,"type","subscribe"); - break; - case JPACKET__UNSUBSCRIBE: - xmlnode_put_attrib(pres,"type","unsubscribe"); - break; - case JPACKET__SUBSCRIBED: - xmlnode_put_attrib(pres,"type","subscribed"); - break; - case JPACKET__UNSUBSCRIBED: - xmlnode_put_attrib(pres,"type","unsubscribed"); - break; - case JPACKET__PROBE: - xmlnode_put_attrib(pres,"type","probe"); - break; - case JPACKET__UNAVAILABLE: - xmlnode_put_attrib(pres,"type","unavailable"); - break; - case JPACKET__INVISIBLE: - xmlnode_put_attrib(pres,"type","invisible"); - break; - } - if(to != NULL) - xmlnode_put_attrib(pres,"to",to); - if(status != NULL) - xmlnode_insert_cdata(xmlnode_insert_tag(pres,"status"),status,strlen(status)); - - return pres; -} - -/** - * utility for making IQ stanzas, that contain a element in a different namespace - * - * @note In traditional Jabber protocols the element inside an iq element has the name "query". - * This util is not able to create IQ stanzas that contain a query which a element that does - * not have the name "query" - * - * @param type the type of the iq stanza (one of JPACKET__GET, JPACKET__SET, JPACKET__RESULT, JPACKET__ERROR) - * @param ns the namespace of the element - * @return the created xmlnode - */ -xmlnode jutil_iqnew(int type, char *ns) -{ - xmlnode iq; - - iq = xmlnode_new_tag("iq"); - switch(type) - { - case JPACKET__GET: - xmlnode_put_attrib(iq,"type","get"); - break; - case JPACKET__SET: - xmlnode_put_attrib(iq,"type","set"); - break; - case JPACKET__RESULT: - xmlnode_put_attrib(iq,"type","result"); - break; - case JPACKET__ERROR: - xmlnode_put_attrib(iq,"type","error"); - break; - } - xmlnode_put_attrib(xmlnode_insert_tag(iq,"query"),"xmlns",ns); - - return iq; -} - -/** - * utility for making message stanzas - * - * @param type the type of the message (as a string!) - * @param to the recipient of the message - * @param subj the subject of the message (NULL for no subject element) - * @param body the body of the message - * @return the xmlnode containing the new message stanza - */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body) -{ - xmlnode msg; - - msg = xmlnode_new_tag("message"); - - if (type != NULL) { - xmlnode_put_attrib (msg, "type", type); - } - - if (to != NULL) { - xmlnode_put_attrib (msg, "to", to); - } - - if (subj != NULL) { - xmlnode_insert_cdata(xmlnode_insert_tag(msg, "subject"), subj, strlen(subj)); - } - - if (body != NULL) { - xmlnode_insert_cdata(xmlnode_insert_tag(msg, "body"), body, strlen(body)); - } - - return msg; -} - -/** - * utility for making stream packets (containing the stream header element) - * - * @param xmlns the default namespace of the stream (e.g. jabber:client or jabber:server) - * @param server the domain of the server - * @return the xmlnode containing the root element of the stream - */ -xmlnode jutil_header(char* xmlns, char* server) -{ - xmlnode result; - if ((xmlns == NULL)||(server == NULL)) - return NULL; - result = xmlnode_new_tag("stream:stream"); - xmlnode_put_attrib(result, "xmlns:stream", "http://etherx.jabber.org/streams"); - xmlnode_put_attrib(result, "xmlns", xmlns); - xmlnode_put_attrib(result, "to", server); - - return result; -} - -/** - * returns the priority on an available presence packet - * - * @param xmlnode the xmlnode containing the presence packet - * @return the presence priority, -129 for unavailable presences and errors - */ -int jutil_priority(xmlnode x) -{ - char *str; - int p; - - if(x == NULL) - return -129; - - if(xmlnode_get_attrib(x,"type") != NULL) - return -129; - - x = xmlnode_get_tag(x,"priority"); - if(x == NULL) - return 0; - - str = xmlnode_get_data((x)); - if(str == NULL) - return 0; - - p = atoi(str); - /* xmpp-im section 2.2.2.3 */ - return p<-128 ? -128 : p>127 ? 127 : p; -} - -/** - * reverse sender and destination of a packet - * - * @param x the xmlnode where sender and receiver should be exchanged - */ -void jutil_tofrom(xmlnode x) -{ - char *to, *from; - - to = xmlnode_get_attrib(x,"to"); - from = xmlnode_get_attrib(x,"from"); - xmlnode_put_attrib(x,"from",to); - xmlnode_put_attrib(x,"to",from); -} - -/** - * change and xmlnode to be the result xmlnode for the original iq query - * - * @param x the xmlnode that should become the result for itself - * @return the result xmlnode (same as given as parameter x) - */ -xmlnode jutil_iqresult(xmlnode x) -{ - xmlnode cur; - - jutil_tofrom(x); - - xmlnode_put_attrib(x,"type","result"); - - /* hide all children of the iq, they go back empty */ - for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) - xmlnode_hide(cur); - - return x; -} - -/** - * get the present time as a textual timestamp in the format YYYYMMDDTHH:MM:SS - * - * @note this function is not thread safe - * - * @return pointer to a static (!) buffer containing the timestamp (or NULL on failure) - */ -char *jutil_timestamp(void) -{ - time_t t; - struct tm *new_time; - static char timestamp[18]; - int ret; - - t = time(NULL); - - if(t == (time_t)-1) - return NULL; - new_time = gmtime(&t); - - ret = snprintf(timestamp, 18, "%d%02d%02dT%02d:%02d:%02d", 1900+new_time->tm_year, - new_time->tm_mon+1, new_time->tm_mday, new_time->tm_hour, - new_time->tm_min, new_time->tm_sec); - - if(ret == -1) - return NULL; - - return timestamp; -} - -/** - * map a terror structure to a xterror structure - * - * terror structures have been used in jabberd14 up to version 1.4.3 but - * are not able to hold XMPP compliant stanza errors. The xterror - * structure has been introduced to be XMPP compliant. This function - * is to ease writting wrappers that accept terror structures and call - * the real functions that require now xterror structures - * - * @param old the terror struct that should be converted - * @param mapped pointer to the xterror struct that should be filled with the converted error - */ -void jutil_error_map(terror old, xterror *mapped) -{ - mapped->code = old.code; - if (old.msg == NULL) - mapped->msg[0] = 0; - else - strncpy(mapped->msg, old.msg, sizeof(mapped->msg)); - - switch (old.code) - { - case 302: - strcpy(mapped->type, "modify"); - strcpy(mapped->condition, "redirect"); - break; - case 400: - strcpy(mapped->type, "modify"); - strcpy(mapped->condition, "bad-request"); - break; - case 401: - strcpy(mapped->type, "auth"); - strcpy(mapped->condition, "not-authorized"); - break; - case 402: - strcpy(mapped->type, "auth"); - strcpy(mapped->condition, "payment-required"); - break; - case 403: - strcpy(mapped->type, "auth"); - strcpy(mapped->condition, "forbidden"); - break; - case 404: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "item-not-found"); - break; - case 405: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "not-allowed"); - break; - case 406: - strcpy(mapped->type, "modify"); - strcpy(mapped->condition, "not-acceptable"); - break; - case 407: - strcpy(mapped->type, "auth"); - strcpy(mapped->condition, "registration-requited"); - break; - case 408: - strcpy(mapped->type, "wait"); - strcpy(mapped->condition, "remote-server-timeout"); - break; - case 409: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "conflict"); - break; - case 500: - strcpy(mapped->type, "wait"); - strcpy(mapped->condition, "internal-server-error"); - break; - case 501: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "feature-not-implemented"); - break; - case 502: - strcpy(mapped->type, "wait"); - strcpy(mapped->condition, "service-unavailable"); - break; - case 503: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "service-unavailable"); - break; - case 504: - strcpy(mapped->type, "wait"); - strcpy(mapped->condition, "remote-server-timeout"); - break; - case 510: - strcpy(mapped->type, "cancel"); - strcpy(mapped->condition, "service-unavailable"); - break; - default: - strcpy(mapped->type, "wait"); - strcpy(mapped->condition, "undefined-condition"); - } -} - -/** - * update an xmlnode to be the error stanza for itself - * - * @param x the xmlnode that should become an stanza error message - * @param E the structure that holds the error information - */ -void jutil_error_xmpp(xmlnode x, xterror E) -{ - xmlnode err; - char code[4]; - - xmlnode_put_attrib(x, "type", "error"); - err = xmlnode_insert_tag(x, "error"); - - snprintf(code, sizeof(code), "%d", E.code); - xmlnode_put_attrib(err, "code", code); - if (E.type != NULL) - xmlnode_put_attrib(err, "type", E.type); - if (E.condition != NULL) - xmlnode_put_attrib(xmlnode_insert_tag(err, E.condition), "xmlns", NS_XMPP_STANZAS); - if (E.msg != NULL) - { - xmlnode text; - text = xmlnode_insert_tag(err, "text"); - xmlnode_put_attrib(text, "xmlns", NS_XMPP_STANZAS); - xmlnode_insert_cdata(text, E.msg, strlen(E.msg)); - } - - jutil_tofrom(x); -} - -/** - * add a delayed delivery (JEP-0091) element to a message using the - * present timestamp. - * If a reason is given, this reason will be added as CDATA to the - * inserted element - * - * @param msg the message where the element should be added - * @param reason plain text information why the delayed delivery information has been added - */ -void jutil_delay(xmlnode msg, char *reason) -{ - xmlnode delay; - - delay = xmlnode_insert_tag(msg,"x"); - xmlnode_put_attrib(delay,"xmlns",NS_DELAY); - xmlnode_put_attrib(delay,"from",xmlnode_get_attrib(msg,"to")); - xmlnode_put_attrib(delay,"stamp",jutil_timestamp()); - if(reason != NULL) - xmlnode_insert_cdata(delay,reason,strlen(reason)); -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/latin1tab.h --- a/mcabber/libjabber/latin1tab.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, -/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/libxode.h --- a/mcabber/libjabber/libxode.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,468 +0,0 @@ -/* - * jabberd - Jabber Open Source Server - * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, - * Ryan Eatmon, Robert Norris - * - * 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, MA02111-1307USA - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xmlparse.h" - -/* -** Arrange to use either varargs or stdargs -*/ - -#define MAXSHORTSTR 203 /* max short string length */ -#define QUAD_T unsigned long long - -#ifdef __STDC__ - -#include - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_END va_end(ap) - -#else /* __STDC__ */ - -# include - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) -# define VA_END va_end(ap) - -#endif /* __STDC__ */ - - -#ifndef INCL_LIBXODE_H -#define INCL_LIBXODE_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_SNPRINTF -extern int ap_snprintf(char *, size_t, const char *, ...); -#define snprintf ap_snprintf -#endif - -#ifndef HAVE_VSNPRINTF -extern int ap_vsnprintf(char *, size_t, const char *, va_list ap); -#define vsnprintf ap_vsnprintf -#endif - -#define ZONE zonestr(__FILE__,__LINE__) -char *zonestr(char *file, int line); - -/* --------------------------------------------------------- */ -/* */ -/* Pool-based memory management routines */ -/* */ -/* --------------------------------------------------------- */ - -#undef POOL_DEBUG -/* - flip these, this should be a prime number for top # of pools debugging -#define POOL_DEBUG 40009 -*/ - -/* pheap - singular allocation of memory */ -struct pheap -{ - void *block; - int size, used; -}; - -/* pool_cleaner - callback type which is associated - with a pool entry; invoked when the pool entry is - free'd */ -typedef void (*pool_cleaner)(void *arg); - -/* pfree - a linked list node which stores an - allocation chunk, plus a callback */ -struct pfree -{ - pool_cleaner f; - void *arg; - struct pheap *heap; - struct pfree *next; -}; - -/* pool - base node for a pool. Maintains a linked list - of pool entries (pfree) */ -typedef struct pool_struct -{ - int size; - struct pfree *cleanup; - struct pheap *heap; -#ifdef POOL_DEBUG - char name[8], zone[32]; - int lsize; -} _pool, *pool; -#define pool_new() _pool_new(__FILE__,__LINE__) -#define pool_heap(i) _pool_new_heap(i,__FILE__,__LINE__) -#else -} _pool, *pool; -#define pool_heap(i) _pool_new_heap(i, NULL, 0) -#define pool_new() _pool_new(NULL, 0) -#endif - -pool _pool_new(char *zone, int line); /* new pool :) */ -pool _pool_new_heap(int size, char *zone, int line); /* creates a new memory pool with an initial heap size */ -void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */ -void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */ -void *pmalloco(pool p, int size); /* YAPW for zeroing the block */ -char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */ -void pool_stat(int full); /* print to stderr the changed pools and reset */ -char *pstrdupx(pool p, const char *src); /* temp stub */ -void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */ -void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */ -int pool_size(pool p); /* returns total bytes allocated in this pool */ - - - - -/* --------------------------------------------------------- */ -/* */ -/* Socket helper stuff */ -/* */ -/* --------------------------------------------------------- */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define NETSOCKET_SERVER 0 -#define NETSOCKET_CLIENT 1 -#define NETSOCKET_UDP 2 - -#ifndef WIN32 -int make_netsocket(u_short port, char *host, int type, int ssl); -int make_nb_netsocket(u_short port, char *host, int type, int ssl, int * state); -void change_socket_to_blocking(int socket); -struct in_addr *make_addr(char *host); -int set_fd_close_on_exec(int fd, int flag); -#endif - - -/* --------------------------------------------------------- */ -/* */ -/* String management routines */ -/* */ -/* --------------------------------------------------------- */ -char *j_strdup(const char *str); /* provides NULL safe strdup wrapper */ -char *j_strcat(char *dest, char *txt); /* strcpy() clone */ -int j_strcmp(const char *a, const char *b); /* provides NULL safe strcmp wrapper */ -int j_strcasecmp(const char *a, const char *b); /* provides NULL safe strcasecmp wrapper */ -int j_strncmp(const char *a, const char *b, int i); /* provides NULL safe strncmp wrapper */ -int j_strncasecmp(const char *a, const char *b, int i); /* provides NULL safe strncasecmp wrapper */ -int j_strlen(const char *a); /* provides NULL safe strlen wrapper */ -int j_atoi(const char *a, int def); /* checks for NULL and uses default instead, convienence */ -void str_b64decode(char *str); /* what it says */ - - -/* --------------------------------------------------------- */ -/* */ -/* SHA calculations */ -/* */ -/* --------------------------------------------------------- */ -#if (SIZEOF_INT == 4) -typedef unsigned int uint32; -#elif (SIZEOF_SHORT == 4) -typedef unsigned short uint32; -#else -typedef unsigned int uint32; -#endif /* HAVEUINT32 */ - -int sha_hash(int *data, int *hash); -int sha_init(int *hash); -char *shahash(char *str); /* NOT THREAD SAFE */ -void shahash_r(const char* str, char hashbuf[40]); /* USE ME */ - -int strprintsha(char *dest, int *hashval); - - -/* --------------------------------------------------------- */ -/* */ -/* Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef int (*KEYHASHFUNC)(const void *key); -typedef int (*KEYCOMPAREFUNC)(const void *key1, const void *key2); -typedef int (*TABLEWALKFUNC)(void *user_data, const void *key, void *data); - -typedef void *HASHTABLE; - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp); -void ghash_destroy(HASHTABLE tbl); -void *ghash_get(HASHTABLE tbl, const void *key); -int ghash_put(HASHTABLE tbl, const void *key, void *value); -int ghash_remove(HASHTABLE tbl, const void *key); -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data); -int str_hash_code(const char *s); - - -/* --------------------------------------------------------- */ -/* */ -/* XML escaping utils */ -/* */ -/* --------------------------------------------------------- */ -char *strescape(pool p, char *buf); /* Escape <>&'" chars */ -char *strunescape(pool p, char *buf); - - -/* --------------------------------------------------------- */ -/* */ -/* String pools (spool) functions */ -/* */ -/* --------------------------------------------------------- */ -struct spool_node -{ - char *c; - struct spool_node *next; -}; - -typedef struct spool_struct -{ - pool p; - int len; - struct spool_node *last; - struct spool_node *first; -} *spool; - -spool spool_new(pool p); /* create a string pool */ -void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */ -char *spool_print(spool s); /* return a big string */ -void spool_add(spool s, char *str); /* add a single string to the pool */ -char *spools(pool p, ...); /* wrap all the spooler stuff in one function, the happy fun ball! */ - - -/* --------------------------------------------------------- */ -/* */ -/* xmlnodes - Document Object Model */ -/* */ -/* --------------------------------------------------------- */ -#define NTYPE_TAG 0 -#define NTYPE_ATTRIB 1 -#define NTYPE_CDATA 2 - -#define NTYPE_LAST 2 -#define NTYPE_UNDEF -1 - -/* -------------------------------------------------------------------------- - Node structure. Do not use directly! Always use accessor macros - and methods! - -------------------------------------------------------------------------- */ -typedef struct xmlnode_t -{ - char* name; - unsigned short type; - char* data; - int data_sz; - int complete; - pool p; - struct xmlnode_t* parent; - struct xmlnode_t* firstchild; - struct xmlnode_t* lastchild; - struct xmlnode_t* prev; - struct xmlnode_t* next; - struct xmlnode_t* firstattrib; - struct xmlnode_t* lastattrib; -} _xmlnode, *xmlnode; - -/* Node creation routines */ -xmlnode xmlnode_wrap(xmlnode x,const char* wrapper); -xmlnode xmlnode_new_tag(const char* name); -xmlnode xmlnode_new_tag_pool(pool p, const char* name); -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name); -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size); -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node); -void xmlnode_insert_node(xmlnode parent, xmlnode node); -xmlnode xmlnode_str(char *str, int len); -xmlnode xmlnode_file(char *file); -xmlnode xmlnode_dup(xmlnode x); /* duplicate x */ -xmlnode xmlnode_dup_pool(pool p, xmlnode x); - -/* Node Memory Pool */ -pool xmlnode_pool(xmlnode node); -xmlnode _xmlnode_new(pool p, const char *name, unsigned int type); - -/* Node editing */ -void xmlnode_hide(xmlnode child); -void xmlnode_hide_attrib(xmlnode parent, const char *name); - -/* Node deletion routine, also frees the node pool! */ -void xmlnode_free(xmlnode node); - -/* Locates a child tag by name and returns it */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name); -char* xmlnode_get_tag_data(xmlnode parent, const char* name); - -/* Attribute accessors */ -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value); -char* xmlnode_get_attrib(xmlnode owner, const char* name); -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts); - -/* Bastard am I, but these are fun for internal use ;-) */ -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value); -void* xmlnode_get_vattrib(xmlnode owner, const char* name); - -/* Node traversal routines */ -xmlnode xmlnode_get_firstattrib(xmlnode parent); -xmlnode xmlnode_get_firstchild(xmlnode parent); -xmlnode xmlnode_get_lastchild(xmlnode parent); -xmlnode xmlnode_get_nextsibling(xmlnode sibling); -xmlnode xmlnode_get_prevsibling(xmlnode sibling); -xmlnode xmlnode_get_parent(xmlnode node); - -/* Node information routines */ -char* xmlnode_get_name(xmlnode node); -char* xmlnode_get_data(xmlnode node); -int xmlnode_get_datasz(xmlnode node); -int xmlnode_get_type(xmlnode node); - -int xmlnode_has_children(xmlnode node); -int xmlnode_has_attribs(xmlnode node); - -/* Node-to-string translation */ -char* xmlnode2str(xmlnode node); - -/* Node-to-terminated-string translation - -- useful for interfacing w/ scripting langs */ -char* xmlnode2tstr(xmlnode node); - -int xmlnode_cmp(xmlnode a, xmlnode b); /* compares a and b for equality */ - -int xmlnode2file(char *file, xmlnode node); /* writes node to file */ -int xmlnode2file_limited(char *file, xmlnode node, size_t sizelimit); - -/* Expat callbacks */ -void expat_startElement(void* userdata, const char* name, const char** atts); -void expat_endElement(void* userdata, const char* name); -void expat_charData(void* userdata, const char* s, int len); - -/*********************** - * XSTREAM Section - ***********************/ - -#define XSTREAM_MAXNODE 1000000 -#define XSTREAM_MAXDEPTH 100 - -#define XSTREAM_ROOT 0 /* root element */ -#define XSTREAM_NODE 1 /* normal node */ -#define XSTREAM_CLOSE 2 /* closed */ -#define XSTREAM_ERR 4 /* parser error */ - -typedef void (*xstream_onNode)(int type, xmlnode x, void *arg); /* xstream event handler */ - -typedef struct xstream_struct -{ - XML_Parser parser; - xmlnode node; - char *cdata; - int cdata_len; - pool p; - xstream_onNode f; - void *arg; - int status; - int depth; -} *xstream, _xstream; - -xstream xstream_new(pool p, xstream_onNode f, void *arg); /* create a new xstream */ -int xstream_eat(xstream xs, char *buff, int len); /* parse new data for this xstream, returns last XSTREAM_* status */ - -/* convience functions */ -xmlnode xstream_header(char *nspace, char *to, char *from); -char *xstream_header_char(xmlnode x); - -/* SHA.H */ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Header File - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - * Paul Kocher - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -typedef struct { - uint32_t H[5]; - uint32_t W[80]; - int lenW; - uint32_t sizeHi,sizeLo; -} SHA_CTX; - - -void shaInit(SHA_CTX *ctx); -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); - - -/* END SHA.H */ - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_LIBXODE_H */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/log.c --- a/mcabber/libjabber/log.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include "jabber.h" -#include "log.h" - -#ifdef DEBUG - -void jdebug(char *zone, const char *msgfmt, ...) -{ - va_list ap; - static char loghdr[LOGSIZE_HDR]; - static char logmsg[LOGSIZE_TAIL]; - static int size; - - /* XXX: We may want to check the sizes eventually */ - size = snprintf(loghdr, LOGSIZE_HDR, "debug/%s %s\n", zone, msgfmt); - - va_start(ap, msgfmt); - size = vsnprintf(logmsg, LOGSIZE_TAIL, loghdr, ap); - - fprintf(stderr,"%s",logmsg); - - return; -} - - -#endif /* DEBUG */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/log.h --- a/mcabber/libjabber/log.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#ifndef INCL_LOG_H -#define INCL_LOG_H - -#define LOGSIZE_HDR 1024 -#define LOGSIZE_TAIL 2048 - - -#ifdef DEBUG - void jdebug(char *zone, const char *msgfmt, ...); -#else - #define jdebug if(0) warn -#endif - - - -#endif /* INCL_LOG_H */ - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/nametab.h --- a/mcabber/libjabber/nametab.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -static const unsigned namingBitmap[] = { -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, -0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, -0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, -0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, -0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, -0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, -0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, -0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, -0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, -0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, -0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, -0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, -0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, -0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, -0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, -0x40000000, 0xF580C900, 0x00000007, 0x02010800, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, -0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, -0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, -0x00000000, 0x00004C40, 0x00000000, 0x00000000, -0x00000007, 0x00000000, 0x00000000, 0x00000000, -0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, -0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, -0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, -0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, -0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, -0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, -0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, -0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, -0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, -0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, -0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, -0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, -0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, -0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, -0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, -0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, -0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, -0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, -}; -static const unsigned char nmstrtPages[] = { -0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, -0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const unsigned char namePages[] = { -0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, -0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/pool.c --- a/mcabber/libjabber/pool.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,474 +0,0 @@ -/* - * pool.c - * This code comes from jabberd - Jabber Open Source Server - * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, - * Ryan Eatmon, Robert Norris - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - * - * 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, MA02111-1307USA - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file pool.c - * @brief Handling of memory pools - * - * Jabberd handles its memory allocations in pools. You create a pool, can - * allocate memory from it and all allocations will be freed if you free - * the pool. Therefore you don't have to care that each malloc is freed, - * you only have to take care that the pool is freed. - * - * The normal call-flow for pools is: - * - * pool p = pool_new(); - * struct mystruct *allocation1 = pmalloc(sizeof(struct mystruct)); - * struct myotherstruct *allocation2 = pmalloc(sizeof(struct myotherstruct)); - * ... - * pool_free(p); - */ - -#include "libxode.h" - -#define MAX_MALLOC_TRIES 10 /**< how many seconds we try to allocate memory */ - -#ifdef POOL_DEBUG -int pool__total = 0; /**< how many memory blocks are allocated */ -int pool__ltotal = 0; -xht pool__disturbed = NULL; - -inline void *_retried__malloc(size_t size); - -/** - * create a new memory allocation and increment the pool__total counter - * - * only used if POOL_DEBUG is defined, else it is an alias for malloc - * - * @param size size of the memory to allocate - * @return pointer to the allocated memory - */ -void *_pool__malloc(size_t size) -{ - pool__total++; - return malloc(size); -} - -/** - * free memory and decrement the pool__total counter - * - * only used if POOL_DEBUG is defined, else it is an alias for free - * - * @param block pointer to the memory allocation that should be freed - */ -void _pool__free(void *block) -{ - pool__total--; - free(block); -} -#else -#define _pool__malloc malloc /**< _pool__malloc updates pool__total counter if POOL_DEBUG is defined */ -#define _pool__free free /**< _pool__free updates pool__total counter if POOL_DEBUG is defined */ -#endif - -/** - * try to allocate memory - * - * If allocation fails, it will be retries for MAX_MALLOC_TRIES seconds. - * If it still fails, we exit the process - * - * @param size how many bytes of memory we allocate - * @return pointer to the allocated memory - */ -void *_retried__malloc(size_t size) { - void *allocated_memory; - int malloc_tries = 0; - - while ((allocated_memory=_pool__malloc(size)) == NULL) { - if (malloc_tries++ > MAX_MALLOC_TRIES) { - exit(999); - } - - sleep(1); //pth_sleep(1); - } - - return allocated_memory; -} - -/** - * make an empty pool - * - * Use the macro pool_new() instead of a direct call to this function. The - * macro will create the parameters for you. - * - * @param zone the file in which the pool_new macro is called - * @param line the line in the file in which the pool_new macro is called - * @return the new allocated memory pool - */ -pool _pool_new(char *zone, int line) -{ - // int malloc_tries = 0; -#ifdef POOL_DEBUG - int old__pool__total; -#endif - - pool p = _retried__malloc(sizeof(_pool)); - - p->cleanup = NULL; - p->heap = NULL; - p->size = 0; - -#ifdef POOL_DEBUG - p->lsize = -1; - p->zone[0] = '\0'; - strcat(p->zone,zone); - snprintf(p->zone, sizeof(p->zone), "%s:%i", zone, line); - snprintf(p->name, sizeof(p->name), "%X", p); - - if(pool__disturbed == NULL) - { - pool__disturbed = (xht)1; /* reentrancy flag! */ - pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp); - } - if(pool__disturbed != (xht)1) - ghash_put(pool__disturbed,p->name,p); -#endif - - return p; -} - -/** - * free a memory heap (struct pheap) - * - * @param arg which heep should be freed - */ -void _pool_heap_free(void *arg) -{ - struct pheap *h = (struct pheap *)arg; - - _pool__free(h->block); - _pool__free(h); -} - -/** - * append a pool_cleaner function (callback) to a pool - * - * mem should always be freed last - * - * All appended pool_cleaner functions will be called if a pool is freed. - * This might be used to clean logically subpools. - * - * @param p to which pool the pool_cleaner should be added - * @param pf structure containing the reference to the pool_cleaner and links for the list - */ -void _pool_cleanup_append(pool p, struct pfree *pf) -{ - struct pfree *cur; - - if(p->cleanup == NULL) - { - p->cleanup = pf; - return; - } - - /* fast forward to end of list */ - for(cur = p->cleanup; cur->next != NULL; cur = cur->next); - - cur->next = pf; -} - -/** - * create a cleanup tracker - * - * this function is used to create a pfree structure that can be passed to _pool_cleanup_append() - * - * @param p the pool to which the pool_cleaner should be added - * @param f the function that should be called if the pool is freed - * @param arg the parameter that should be passed to the pool_cleaner function - * @return pointer to the new pfree structure - */ -struct pfree *_pool_free(pool p, pool_cleaner f, void *arg) -{ - struct pfree *ret; - - /* make the storage for the tracker */ - ret = _retried__malloc(sizeof(struct pfree)); - ret->f = f; - ret->arg = arg; - ret->next = NULL; - - return ret; -} - -/** - * create a heap and make sure it get's cleaned up - * - * pheaps are used by memory pools internally to handle the memory allocations - * - * @note the macro pool_heap calls _pool_new_heap and NOT _pool_heap - * - * @param p for which pool the heap should be created - * @param size how big the pool should be - * @return pointer to the new pheap - */ -struct pheap *_pool_heap(pool p, int size) -{ - struct pheap *ret; - struct pfree *clean; - - /* make the return heap */ - ret = _retried__malloc(sizeof(struct pheap)); - ret->block = _retried__malloc(size); - ret->size = size; - p->size += size; - ret->used = 0; - - /* append to the cleanup list */ - clean = _pool_free(p, _pool_heap_free, (void *)ret); - clean->heap = ret; /* for future use in finding used mem for pstrdup */ - _pool_cleanup_append(p, clean); - - return ret; -} - -/** - * create a new memory pool and set the initial heap size - * - * @note you should not call this function but use the macro pool_heap instead which fills zone and line automatically - * - * @param size the initial size of the memory pool - * @param zone the file where this function is called (for debugging) - * @param line the line in the file where this function is called - * @return the new memory pool - */ -pool _pool_new_heap(int size, char *zone, int line) -{ - pool p; - p = _pool_new(zone, line); - p->heap = _pool_heap(p,size); - return p; -} - -/** - * allocate memory from a memory pool - * - * @param p the pool to use - * @param size how much memory to allocate - * @return pointer to the allocated memory - */ -void *pmalloc(pool p, int size) -{ - void *block; - - if(p == NULL) - { - fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n"); - abort(); - } - - /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */ - if(p->heap == NULL || size > (p->heap->size / 2)) - { - block = _retried__malloc(size); - p->size += size; - _pool_cleanup_append(p, _pool_free(p, _pool__free, block)); - return block; - } - - /* we have to preserve boundaries, long story :) */ - if(size >= 4) - while(p->heap->used&7) p->heap->used++; - - /* if we don't fit in the old heap, replace it */ - if(size > (p->heap->size - p->heap->used)) - p->heap = _pool_heap(p, p->heap->size); - - /* the current heap has room */ - block = (char *)p->heap->block + p->heap->used; - p->heap->used += size; - return block; -} - -/** - * allocate memory and initialize the memory with the given char c - * - * @deprecated jabberd does use pmalloco instead, this function will be removed - * - * @param p which pool to use - * @param size the size of the allocation - * @param c the initialization character - * @return pointer to the allocated memory - */ -void *pmalloc_x(pool p, int size, char c) -{ - void* result = pmalloc(p, size); - if (result != NULL) - memset(result, c, size); - return result; -} - -/** - * allocate memory and initialize the memory with zero bytes - * - * easy safety utility (for creating blank mem for structs, etc) - * - * @param p which pool to use - * @param size the size of the allocation - * @return pointer to the allocated memory - */ -void *pmalloco(pool p, int size) -{ - void *block = pmalloc(p, size); - memset(block, 0, size); - return block; -} - -/** - * duplicate a string and allocate memory for it - * - * @todo efficient: move this to const char* and then loop through the existing heaps to see if src is within a block in this pool - * - * @param p the pool to use - * @param src the string that should be duplicated - * @return the duplicated string - */ -char *pstrdup(pool p, const char *src) -{ - char *ret; - - if(src == NULL) - return NULL; - - ret = pmalloc(p,strlen(src) + 1); - strcpy(ret,src); - - return ret; -} - -/** - * when pstrdup() is moved to "const char*", this one would actually return a new block - */ -char *pstrdupx(pool p, const char *src) -{ - return pstrdup(p, src); -} - -/** - * get the size of a memory pool - * - * @param p the pool - * @return the size - */ -int pool_size(pool p) -{ - if(p == NULL) return 0; - - return p->size; -} - -/** - * free a pool (and all memory that is allocated in it) - * - * @param p which pool to free - */ -void pool_free(pool p) -{ - struct pfree *cur, *stub; - - if(p == NULL) return; - - cur = p->cleanup; - while(cur != NULL) - { - (*cur->f)(cur->arg); - stub = cur->next; - _pool__free(cur); - cur = stub; - } - -#ifdef POOL_DEBUG - ghash_remove(pool__disturbed,p->name); -#endif - - _pool__free(p); - -} - -/** - * public cleanup utils, insert in a way that they are run FIFO, before mem frees - */ -void pool_cleanup(pool p, pool_cleaner f, void *arg) -{ - struct pfree *clean; - - clean = _pool_free(p, f, arg); - clean->next = p->cleanup; - p->cleanup = clean; -} - -#ifdef POOL_DEBUG -void debug_log(char *zone, const char *msgfmt, ...); -void _pool_stat(xht h, const char *key, void *data, void *arg) -{ - pool p = (pool)data; - - if(p->lsize == -1) - debug_log("pool_debug","%s: %s is a new pool",p->zone, p->name); - else if(p->size > p->lsize) - debug_log("pool_debug","%s: %s grew %d",p->zone, p->name, p->size - p->lsize); - else if((int)arg) - debug_log("pool_debug","%s: %s exists %d",p->zone,p->name, p->size); - p->lsize = p->size; -} - -/** - * print memory pool statistics (for debugging purposes) - * - * @param full make a full report? (0 = no, 1 = yes) - */ -void pool_stat(int full) -{ - if (pool__disturbed == NULL || pool__disturbed == (xht)1) - return; - - ghash_walk(pool__disturbed,_pool_stat,(void *)full); - if(pool__total != pool__ltotal) - debug_log("pool_debug","%d\ttotal missed mallocs",pool__total); - pool__ltotal = pool__total; - - return; -} -#else -/** - * dummy implementation: print memory pool statistics (for debugging purposes, real implementation if POOL_DEBUG is defined) - * - * @param full make a full report? (0 = no, 1 = yes) - */ -void pool_stat(int full) -{ - return; -} -#endif diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/pproxy.c --- a/mcabber/libjabber/pproxy.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * - */ - -/** - * @file pproxy.c - * @brief presence proxy database - DEPRECATED - * - * @deprecated these functions are not used by jabberd itself (but aim-t uses them), they will be removed from jabberd - * - * The presence proxy database is used to store presences for different resources of a JID. - * - * these aren't the most efficient things in the world, a hash optimized for tiny spaces would be far better - */ - -#include "jabber.h" - -/* these aren't the most efficient things in the world, a hash optimized for tiny spaces would be far better */ - -ppdb _ppdb_new(pool p, jid id) -{ - ppdb ret; - ret = pmalloc(p,sizeof(_ppdb)); - ret->p = p; - ret->pri = -1; - ret->next = NULL; - ret->user = NULL; - ret->x = NULL; - ret->id = jid_new(p,jid_full(id)); - - return ret; -} - -ppdb _ppdb_get(ppdb db, jid id) -{ - ppdb cur; - - if(db == NULL || id == NULL) return NULL; - - for(cur = db->next; cur != NULL; cur = cur->next) - if(jid_cmp(cur->id,id) == 0) return cur; - - return NULL; -} - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x) -{ - ppdb cur, curu; - pool p; - - if(id == NULL || id->server == NULL || x == NULL) - return db; - - /* new ppdb list dummy holder */ - if(db == NULL) - { - p = pool_heap(1024); - db = _ppdb_new(p,NULL); - } - - cur = _ppdb_get(db,id); - - /* just update it */ - if(cur != NULL) - { - xmlnode_free(cur->x); - cur->x = xmlnode_dup(x); - cur->pri = jutil_priority(x); - return db; - } - - /* make an entry for it */ - cur = _ppdb_new(db->p,id); - cur->x = xmlnode_dup(x); - cur->pri = jutil_priority(x); - cur->next = db->next; - db->next = cur; - - /* if this is a user's resource presence, get the the user entry */ - if(id->user != NULL && (curu = _ppdb_get(db,jid_user(id))) != cur) - { - /* no user entry, make one */ - if(curu == NULL) - { - curu = _ppdb_new(db->p,jid_user(id)); - curu->next = db->next; - db->next = curu; - } - - /* insert this resource into the user list */ - cur->user = curu->user; - curu->user = cur; - } - - return db; -} - -xmlnode ppdb_primary(ppdb db, jid id) -{ - ppdb cur, top; - - if(db == NULL || id == NULL) return NULL; - - cur = _ppdb_get(db,id); - - if(cur == NULL) return NULL; - - /* not user@host check, just return */ - if(id->user == NULL || id->resource != NULL) return cur->x; - - top = cur; - for(cur = cur->user; cur != NULL; cur = cur->user) - if(cur->pri >= top->pri) top = cur; - - if(top != NULL && top->pri >= 0) return top->x; - - return NULL; -} - -/* return the presence for the id, successive calls return all of the known resources for a user@host address */ -xmlnode ppdb_get(ppdb db, jid id) -{ - static ppdb last = NULL; - ppdb cur; - - if(db == NULL || id == NULL) return NULL; - - /* MODE: if this is NOT just user@host addy, return just the single entry */ - if(id->user == NULL || id->resource != NULL) - { - /* we were just here, return now */ - if(last != NULL) - { - last = NULL; - return NULL; - } - - last = _ppdb_get(db,id); - if(last != NULL) - return last->x; - else - return NULL; - } - - /* handle looping for user@host */ - - /* we're already in the loop */ - if(last != NULL) - { - /* this is the last entry in the list */ - if(last->user == NULL) - { - last = NULL; - return NULL; - } - - last = last->user; - return last->x; - } - - /* start a new loop */ - cur = _ppdb_get(db,id); - - if(cur == NULL) return NULL; - - last = cur->user; - if(last != NULL) - return last->x; - else - return NULL; -} - - -void ppdb_free(ppdb db) -{ - ppdb cur; - - if(db == NULL) return; - - for(cur = db; cur != NULL; cur = cur->next) - xmlnode_free(cur->x); - - pool_free(db->p); -} - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/rate.c --- a/mcabber/libjabber/rate.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * create a new instance of jlimit that is used to limit events - * - * limit the events to maxp points per maxt seconds - * - * @param maxt time interval (in seconds) after which the points are cleared - * @param maxp maximum number of points available for the time interval given in maxt - * @return new instance of jlimit (has to be freed with jlimit_free if not used anymore) - */ - -#include "jabber.h" - -jlimit jlimit_new(int maxt, int maxp) -{ - pool p; - jlimit r; - - p = pool_new(); - r = pmalloc(p,sizeof(_jlimit)); - r->key = NULL; - r->start = r->points = 0; - r->maxt = maxt; - r->maxp = maxp; - r->p = p; - - return r; -} - -/** - * free a jlimit instance - * - * @param r the jlimit instance that should be freed - */ -void jlimit_free(jlimit r) -{ - if(r != NULL) - { - if(r->key != NULL) free(r->key); - pool_free(r->p); - } -} - -/** - * update/check a key in a jlimit instance - * - * Each jlimit instance can track many limits (that have the same setup). - * The limit is selected by the key, which can be an IP address. - * - * @param r the jlimit instance - * @param key for which key the limit should be checked - * @param points how many points of the limit should be consumed - * @return 1 if limit reached, 0 if we are still within the rate limit - */ -int jlimit_check(jlimit r, char *key, int points) -{ - int now = time(NULL); - - if(r == NULL) return 0; - - /* make sure we didn't go over the time frame or get a null/new key */ - if((now - r->start) > r->maxt || key == NULL || j_strcmp(key,r->key) != 0) - { /* start a new key */ - free(r->key); - if(key != NULL) - /* We use strdup instead of pstrdup since r->key needs to be free'd before - and more often than the rest of the rlimit structure */ - r->key = strdup(key); - else - r->key = NULL; - r->start = now; - r->points = 0; - } - - r->points += points; - - /* if we're within the time frame and over the point limit */ - if(r->points > r->maxp && (now - r->start) < r->maxt) - { - return 1; /* we don't reset the rate here, so that it remains rated until the time runs out */ - } - - return 0; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/sha.c --- a/mcabber/libjabber/sha.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - * Paul Kocher - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include "libxode.h" - -static void shaHashBlock(SHA_CTX *ctx); - -void shaInit(SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301L; - ctx->H[1] = 0xefcdab89L; - ctx->H[2] = 0x98badcfeL; - ctx->H[3] = 0x10325476L; - ctx->H[4] = 0xc3d2e1f0L; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) { - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (uint32_t)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - shaUpdate(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - shaUpdate(ctx, &pad0x00, 1); - shaUpdate(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - shaInit(ctx); -} - - -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { - SHA_CTX ctx; - - shaInit(&ctx); - shaUpdate(&ctx, dataIn, len); - shaFinal(&ctx, hashout); -} - - -#define SHA_ROTL(X,n) (((X) << (n)) | ((X) >> (32-(n)))) - -static void shaHashBlock(SHA_CTX *ctx) { - int t; - uint32_t A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -/*---------------------------------------------------------------------------- - * - * This code added by Thomas "temas" Muldowney for Jabber compatability - * - *---------------------------------------------------------------------------*/ -char *shahash(char *str) -{ - static char final[41]; - char *pos; - unsigned char hashval[20]; - int x; - - if(!str || strlen(str) == 0) - return NULL; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = final; - for(x=0;x<20;x++) - { - snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - return (char *)final; -} - -void shahash_r(const char* str, char hashbuf[41]) -{ - int x; - char *pos; - unsigned char hashval[20]; - - if(!str || strlen(str) == 0) - return; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = hashbuf; - for(x=0;x<20;x++) - { - snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - - return; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/snprintf.c --- a/mcabber/libjabber/snprintf.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,945 +0,0 @@ -/* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the Apache Group - * for use in the Apache HTTP server project (http://www.apache.org/)." - * - * 4. The names "Apache Server" and "Apache Group" must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 5. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the Apache Group - * for use in the Apache HTTP server project (http://www.apache.org/)." - * - * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Group and was originally based - * on public domain software written at the National Center for - * Supercomputing Applications, University of Illinois, Urbana-Champaign. - * For more information on the Apache Group and the Apache HTTP server - * project, please see . - * - * This code is based on, and used with the permission of, the - * SIO stdio-replacement strx_* functions by Panos Tsirigotis - * for xinetd. - */ - -/** - * @file snprintf.c - * @brief implement snprintf if not present in the libc - * - * snprintf is not implemented by all libc implementations, this file implements this - * function, if it is not already present. You should not call any of the functions - * in this file directly! - */ - -#include - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -#include -#include -#include -#include -#include -#include -#include - - -#ifdef HAVE_GCVT - -#define ap_ecvt ecvt -#define ap_fcvt fcvt -#define ap_gcvt gcvt - -#else - -/* -* cvt.c - IEEE floating point formatting routines for FreeBSD -* from GNU libc-4.6.27 -*/ - -/* -* ap_ecvt converts to decimal -* the number of digits is specified by ndigit -* decpt is set to the position of the decimal point -* sign is set to 0 for positive, 1 for negative -*/ - -#define NDIG 80 - -static char * -ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag) -{ - register int r2; - double fi, fj; - register char *p, *p1; - static char buf[NDIG]; - - if (ndigits >= NDIG - 1) - ndigits = NDIG - 2; - r2 = 0; - *sign = 0; - p = &buf[0]; - if (arg < 0) { - *sign = 1; - arg = -arg; - } - arg = modf(arg, &fi); - p1 = &buf[NDIG]; - /* - * Do integer part - */ - if (fi != 0) { - p1 = &buf[NDIG]; - while (fi != 0) { - fj = modf(fi / 10, &fi); - *--p1 = (int) ((fj + .03) * 10) + '0'; - r2++; - } - while (p1 < &buf[NDIG]) - *p++ = *p1++; - } else if (arg > 0) { - while ((fj = arg * 10) < 1) { - arg = fj; - r2--; - } - } - p1 = &buf[ndigits]; - if (eflag == 0) - p1 += r2; - *decpt = r2; - if (p1 < &buf[0]) { - buf[0] = '\0'; - return (buf); - } - while (p <= p1 && p < &buf[NDIG]) { - arg *= 10; - arg = modf(arg, &fj); - *p++ = (int) fj + '0'; - } - if (p1 >= &buf[NDIG]) { - buf[NDIG - 1] = '\0'; - return (buf); - } - p = p1; - *p1 += 5; - while (*p1 > '9') { - *p1 = '0'; - if (p1 > buf) - ++ * --p1; - else { - *p1 = '1'; - (*decpt)++; - if (eflag == 0) { - if (p > buf) - *p = '0'; - p++; - } - } - } - *p = '\0'; - return (buf); -} - -static char * -ap_ecvt(double arg, int ndigits, int *decpt, int *sign) -{ - return (ap_cvt(arg, ndigits, decpt, sign, 1)); -} - -static char * -ap_fcvt(double arg, int ndigits, int *decpt, int *sign) -{ - return (ap_cvt(arg, ndigits, decpt, sign, 0)); -} - -/* -* ap_gcvt - Floating output conversion to -* minimal length string -*/ - -static char * -ap_gcvt(double number, int ndigit, char *buf) -{ - int sign, decpt; - register char *p1, *p2; - int i; - - p1 = ap_ecvt(number, ndigit, &decpt, &sign); - p2 = buf; - if (sign) - *p2++ = '-'; - for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) - ndigit--; - if ((decpt >= 0 && decpt - ndigit > 4) - || (decpt < 0 && decpt < -3)) { /* use E-style */ - decpt--; - *p2++ = *p1++; - *p2++ = '.'; - for (i = 1; i < ndigit; i++) - *p2++ = *p1++; - *p2++ = 'e'; - if (decpt < 0) { - decpt = -decpt; - *p2++ = '-'; - } else - *p2++ = '+'; - if (decpt / 100 > 0) - *p2++ = decpt / 100 + '0'; - if (decpt / 10 > 0) - *p2++ = (decpt % 100) / 10 + '0'; - *p2++ = decpt % 10 + '0'; - } else { - if (decpt <= 0) { - if (*p1 != '0') - *p2++ = '.'; - while (decpt < 0) { - decpt++; - *p2++ = '0'; - } - } - for (i = 1; i <= ndigit; i++) { - *p2++ = *p1++; - if (i == decpt) - *p2++ = '.'; - } - if (ndigit < decpt) { - while (ndigit++ < decpt) - *p2++ = '0'; - *p2++ = '.'; - } - } - if (p2[-1] == '.') - p2--; - *p2 = '\0'; - return (buf); -} - -#endif /* HAVE_CVT */ - -typedef enum { - NO = 0, YES = 1 -} boolean_e; - -#ifndef FALSE -# define FALSE 0 -#endif -#ifndef TRUE -# define TRUE 1 -#endif -#define NUL '\0' -#define INT_NULL ((int *)0) -#define WIDE_INT long - -typedef WIDE_INT wide_int; -typedef unsigned WIDE_INT u_wide_int; -typedef int bool_int; - -#define S_NULL "(null)" -#define S_NULL_LEN 6 - -#define FLOAT_DIGITS 6 -#define EXPONENT_LENGTH 10 - -/* - * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions - * - * XXX: this is a magic number; do not decrease it - */ -#define NUM_BUF_SIZE 512 - - -/* - * Descriptor for buffer area - */ -struct buf_area { - char *buf_end; - char *nextb; /* pointer to next byte to read/write */ -}; - -typedef struct buf_area buffy; - -/* - * The INS_CHAR macro inserts a character in the buffer and writes - * the buffer back to disk if necessary - * It uses the char pointers sp and bep: - * sp points to the next available character in the buffer - * bep points to the end-of-buffer+1 - * While using this macro, note that the nextb pointer is NOT updated. - * - * NOTE: Evaluation of the c argument should not have any side-effects - */ -#define INS_CHAR( c, sp, bep, cc ) \ - { \ - if ( sp < bep ) \ - { \ - *sp++ = c ; \ - cc++ ; \ - } \ - } - -#define NUM( c ) ( c - '0' ) - -#define STR_TO_DEC( str, num ) \ - num = NUM( *str++ ) ; \ - while ( isdigit((int)*str ) ) \ - { \ - num *= 10 ; \ - num += NUM( *str++ ) ; \ - } - -/* - * This macro does zero padding so that the precision - * requirement is satisfied. The padding is done by - * adding '0's to the left of the string that is going - * to be printed. - */ -#define FIX_PRECISION( adjust, precision, s, s_len ) \ - if ( adjust ) \ - while ( s_len < precision ) \ - { \ - *--s = '0' ; \ - s_len++ ; \ - } - -/* - * Macro that does padding. The padding is done by printing - * the character ch. - */ -#define PAD( width, len, ch ) do \ - { \ - INS_CHAR( ch, sp, bep, cc ) ; \ - width-- ; \ - } \ - while ( width > len ) - -/* - * Prefix the character ch to the string str - * Increase length - * Set the has_prefix flag - */ -#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES - - -/* - * Convert num to its decimal format. - * Return value: - * - a pointer to a string containing the number (no sign) - * - len contains the length of the string - * - is_negative is set to TRUE or FALSE depending on the sign - * of the number (always set to FALSE if is_unsigned is TRUE) - * - * The caller provides a buffer for the string: that is the buf_end argument - * which is a pointer to the END of the buffer + 1 (i.e. if the buffer - * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) - */ -static char * -conv_10(register wide_int num, register bool_int is_unsigned, - register bool_int * is_negative, char *buf_end, register int *len) -{ - register char *p = buf_end; - register u_wide_int magnitude; - - if (is_unsigned) { - magnitude = (u_wide_int) num; - *is_negative = FALSE; - } else { - *is_negative = (num < 0); - - /* - * On a 2's complement machine, negating the most negative integer - * results in a number that cannot be represented as a signed integer. - * Here is what we do to obtain the number's magnitude: - * a. add 1 to the number - * b. negate it (becomes positive) - * c. convert it to unsigned - * d. add 1 - */ - if (*is_negative) { - wide_int t = num + 1; - - magnitude = ((u_wide_int) - t) + 1; - } else - magnitude = (u_wide_int) num; - } - - /* - * We use a do-while loop so that we write at least 1 digit - */ - do { - register u_wide_int new_magnitude = magnitude / 10; - - *--p = magnitude - new_magnitude * 10 + '0'; - magnitude = new_magnitude; - } - while (magnitude); - - *len = buf_end - p; - return (p); -} - - - -/* - * Convert a floating point number to a string formats 'f', 'e' or 'E'. - * The result is placed in buf, and len denotes the length of the string - * The sign is returned in the is_negative argument (and is not placed - * in buf). - */ -static char * -conv_fp(register char format, register double num, - boolean_e add_dp, int precision, bool_int * is_negative, char *buf, int *len) -{ - register char *s = buf; - register char *p; - int decimal_point; - - if (format == 'f') - p = ap_fcvt(num, precision, &decimal_point, is_negative); - else /* either e or E format */ - p = ap_ecvt(num, precision + 1, &decimal_point, is_negative); - - /* - * Check for Infinity and NaN - */ - if (isalpha((int)*p)) { - *len = strlen(strcpy(buf, p)); - *is_negative = FALSE; - return (buf); - } - if (format == 'f') { - if (decimal_point <= 0) { - *s++ = '0'; - if (precision > 0) { - *s++ = '.'; - while (decimal_point++ < 0) - *s++ = '0'; - } else if (add_dp) { - *s++ = '.'; - } - } else { - while (decimal_point-- > 0) { - *s++ = *p++; - } - if (precision > 0 || add_dp) { - *s++ = '.'; - } - } - } else { - *s++ = *p++; - if (precision > 0 || add_dp) - *s++ = '.'; - } - - /* - * copy the rest of p, the NUL is NOT copied - */ - while (*p) - *s++ = *p++; - - if (format != 'f') { - char temp[EXPONENT_LENGTH]; /* for exponent conversion */ - int t_len; - bool_int exponent_is_negative; - - *s++ = format; /* either e or E */ - decimal_point--; - if (decimal_point != 0) { - p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, - &temp[EXPONENT_LENGTH], &t_len); - *s++ = exponent_is_negative ? '-' : '+'; - - /* - * Make sure the exponent has at least 2 digits - */ - if (t_len == 1) - *s++ = '0'; - while (t_len--) - *s++ = *p++; - } else { - *s++ = '+'; - *s++ = '0'; - *s++ = '0'; - } - } - *len = s - buf; - return (buf); -} - - -/* - * Convert num to a base X number where X is a power of 2. nbits determines X. - * For example, if nbits is 3, we do base 8 conversion - * Return value: - * a pointer to a string containing the number - * - * The caller provides a buffer for the string: that is the buf_end argument - * which is a pointer to the END of the buffer + 1 (i.e. if the buffer - * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) - */ -static char * -conv_p2(register u_wide_int num, register int nbits, - char format, char *buf_end, register int *len) -{ - register int mask = (1 << nbits) - 1; - register char *p = buf_end; - static char low_digits[] = "0123456789abcdef"; - static char upper_digits[] = "0123456789ABCDEF"; - register char *digits = (format == 'X') ? upper_digits : low_digits; - - do { - *--p = digits[num & mask]; - num >>= nbits; - } - while (num); - - *len = buf_end - p; - return (p); -} - - -/* - * Do format conversion placing the output in buffer - */ -static int format_converter(register buffy * odp, const char *fmt, - va_list ap) -{ - register char *sp; - register char *bep; - register int cc = 0; - register int i; - - register char *s = NULL; - char *q; - int s_len; - - register int min_width = 0; - int precision = 0; - enum { - LEFT, RIGHT - } adjust; - char pad_char; - char prefix_char; - - double fp_num; - wide_int i_num = (wide_int) 0; - u_wide_int ui_num; - - char num_buf[NUM_BUF_SIZE]; - char char_buf[2]; /* for printing %% and % */ - - /* - * Flag variables - */ - boolean_e is_long; - boolean_e alternate_form; - boolean_e print_sign; - boolean_e print_blank; - boolean_e adjust_precision; - boolean_e adjust_width; - bool_int is_negative; - - sp = odp->nextb; - bep = odp->buf_end; - - while (*fmt) { - if (*fmt != '%') { - INS_CHAR(*fmt, sp, bep, cc); - } else { - /* - * Default variable settings - */ - adjust = RIGHT; - alternate_form = print_sign = print_blank = NO; - pad_char = ' '; - prefix_char = NUL; - - fmt++; - - /* - * Try to avoid checking for flags, width or precision - */ - if (isascii((int)*fmt) && !islower((int)*fmt)) { - /* - * Recognize flags: -, #, BLANK, + - */ - for (;; fmt++) { - if (*fmt == '-') - adjust = LEFT; - else if (*fmt == '+') - print_sign = YES; - else if (*fmt == '#') - alternate_form = YES; - else if (*fmt == ' ') - print_blank = YES; - else if (*fmt == '0') - pad_char = '0'; - else - break; - } - - /* - * Check if a width was specified - */ - if (isdigit((int)*fmt)) { - STR_TO_DEC(fmt, min_width); - adjust_width = YES; - } else if (*fmt == '*') { - min_width = va_arg(ap, int); - fmt++; - adjust_width = YES; - if (min_width < 0) { - adjust = LEFT; - min_width = -min_width; - } - } else - adjust_width = NO; - - /* - * Check if a precision was specified - * - * XXX: an unreasonable amount of precision may be specified - * resulting in overflow of num_buf. Currently we - * ignore this possibility. - */ - if (*fmt == '.') { - adjust_precision = YES; - fmt++; - if (isdigit((int)*fmt)) { - STR_TO_DEC(fmt, precision); - } else if (*fmt == '*') { - precision = va_arg(ap, int); - fmt++; - if (precision < 0) - precision = 0; - } else - precision = 0; - } else - adjust_precision = NO; - } else - adjust_precision = adjust_width = NO; - - /* - * Modifier check - */ - if (*fmt == 'l') { - is_long = YES; - fmt++; - } else - is_long = NO; - - /* - * Argument extraction and printing. - * First we determine the argument type. - * Then, we convert the argument to a string. - * On exit from the switch, s points to the string that - * must be printed, s_len has the length of the string - * The precision requirements, if any, are reflected in s_len. - * - * NOTE: pad_char may be set to '0' because of the 0 flag. - * It is reset to ' ' by non-numeric formats - */ - switch (*fmt) { - case 'u': - if (is_long) - i_num = va_arg(ap, u_wide_int); - else - i_num = (wide_int) va_arg(ap, unsigned int); - /* - * The rest also applies to other integer formats, so fall - * into that case. - */ - case 'd': - case 'i': - /* - * Get the arg if we haven't already. - */ - if ((*fmt) != 'u') { - if (is_long) - i_num = va_arg(ap, wide_int); - else - i_num = (wide_int) va_arg(ap, int); - }; - s = conv_10(i_num, (*fmt) == 'u', &is_negative, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - - if (*fmt != 'u') { - if (is_negative) - prefix_char = '-'; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - } - break; - - - case 'o': - if (is_long) - ui_num = va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); - s = conv_p2(ui_num, 3, *fmt, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - if (alternate_form && *s != '0') { - *--s = '0'; - s_len++; - } - break; - - - case 'x': - case 'X': - if (is_long) - ui_num = (u_wide_int) va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); - s = conv_p2(ui_num, 4, *fmt, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - if (alternate_form && i_num != 0) { - *--s = *fmt; /* 'x' or 'X' */ - *--s = '0'; - s_len += 2; - } - break; - - - case 's': - s = va_arg(ap, char *); - if (s != NULL) { - s_len = strlen(s); - if (adjust_precision && precision < s_len) - s_len = precision; - } else { - s = S_NULL; - s_len = S_NULL_LEN; - } - pad_char = ' '; - break; - - - case 'f': - case 'e': - case 'E': - fp_num = va_arg(ap, double); - - s = conv_fp(*fmt, fp_num, alternate_form, - (adjust_precision == NO) ? FLOAT_DIGITS : precision, - &is_negative, &num_buf[1], &s_len); - if (is_negative) - prefix_char = '-'; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - break; - - - case 'g': - case 'G': - if (adjust_precision == NO) - precision = FLOAT_DIGITS; - else if (precision == 0) - precision = 1; - /* - * * We use &num_buf[ 1 ], so that we have room for the sign - */ - s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1]); - if (*s == '-') - prefix_char = *s++; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - - s_len = strlen(s); - - if (alternate_form && (q = strchr(s, '.')) == NULL) - s[s_len++] = '.'; - if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) - *q = 'E'; - break; - - - case 'c': - char_buf[0] = (char) (va_arg(ap, int)); - s = &char_buf[0]; - s_len = 1; - pad_char = ' '; - break; - - - case '%': - char_buf[0] = '%'; - s = &char_buf[0]; - s_len = 1; - pad_char = ' '; - break; - - - case 'n': - *(va_arg(ap, int *)) = cc; - break; - - /* - * Always extract the argument as a "char *" pointer. We - * should be using "void *" but there are still machines - * that don't understand it. - * If the pointer size is equal to the size of an unsigned - * integer we convert the pointer to a hex number, otherwise - * we print "%p" to indicate that we don't handle "%p". - */ - case 'p': - ui_num = (u_wide_int) va_arg(ap, char *); - - if (sizeof(char *) <= sizeof(u_wide_int)) - s = conv_p2(ui_num, 4, 'x', - &num_buf[NUM_BUF_SIZE], &s_len); - else { - s = "%p"; - s_len = 2; - } - pad_char = ' '; - break; - - - case NUL: - /* - * The last character of the format string was %. - * We ignore it. - */ - continue; - - - /* - * The default case is for unrecognized %'s. - * We print % to help the user identify what - * option is not understood. - * This is also useful in case the user wants to pass - * the output of format_converter to another function - * that understands some other % (like syslog). - * Note that we can't point s inside fmt because the - * unknown could be preceded by width etc. - */ - default: - char_buf[0] = '%'; - char_buf[1] = *fmt; - s = char_buf; - s_len = 2; - pad_char = ' '; - break; - } - - if (prefix_char != NUL) { - *--s = prefix_char; - s_len++; - } - if (adjust_width && adjust == RIGHT && min_width > s_len) { - if (pad_char == '0' && prefix_char != NUL) { - INS_CHAR(*s, sp, bep, cc) - s++; - s_len--; - min_width--; - } - PAD(min_width, s_len, pad_char); - } - /* - * Print the string s. - */ - for (i = s_len; i != 0; i--) { - INS_CHAR(*s, sp, bep, cc); - s++; - } - - if (adjust_width && adjust == LEFT && min_width > s_len) - PAD(min_width, s_len, pad_char); - } - fmt++; - } - odp->nextb = sp; - return (cc); -} - - -/* - * This is the general purpose conversion function. - */ -static void strx_printv(int *ccp, char *buf, size_t len, const char *format, - va_list ap) -{ - buffy od; - int cc; - - /* - * First initialize the descriptor - * Notice that if no length is given, we initialize buf_end to the - * highest possible address. - */ - od.buf_end = len ? &buf[len] : (char *) ~0; - od.nextb = buf; - - /* - * Do the conversion - */ - cc = format_converter(&od, format, ap); - if (len == 0 || od.nextb <= od.buf_end) - *(od.nextb) = '\0'; - if (ccp) - *ccp = cc; -} - - -int ap_snprintf(char *buf, size_t len, const char *format,...) -{ - int cc; - va_list ap; - - va_start(ap, format); - strx_printv(&cc, buf, (len - 1), format, ap); - va_end(ap); - return (cc); -} - - -int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap) -{ - int cc; - - strx_printv(&cc, buf, (len - 1), format, ap); - return (cc); -} - -#endif /* HAVE_SNPRINTF */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/socket.c --- a/mcabber/libjabber/socket.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,256 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file socket.c - * @brief some misc functions to handle sockets - */ - -#include "libxode.h" -#include "connwrap.h" - -/** - * Simple wrapper to make socket creation easy. - * - * @param port port number of the socket - * @param host hostname where to connect to or listen on - * @param type type of socket (NETSOCKET_SERVER, NETSOCKET_CLIENT; or NETSOCKET_UDP) - * @return file handle of the new socket - * - * NETSOCKET_SERVER is local listening socket - * NETSOCKET_CLIENT is connection socket - */ -int make_netsocket(u_short port, char *host, int type, int ssl) -{ - int s, flag = 1; - struct sockaddr_in sa; - struct in_addr *saddr; - int socket_type; - - /* is this a UDP socket or a TCP socket? */ - socket_type = (type == NETSOCKET_UDP)?SOCK_DGRAM:SOCK_STREAM; - - bzero((void *)&sa,sizeof(struct sockaddr_in)); - - if((s = socket(AF_INET,socket_type,0)) < 0) - return(-1); - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)) < 0) - return(-1); - - saddr = make_addr(host); - if(saddr == NULL) - return(-1); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - - if(type == NETSOCKET_SERVER) - { - /* bind to specific address if specified */ - if(host != NULL) - sa.sin_addr.s_addr = saddr->s_addr; - - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_CLIENT) - { - sa.sin_addr.s_addr = saddr->s_addr; - if(cw_connect(s,(struct sockaddr*)&sa,sizeof sa,ssl) < 0) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_UDP) - { - /* bind to all addresses for now */ - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - - /* specify default recipient for read/write */ - sa.sin_addr.s_addr = saddr->s_addr; - if(cw_connect(s,(struct sockaddr*)&sa,sizeof sa,ssl) < 0) - { - close(s); - return(-1); - } - } - - - return(s); -} - -void change_socket_to_blocking(int s) - /* make socket blocking */ -{ - int val; - val = fcntl(s, F_GETFL, 0); - fcntl(s, F_SETFL, val & (~O_NONBLOCK)); -} - -void change_socket_to_nonblocking(int s) - /* make socket non-blocking */ -{ - int val; - val = fcntl(s, F_GETFL, 0); - fcntl(s, F_SETFL, val | O_NONBLOCK); -} - -/* socket.c - * - * Simple wrapper to make non-blocking client socket creation easy. - * type = NETSOCKET_SERVER is local listening socket - * type = NETSOCKET_CLIENT is connection socket - * type = NETSOCKET_UDP - */ - -int make_nb_netsocket(u_short port, char *host, int type, int ssl, int* state) -{ - int s, flag = 1; - struct sockaddr_in sa; - struct in_addr *saddr; - int socket_type; - - /* is this a UDP socket or a TCP socket? */ - socket_type = (type == NETSOCKET_UDP)?SOCK_DGRAM:SOCK_STREAM; - - bzero((void *)&sa,sizeof(struct sockaddr_in)); - - if((s = socket(AF_INET,socket_type,0)) < 0) - return(-1); - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)) < 0) - return(-1); - change_socket_to_nonblocking(s); - - saddr = make_addr(host); - if(saddr == NULL) - return(-1); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - - if(type == NETSOCKET_SERVER) - { - /* bind to specific address if specified */ - if(host != NULL) - sa.sin_addr.s_addr = saddr->s_addr; - - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_CLIENT) - { - int rc; - sa.sin_addr.s_addr = saddr->s_addr; - rc = cw_nb_connect(s,(struct sockaddr*)&sa,sizeof sa,ssl, state); - if (rc == -1 ) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_UDP) - { - /* bind to all addresses for now */ - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - - /* specify default recipient for read/write */ - sa.sin_addr.s_addr = saddr->s_addr; - if(cw_connect(s,(struct sockaddr*)&sa,sizeof sa,ssl) < 0) - { - close(s); - return(-1); - } - } - - - return(s); -} - -struct in_addr *make_addr(char *host) -{ - struct hostent *hp; - static struct in_addr addr; - char myname[MAXHOSTNAMELEN + 1]; - - if (host == NULL || strlen(host) == 0) { - gethostname(myname,MAXHOSTNAMELEN); - hp = gethostbyname(myname); - if(hp != NULL) { - return (struct in_addr *) *hp->h_addr_list; - } - } else { - addr.s_addr = inet_addr(host); - if(addr.s_addr != (in_addr_t)-1) { - return &addr; - } - hp = gethostbyname(host); - if(hp != NULL) { - return (struct in_addr *) *hp->h_addr_list; - } - } - return NULL; -} - -/** - * Sets a file descriptor to close on exec. - * - * @param fd the file descriptor - * @param flag 1 to close on exec, 0 to leave open across exec - * - * @deprecated this function is not used by jabberd14 and might be removed in future versions - */ -int set_fd_close_on_exec(int fd, int flag) -{ - int oldflags = fcntl(fd,F_GETFL); - int newflags; - - if(flag) - newflags = oldflags | FD_CLOEXEC; - else - newflags = oldflags & (~FD_CLOEXEC); - - if(newflags==oldflags) - return 0; - return fcntl(fd,F_SETFL,(long)newflags); -} - diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/str.c --- a/mcabber/libjabber/str.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file str.c - * @brief utilities for string handling - * - * This file contains utility functions for string handling: - * - NULL pointer save versions of many functions in string.c - * - string spools - * - functions to (un)escape strings for XML usage - * - * String spools allow to create a string by concatenating several smaller strings - * and the spool implementation is allocating the neccessary memory using memory pools. - */ - -#include "libxode.h" - -/** - * NULL pointer save version of strdup() - * - * @param str the string the should be duplicated - * @return the duplicated string - */ -char *j_strdup(const char *str) -{ - if(str == NULL) - return NULL; - else - return strdup(str); -} - -/** - * NULL pointer save version of strcat() - * - * @note the return value of j_strcat() is not compatible with the return value of strcat() - * - * @todo check if the behaviour of the return value is intended - * - * @param dest where to append the string - * @param txt what to append - * @return dest if txt contains a NULL pointer, pointer to the terminating zero byte of the result else - */ -char *j_strcat(char *dest, char *txt) -{ - if(!txt) return(dest); - - while(*txt) - *dest++ = *txt++; - *dest = '\0'; - - return(dest); -} - -/** - * NULL pointer save version of strcmp - * - * If one of the parameters contains a NULL pointer, the string is considered to be unequal. - * - * @note the return value is not compatible with strcmp() - * - * @param a the one string - * @param b the other string - * @return 0 if the strings are equal, -1 if the strings are not equal - */ -int j_strcmp(const char *a, const char *b) -{ - if(a == NULL || b == NULL) - return -1; - - while(*a == *b && *a != '\0' && *b != '\0'){ a++; b++; } - - if(*a == *b) return 0; - - return -1; -} - -/** - * NULL pointer save version of strcasecmp() - * - * If one of the parameters contains a NULL pointer, the string is considered to be unequal - * - * @param a the one string - * @param b the other string - * @return 0 if the strings are equal, non zero else - */ -int j_strcasecmp(const char *a, const char *b) -{ - if(a == NULL || b == NULL) - return -1; - else - return strcasecmp(a, b); -} - -/** - * NULL pointer save version of strncmp() - * - * If one of the parameters contains a NULL pointer, the string is considered to be unequal - * - * @param a the first string - * @param b the second string - * @param i how many characters to compare at most - * @return 0 if the strings are equal (within the given length limitation), non zero else - */ -int j_strncmp(const char *a, const char *b, int i) -{ - if(a == NULL || b == NULL) - return -1; - else - return strncmp(a, b, i); -} - -/** - * NULL pointer save version of strncasecmp() - * - * If one of the parameters contains a NULL pointer, the string is considered to be unequal - * - * @param a the first string - * @param b the second string - * @param i how many characters to compare at most - * @return 0 if the strings are equal (within the given length limitation), non zero else - */ -int j_strncasecmp(const char *a, const char *b, int i) -{ - if(a == NULL || b == NULL) - return -1; - else - return strncasecmp(a, b, i); -} - -/** - * NULL pointer save version of strlen - * - * If the parameter contains a NULL pointer, 0 is returned - * - * @param a the string for which the length should be calculated - * @return 0 if a==NULL, length of the string else - */ -int j_strlen(const char *a) -{ - if(a == NULL) - return 0; - else - return strlen(a); -} - -int j_atoi(const char *a, int def) -{ - if(a == NULL) - return def; - else - return atoi(a); -} - -spool spool_new(pool p) -{ - spool s; - - s = pmalloc(p, sizeof(struct spool_struct)); - s->p = p; - s->len = 0; - s->last = NULL; - s->first = NULL; - return s; -} - -void spool_add(spool s, char *str) -{ - struct spool_node *sn; - int len; - - if(str == NULL) - return; - - len = strlen(str); - if(len == 0) - return; - - sn = pmalloc(s->p, sizeof(struct spool_node)); - sn->c = pstrdup(s->p, str); - sn->next = NULL; - - s->len += len; - if(s->last != NULL) - s->last->next = sn; - s->last = sn; - if(s->first == NULL) - s->first = sn; -} - -void spooler(spool s, ...) -{ - va_list ap; - char *arg = NULL; - - if(s == NULL) - return; - - va_start(ap, s); - - /* loop till we hit our end flag, the first arg */ - while(1) - { - arg = va_arg(ap,char *); - if((spool)arg == s) - break; - else - spool_add(s, arg); - } - - va_end(ap); -} - -char *spool_print(spool s) -{ - char *ret,*tmp; - struct spool_node *next; - - if(s == NULL || s->len == 0 || s->first == NULL) - return NULL; - - ret = pmalloc(s->p, s->len + 1); - *ret = '\0'; - - next = s->first; - tmp = ret; - while(next != NULL) - { - tmp = j_strcat(tmp,next->c); - next = next->next; - } - - return ret; -} - -/* convenience :) */ -char *spools(pool p, ...) -{ - va_list ap; - spool s; - char *arg = NULL; - - if(p == NULL) - return NULL; - - s = spool_new(p); - - va_start(ap, p); - - /* loop till we hit our end flag, the first arg */ - while(1) - { - arg = va_arg(ap,char *); - if((pool)arg == p) - break; - else - spool_add(s, arg); - } - - va_end(ap); - - return spool_print(s); -} - - -char *strunescape(pool p, char *buf) -{ - int i,j=0; - char *temp; - - if (p == NULL || buf == NULL) return(NULL); - - if (strchr(buf,'&') == NULL) return(buf); - - temp = pmalloc(p,strlen(buf)+1); - - if (temp == NULL) return(NULL); - - for(i=0;i<(int)strlen(buf);i++) - { - if (buf[i]=='&') - { - if (strncmp(&buf[i],"&",5)==0) - { - temp[j] = '&'; - i += 4; - } else if (strncmp(&buf[i],""",6)==0) { - temp[j] = '\"'; - i += 5; - } else if (strncmp(&buf[i],"'",6)==0) { - temp[j] = '\''; - i += 5; - } else if (strncmp(&buf[i],"<",4)==0) { - temp[j] = '<'; - i += 3; - } else if (strncmp(&buf[i],">",4)==0) { - temp[j] = '>'; - i += 3; - } - } else { - temp[j]=buf[i]; - } - j++; - } - temp[j]='\0'; - return(temp); -} - - -char *strescape(pool p, char *buf) -{ - int i,j,oldlen,newlen; - char *temp; - - if (p == NULL || buf == NULL) return(NULL); - - oldlen = newlen = strlen(buf); - for(i=0;i': - newlen+=4; - break; - } - } - - if(oldlen == newlen) return buf; - - temp = pmalloc(p,newlen+1); - - if (temp==NULL) return(NULL); - - for(i=j=0;i': - memcpy(&temp[j],">",4); - j += 4; - break; - default: - temp[j++] = buf[i]; - } - } - temp[j] = '\0'; - return temp; -} - -char *zonestr(char *file, int line) -{ - static char buff[64]; - int i; - - i = snprintf(buff,63,"%s:%d",file,line); - buff[i] = '\0'; - - return buff; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/utf8tab.h --- a/mcabber/libjabber/utf8tab.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, -/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmldef.h --- a/mcabber/libjabber/xmldef.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include - -#ifdef XML_WINLIB - -#define WIN32_LEAN_AND_MEAN -#define STRICT -#include - -#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x)) -#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y)) -#define free(x) HeapFree(GetProcessHeap(), 0, (x)) -#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y) -#define abort() /* as nothing */ - -#else /* not XML_WINLIB */ - -#include - -#endif /* not XML_WINLIB */ - -/* This file can be used for any definitions needed in -particular environments. */ - -#ifdef MOZILLA - -#include "nspr.h" -#define malloc(x) PR_Malloc(x) -#define realloc(x, y) PR_Realloc((x), (y)) -#define calloc(x, y) PR_Calloc((x),(y)) -#define free(x) PR_Free(x) -#define int int32 - -#endif /* MOZILLA */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmlnode.c --- a/mcabber/libjabber/xmlnode.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,834 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -#include "libxode.h" - -/* Internal routines */ -xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) -{ - xmlnode result = NULL; - if (type > NTYPE_LAST) - return NULL; - - if (type != NTYPE_CDATA && name == NULL) - return NULL; - - if (p == NULL) - { - p = pool_heap(1*1024); - } - - /* Allocate & zero memory */ - result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); - - /* Initialize fields */ - if (type != NTYPE_CDATA) - result->name = pstrdup(p,name); - result->type = type; - result->p = p; - return result; -} - -static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type) -{ - xmlnode result; - - result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); - if (result != NULL) - { - /* Setup sibling pointers */ - result->prev = lastsibling; - lastsibling->next = result; - } - return result; -} - -static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) -{ - xmlnode result; - - if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL; - - /* If parent->firstchild is NULL, simply create a new node for the first child */ - if (parent->firstchild == NULL) - { - result = _xmlnode_new(parent->p, name, type); - parent->firstchild = result; - } - /* Otherwise, append this to the lastchild */ - else - { - result= _xmlnode_append_sibling(parent->lastchild, name, type); - } - result->parent = parent; - parent->lastchild = result; - return result; - -} - -static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) -{ - xmlnode current; - - /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with - the specified name */ - current = firstsibling; - while (current != NULL) - { - if ((current->type == type) && (j_strcmp(current->name, name) == 0)) - return current; - else - current = current->next; - } - return NULL; -} - -void _xmlnode_merge(xmlnode data) -{ - xmlnode cur; - char *merge, *scur; - int imerge; - - /* get total size of all merged cdata */ - imerge = 0; - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - imerge += cur->data_sz; - - /* copy in current data and then spin through all of them and merge */ - scur = merge = pmalloc(data->p,imerge + 1); - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - { - memcpy(scur,cur->data,cur->data_sz); - scur += cur->data_sz; - } - *scur = '\0'; - - /* this effectively hides all of the merged-in chunks */ - data->next = cur; - if(cur == NULL) - data->parent->lastchild = data; - else - cur->prev = data; - - /* reset data */ - data->data = merge; - data->data_sz = imerge; -} - -static void _xmlnode_hide_sibling(xmlnode child) -{ - if(child == NULL) - return; - - if(child->prev != NULL) - child->prev->next = child->next; - if(child->next != NULL) - child->next->prev = child->prev; -} - -void _xmlnode_tag2str(spool s, xmlnode node, int flag) -{ - xmlnode tmp; - - if(flag==0 || flag==1) - { - spooler(s,"<",xmlnode_get_name(node),s); - tmp = xmlnode_get_firstattrib(node); - while(tmp) { - spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); - tmp = xmlnode_get_nextsibling(tmp); - } - if(flag==0) - spool_add(s,"/>"); - else - spool_add(s,">"); - } - else - { - spooler(s,"",s); - } -} - -spool _xmlnode2spool(xmlnode node) -{ - spool s; - int level=0,dir=0; - xmlnode tmp; - - if(!node || xmlnode_get_type(node)!=NTYPE_TAG) - return NULL; - - s = spool_new(xmlnode_pool(node)); - if(!s) return(NULL); - - while(1) - { - if(dir==0) - { - if(xmlnode_get_type(node) == NTYPE_TAG) - { - if(xmlnode_has_children(node)) - { - _xmlnode_tag2str(s,node,1); - node = xmlnode_get_firstchild(node); - level++; - continue; - }else{ - _xmlnode_tag2str(s,node,0); - } - }else{ - spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); - } - } - - tmp = xmlnode_get_nextsibling(node); - if(!tmp) - { - node = xmlnode_get_parent(node); - level--; - if(level>=0) _xmlnode_tag2str(s,node,2); - if(level<1) break; - dir = 1; - }else{ - node = tmp; - dir = 0; - } - } - - return s; -} - - -/* External routines */ - - -/* - * xmlnode_new_tag -- create a tag node - * Automatically creates a memory pool for the node. - * - * parameters - * name -- name of the tag - * - * returns - * a pointer to the tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_new_tag(const char* name) -{ - return _xmlnode_new(NULL, name, NTYPE_TAG); -} - - -/* - * xmlnode_new_tag_pool -- create a tag node within given pool - * - * parameters - * p -- previously created memory pool - * name -- name of the tag - * - * returns - * a pointer to the tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_new_tag_pool(pool p, const char* name) -{ - return _xmlnode_new(p, name, NTYPE_TAG); -} - - -/* - * xmlnode_insert_tag -- append a child tag to a tag - * - * parameters - * parent -- pointer to the parent tag - * name -- name of the child tag - * - * returns - * a pointer to the child tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name) -{ - return _xmlnode_insert(parent, name, NTYPE_TAG); -} - - -/* - * xmlnode_insert_cdata -- append character data to a tag - * - * parameters - * parent -- parent tag - * CDATA -- character data - * size -- size of CDATA - * or -1 for null-terminated CDATA strings - * - * returns - * a pointer to the child CDATA node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size) -{ - xmlnode result; - - if(CDATA == NULL || parent == NULL) - return NULL; - - if(size == (unsigned int)-1) - size = strlen(CDATA); - - result = _xmlnode_insert(parent, NULL, NTYPE_CDATA); - if (result != NULL) - { - result->data = (char*)pmalloc(result->p, size + 1); - memcpy(result->data, CDATA, size); - result->data[size] = '\0'; - result->data_sz = size; - } - - return result; -} - - -/* - * xmlnode_get_tag -- find given tag in an xmlnode tree - * - * parameters - * parent -- pointer to the parent tag - * name -- "name" for the child tag of that name - * "name/name" for a sub child (recurses) - * "?attrib" to match the first tag with that attrib defined - * "?attrib=value" to match the first tag with that attrib and value - * "=cdata" to match the cdata contents of the child - * or any combination: "name/name/?attrib", "name=cdata", etc - * - * results - * a pointer to the tag matching search criteria - * or NULL if search was unsuccessfull - */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name) -{ - char *str, *slash, *qmark, *equals; - xmlnode step, ret; - - - if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; - - if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) - return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); - - str = strdup(name); - slash = strstr(str, "/"); - qmark = strstr(str, "?"); - equals = strstr(str, "="); - - if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) - { /* of type =cdata */ - - *equals = '\0'; - equals++; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; - - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(j_strcmp(xmlnode_get_data(step),equals) != 0) - continue; - - break; - } - - free(str); - return step; - } - - - if(qmark != NULL && (slash == NULL || qmark < slash)) - { /* of type ?attrib */ - - *qmark = '\0'; - qmark++; - if(equals != NULL) - { - *equals = '\0'; - equals++; - } - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; - - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(xmlnode_get_attrib(step,qmark) == NULL) - continue; - - if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) - continue; - - break; - } - - free(str); - return step; - } - - - *slash = '\0'; - ++slash; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) continue; - - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - ret = xmlnode_get_tag(step, slash); - if(ret != NULL) - { - free(str); - return ret; - } - } - - free(str); - return NULL; -} - - -/* return the cdata from any tag */ -char *xmlnode_get_tag_data(xmlnode parent, const char *name) -{ - xmlnode tag; - - tag = xmlnode_get_tag(parent, name); - if(tag == NULL) return NULL; - - return xmlnode_get_data(tag); -} - - -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value) -{ - xmlnode attrib; - - if(owner == NULL || name == NULL || value == NULL) return; - - /* If there are no existing attributs, allocate a new one to start - the list */ - if (owner->firstattrib == NULL) - { - attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB); - owner->firstattrib = attrib; - owner->lastattrib = attrib; - } - else - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - { - attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB); - owner->lastattrib = attrib; - } - } - /* Update the value of the attribute */ - attrib->data_sz = strlen(value); - attrib->data = pstrdup(owner->p, value); - -} - -char* xmlnode_get_attrib(xmlnode owner, const char* name) -{ - xmlnode attrib; - - if (owner != NULL && owner->firstattrib != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib != NULL) - return (char*)attrib->data; - } - return NULL; -} - -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value) -{ - xmlnode attrib; - - if (owner != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib == NULL) - { - xmlnode_put_attrib(owner, name, ""); - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - } - if (attrib != NULL) - attrib->firstchild = (xmlnode)value; - } -} - -void* xmlnode_get_vattrib(xmlnode owner, const char* name) -{ - xmlnode attrib; - - if (owner != NULL && owner->firstattrib != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib != NULL) - return (void*)attrib->firstchild; - } - return NULL; -} - -xmlnode xmlnode_get_firstattrib(xmlnode parent) -{ - if (parent != NULL) - return parent->firstattrib; - return NULL; -} - -xmlnode xmlnode_get_firstchild(xmlnode parent) -{ - if (parent != NULL) - return parent->firstchild; - return NULL; -} - -xmlnode xmlnode_get_lastchild(xmlnode parent) -{ - if (parent != NULL) - return parent->lastchild; - return NULL; -} - -xmlnode xmlnode_get_nextsibling(xmlnode sibling) -{ - if (sibling != NULL) - return sibling->next; - return NULL; -} - -xmlnode xmlnode_get_prevsibling(xmlnode sibling) -{ - if (sibling != NULL) - return sibling->prev; - return NULL; -} - -xmlnode xmlnode_get_parent(xmlnode node) -{ - if (node != NULL) - return node->parent; - return NULL; -} - -char* xmlnode_get_name(xmlnode node) -{ - if (node != NULL) - return node->name; - return NULL; -} - -char* xmlnode_get_data(xmlnode node) -{ - if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */ - for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node)) - if(xmlnode_get_type(node) == NTYPE_CDATA) break; - - if(node == NULL) return NULL; - - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - - return node->data; -} - -int xmlnode_get_datasz(xmlnode node) -{ - if(xmlnode_get_type(node) != NTYPE_CDATA) return 0; - - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - return node->data_sz; -} - -int xmlnode_get_type(xmlnode node) -{ - if (node != NULL) - return node->type; - return NTYPE_UNDEF; -} - -int xmlnode_has_children(xmlnode node) -{ - if ((node != NULL) && (node->firstchild != NULL)) - return 1; - return 0; -} - -int xmlnode_has_attribs(xmlnode node) -{ - if ((node != NULL) && (node->firstattrib != NULL)) - return 1; - return 0; -} - -pool xmlnode_pool(xmlnode node) -{ - if (node != NULL) - return node->p; - return (pool)NULL; -} - -void xmlnode_hide(xmlnode child) -{ - xmlnode parent; - - if(child == NULL || child->parent == NULL) - return; - - parent = child->parent; - - /* first fix up at the child level */ - _xmlnode_hide_sibling(child); - - /* next fix up at the parent level */ - if(parent->firstchild == child) - parent->firstchild = child->next; - if(parent->lastchild == child) - parent->lastchild = child->prev; -} - -void xmlnode_hide_attrib(xmlnode parent, const char *name) -{ - xmlnode attrib; - - if(parent == NULL || parent->firstattrib == NULL || name == NULL) - return; - - attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - return; - - /* first fix up at the child level */ - _xmlnode_hide_sibling(attrib); - - /* next fix up at the parent level */ - if(parent->firstattrib == attrib) - parent->firstattrib = attrib->next; - if(parent->lastattrib == attrib) - parent->lastattrib = attrib->prev; -} - - - -/* - * xmlnode2str -- convert given xmlnode tree into a string - * - * parameters - * node -- pointer to the xmlnode structure - * - * results - * a pointer to the created string - * or NULL if it was unsuccessfull - */ -char *xmlnode2str(xmlnode node) -{ - return spool_print(_xmlnode2spool(node)); -} - -/* - * xmlnode2tstr -- convert given xmlnode tree into a newline terminated string - * - * parameters - * node -- pointer to the xmlnode structure - * - * results - * a pointer to the created string - * or NULL if it was unsuccessfull - */ -char* xmlnode2tstr(xmlnode node) -{ - spool s = _xmlnode2spool(node); - if (s != NULL) - spool_add(s, "\n"); - return spool_print(s); -} - - -/* loop through both a and b comparing everything, attribs, cdata, children, etc */ -int xmlnode_cmp(xmlnode a, xmlnode b) -{ - int ret = 0; - - while(1) - { - if(a == NULL && b == NULL) - return 0; - - if(a == NULL || b == NULL) - return -1; - - if(xmlnode_get_type(a) != xmlnode_get_type(b)) - return -1; - - switch(xmlnode_get_type(a)) - { - case NTYPE_ATTRIB: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - break; - case NTYPE_TAG: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); - if(ret != 0) - return -1; - break; - case NTYPE_CDATA: - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - } - a = xmlnode_get_nextsibling(a); - b = xmlnode_get_nextsibling(b); - } -} - - -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node) -{ - xmlnode child; - - child = xmlnode_insert_tag(parent, xmlnode_get_name(node)); - if (xmlnode_has_attribs(node)) - xmlnode_insert_node(child, xmlnode_get_firstattrib(node)); - if (xmlnode_has_children(node)) - xmlnode_insert_node(child, xmlnode_get_firstchild(node)); - - return child; -} - -/* places copy of node and node's siblings in parent */ -void xmlnode_insert_node(xmlnode parent, xmlnode node) -{ - if(node == NULL || parent == NULL) - return; - - while(node != NULL) - { - switch(xmlnode_get_type(node)) - { - case NTYPE_ATTRIB: - xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node)); - break; - case NTYPE_TAG: - xmlnode_insert_tag_node(parent, node); - break; - case NTYPE_CDATA: - xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node)); - } - node = xmlnode_get_nextsibling(node); - } -} - - -/* produce full duplicate of x with a new pool, x must be a tag! */ -xmlnode xmlnode_dup(xmlnode x) -{ - xmlnode x2; - - if(x == NULL) - return NULL; - - x2 = xmlnode_new_tag(xmlnode_get_name(x)); - - if (xmlnode_has_attribs(x)) - xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); - if (xmlnode_has_children(x)) - xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); - - return x2; -} - -xmlnode xmlnode_dup_pool(pool p, xmlnode x) -{ - xmlnode x2; - - if(x == NULL) - return NULL; - - x2 = xmlnode_new_tag_pool(p, xmlnode_get_name(x)); - - if (xmlnode_has_attribs(x)) - xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); - if (xmlnode_has_children(x)) - xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); - - return x2; -} - -xmlnode xmlnode_wrap(xmlnode x,const char *wrapper) -{ - xmlnode wrap; - if(x==NULL||wrapper==NULL) return NULL; - wrap=xmlnode_new_tag_pool(xmlnode_pool(x),wrapper); - if(wrap==NULL) return NULL; - wrap->firstchild=x; - wrap->lastchild=x; - x->parent=wrap; - return wrap; -} - -void xmlnode_free(xmlnode node) -{ - if(node == NULL) - return; - - pool_free(node->p); -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmlparse.c --- a/mcabber/libjabber/xmlparse.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3252 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include "xmldef.h" -#include "xmlparse.h" - -#ifdef XML_UNICODE -#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX -#define XmlConvert XmlUtf16Convert -#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS -#define XmlEncode XmlUtf16Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) -typedef unsigned short ICHAR; -#else -#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX -#define XmlConvert XmlUtf8Convert -#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS -#define XmlEncode XmlUtf8Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) -typedef char ICHAR; -#endif - - -#ifndef XML_NS - -#define XmlInitEncodingNS XmlInitEncoding -#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding -#undef XmlGetInternalEncodingNS -#define XmlGetInternalEncodingNS XmlGetInternalEncoding -#define XmlParseXmlDeclNS XmlParseXmlDecl - -#endif - - -#ifdef XML_UNICODE_WCHAR_T -#define XML_T(x) L ## x -#else -#define XML_T(x) x -#endif - -/* Round up n to be a multiple of sz, where sz is a power of 2. */ -#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) - -#include "xmltok.h" -#include "xmlrole.h" -#include "hashtable.h" - -#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ -#define INIT_DATA_BUF_SIZE 1024 -#define INIT_ATTS_SIZE 16 -#define INIT_BLOCK_SIZE 1024 -#define INIT_BUFFER_SIZE 1024 - -#define EXPAND_SPARE 24 - -typedef struct binding { - struct prefix *prefix; - struct binding *nextTagBinding; - struct binding *prevPrefixBinding; - const struct attribute_id *attId; - XML_Char *uri; - int uriLen; - int uriAlloc; -} BINDING; - -typedef struct prefix { - const XML_Char *name; - BINDING *binding; -} PREFIX; - -typedef struct { - const XML_Char *str; - const XML_Char *localPart; - int uriLen; -} TAG_NAME; - -typedef struct tag { - struct tag *parent; - const char *rawName; - int rawNameLength; - TAG_NAME name; - char *buf; - char *bufEnd; - BINDING *bindings; -} TAG; - -typedef struct { - const XML_Char *name; - const XML_Char *textPtr; - int textLen; - const XML_Char *systemId; - const XML_Char *base; - const XML_Char *publicId; - const XML_Char *notation; - char open; -} ENTITY; - -typedef struct block { - struct block *next; - int size; - XML_Char s[1]; -} BLOCK; - -typedef struct { - BLOCK *blocks; - BLOCK *freeBlocks; - const XML_Char *end; - XML_Char *ptr; - XML_Char *start; -} STRING_POOL; - -/* The XML_Char before the name is used to determine whether -an attribute has been specified. */ -typedef struct attribute_id { - XML_Char *name; - PREFIX *prefix; - char maybeTokenized; - char xmlns; -} ATTRIBUTE_ID; - -typedef struct { - const ATTRIBUTE_ID *id; - char isCdata; - const XML_Char *value; -} DEFAULT_ATTRIBUTE; - -typedef struct { - const XML_Char *name; - PREFIX *prefix; - int nDefaultAtts; - int allocDefaultAtts; - DEFAULT_ATTRIBUTE *defaultAtts; -} ELEMENT_TYPE; - -typedef struct { - HASH_TABLE generalEntities; - HASH_TABLE elementTypes; - HASH_TABLE attributeIds; - HASH_TABLE prefixes; - STRING_POOL pool; - int complete; - int standalone; - const XML_Char *base; - PREFIX defaultPrefix; -} DTD; - -typedef struct open_internal_entity { - const char *internalEventPtr; - const char *internalEventEndPtr; - struct open_internal_entity *next; - ENTITY *entity; -} OPEN_INTERNAL_ENTITY; - -typedef enum XML_Error Processor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr); - -static Processor prologProcessor; -static Processor prologInitProcessor; -static Processor contentProcessor; -static Processor cdataSectionProcessor; -static Processor epilogProcessor; -/* static Processor errorProcessor; */ -static Processor externalEntityInitProcessor; -static Processor externalEntityInitProcessor2; -static Processor externalEntityInitProcessor3; -static Processor externalEntityContentProcessor; - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); -static enum XML_Error -initializeEncoding(XML_Parser parser); -static enum XML_Error -doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, - const char *start, const char *end, const char **endPtr); -static enum XML_Error -doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, - TAG_NAME *tagNamePtr, BINDING **bindingsPtr); -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue); -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); -static enum XML_Error -storeEntityValue(XML_Parser parser, const char *start, const char *end); -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); - -static const XML_Char *getContext(XML_Parser parser); -static int setContext(XML_Parser parser, const XML_Char *context); -static void normalizePublicId(XML_Char *s); -static int dtdInit(DTD *); -static void dtdDestroy(DTD *); -static int dtdCopy(DTD *newDtd, const DTD *oldDtd); -static void poolInit(STRING_POOL *); -static void poolClear(STRING_POOL *); -static void poolDestroy(STRING_POOL *); -static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static int poolGrow(STRING_POOL *pool); -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s); -static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); - -#define poolStart(pool) ((pool)->start) -#define poolEnd(pool) ((pool)->ptr) -#define poolLength(pool) ((pool)->ptr - (pool)->start) -#define poolChop(pool) ((void)--(pool->ptr)) -#define poolLastChar(pool) (((pool)->ptr)[-1]) -#define poolDiscard(pool) ((pool)->ptr = (pool)->start) -#define poolFinish(pool) ((pool)->start = (pool)->ptr) -#define poolAppendChar(pool, c) \ - (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ - ? 0 \ - : ((*((pool)->ptr)++ = c), 1)) - -typedef struct { - /* The first member must be userData so that the XML_GetUserData macro works. */ - void *m_userData; - void *m_handlerArg; - char *m_buffer; - /* first character to be parsed */ - const char *m_bufferPtr; - /* past last character to be parsed */ - char *m_bufferEnd; - /* allocated end of buffer */ - const char *m_bufferLim; - long m_parseEndByteIndex; - const char *m_parseEndPtr; - XML_Char *m_dataBuf; - XML_Char *m_dataBufEnd; - XML_StartElementHandler m_startElementHandler; - XML_EndElementHandler m_endElementHandler; - XML_CharacterDataHandler m_characterDataHandler; - XML_ProcessingInstructionHandler m_processingInstructionHandler; - XML_CommentHandler m_commentHandler; - XML_StartCdataSectionHandler m_startCdataSectionHandler; - XML_EndCdataSectionHandler m_endCdataSectionHandler; - XML_DefaultHandler m_defaultHandler; - XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; - XML_NotationDeclHandler m_notationDeclHandler; - XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; - XML_NotStandaloneHandler m_notStandaloneHandler; - XML_ExternalEntityRefHandler m_externalEntityRefHandler; - void *m_externalEntityRefHandlerArg; - XML_UnknownEncodingHandler m_unknownEncodingHandler; - const ENCODING *m_encoding; - INIT_ENCODING m_initEncoding; - const XML_Char *m_protocolEncodingName; - int m_ns; - void *m_unknownEncodingMem; - void *m_unknownEncodingData; - void *m_unknownEncodingHandlerData; - void (*m_unknownEncodingRelease)(void *); - PROLOG_STATE m_prologState; - Processor *m_processor; - enum XML_Error m_errorCode; - const char *m_eventPtr; - const char *m_eventEndPtr; - const char *m_positionPtr; - OPEN_INTERNAL_ENTITY *m_openInternalEntities; - int m_defaultExpandInternalEntities; - int m_tagLevel; - ENTITY *m_declEntity; - const XML_Char *m_declNotationName; - const XML_Char *m_declNotationPublicId; - ELEMENT_TYPE *m_declElementType; - ATTRIBUTE_ID *m_declAttributeId; - char m_declAttributeIsCdata; - DTD m_dtd; - TAG *m_tagStack; - TAG *m_freeTagList; - BINDING *m_inheritedBindings; - BINDING *m_freeBindingList; - int m_attsSize; - int m_nSpecifiedAtts; - ATTRIBUTE *m_atts; - POSITION m_position; - STRING_POOL m_tempPool; - STRING_POOL m_temp2Pool; - char *m_groupConnector; - unsigned m_groupSize; - int m_hadExternalDoctype; - XML_Char m_namespaceSeparator; -} Parser; - -#define userData (((Parser *)parser)->m_userData) -#define handlerArg (((Parser *)parser)->m_handlerArg) -#define startElementHandler (((Parser *)parser)->m_startElementHandler) -#define endElementHandler (((Parser *)parser)->m_endElementHandler) -#define characterDataHandler (((Parser *)parser)->m_characterDataHandler) -#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) -#define commentHandler (((Parser *)parser)->m_commentHandler) -#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) -#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) -#define defaultHandler (((Parser *)parser)->m_defaultHandler) -#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) -#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) -#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) -#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) -#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) -#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) -#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) -#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) -#define encoding (((Parser *)parser)->m_encoding) -#define initEncoding (((Parser *)parser)->m_initEncoding) -#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) -#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) -#define unknownEncodingHandlerData \ - (((Parser *)parser)->m_unknownEncodingHandlerData) -#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) -#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) -#define ns (((Parser *)parser)->m_ns) -#define prologState (((Parser *)parser)->m_prologState) -#define processor (((Parser *)parser)->m_processor) -#define errorCode (((Parser *)parser)->m_errorCode) -#define eventPtr (((Parser *)parser)->m_eventPtr) -#define eventEndPtr (((Parser *)parser)->m_eventEndPtr) -#define positionPtr (((Parser *)parser)->m_positionPtr) -#define position (((Parser *)parser)->m_position) -#define openInternalEntities (((Parser *)parser)->m_openInternalEntities) -#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) -#define tagLevel (((Parser *)parser)->m_tagLevel) -#define buffer (((Parser *)parser)->m_buffer) -#define bufferPtr (((Parser *)parser)->m_bufferPtr) -#define bufferEnd (((Parser *)parser)->m_bufferEnd) -#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) -#define parseEndPtr (((Parser *)parser)->m_parseEndPtr) -#define bufferLim (((Parser *)parser)->m_bufferLim) -#define dataBuf (((Parser *)parser)->m_dataBuf) -#define dataBufEnd (((Parser *)parser)->m_dataBufEnd) -#define dtd (((Parser *)parser)->m_dtd) -#define declEntity (((Parser *)parser)->m_declEntity) -#define declNotationName (((Parser *)parser)->m_declNotationName) -#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) -#define declElementType (((Parser *)parser)->m_declElementType) -#define declAttributeId (((Parser *)parser)->m_declAttributeId) -#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) -#define freeTagList (((Parser *)parser)->m_freeTagList) -#define freeBindingList (((Parser *)parser)->m_freeBindingList) -#define inheritedBindings (((Parser *)parser)->m_inheritedBindings) -#define tagStack (((Parser *)parser)->m_tagStack) -#define atts (((Parser *)parser)->m_atts) -#define attsSize (((Parser *)parser)->m_attsSize) -#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) -#define tempPool (((Parser *)parser)->m_tempPool) -#define temp2Pool (((Parser *)parser)->m_temp2Pool) -#define groupConnector (((Parser *)parser)->m_groupConnector) -#define groupSize (((Parser *)parser)->m_groupSize) -#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) -#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) - -#ifdef _MSC_VER -#ifdef _DEBUG -Parser *asParser(XML_Parser parser) -{ - return parser; -} -#endif -#endif - -XML_Parser XML_ParserCreate(const XML_Char *encodingName) -{ - XML_Parser parser = malloc(sizeof(Parser)); - if (!parser) - return parser; - processor = prologInitProcessor; - XmlPrologStateInit(&prologState); - userData = 0; - handlerArg = 0; - startElementHandler = 0; - endElementHandler = 0; - characterDataHandler = 0; - processingInstructionHandler = 0; - commentHandler = 0; - startCdataSectionHandler = 0; - endCdataSectionHandler = 0; - defaultHandler = 0; - unparsedEntityDeclHandler = 0; - notationDeclHandler = 0; - startNamespaceDeclHandler = 0; - endNamespaceDeclHandler = 0; - notStandaloneHandler = 0; - externalEntityRefHandler = 0; - externalEntityRefHandlerArg = parser; - unknownEncodingHandler = 0; - buffer = 0; - bufferPtr = 0; - bufferEnd = 0; - parseEndByteIndex = 0; - parseEndPtr = 0; - bufferLim = 0; - declElementType = 0; - declAttributeId = 0; - declEntity = 0; - declNotationName = 0; - declNotationPublicId = 0; - memset(&position, 0, sizeof(POSITION)); - errorCode = XML_ERROR_NONE; - eventPtr = 0; - eventEndPtr = 0; - positionPtr = 0; - openInternalEntities = 0; - tagLevel = 0; - tagStack = 0; - freeTagList = 0; - freeBindingList = 0; - inheritedBindings = 0; - attsSize = INIT_ATTS_SIZE; - atts = malloc(attsSize * sizeof(ATTRIBUTE)); - nSpecifiedAtts = 0; - dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); - groupSize = 0; - groupConnector = 0; - hadExternalDoctype = 0; - unknownEncodingMem = 0; - unknownEncodingRelease = 0; - unknownEncodingData = 0; - unknownEncodingHandlerData = 0; - namespaceSeparator = '!'; - ns = 0; - poolInit(&tempPool); - poolInit(&temp2Pool); - protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0; - if (!dtdInit(&dtd) || !atts || !dataBuf - || (encodingName && !protocolEncodingName)) { - XML_ParserFree(parser); - return 0; - } - dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; - XmlInitEncoding(&initEncoding, &encoding, 0); - return parser; -} - -XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) -{ - static - const XML_Char implicitContext[] = { - XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='), - XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'), - XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'), - XML_T('.'), XML_T('w'), XML_T('3'), - XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'), - XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'), - XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'), - XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'), - XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'), - XML_T('\0') - }; - - XML_Parser parser = XML_ParserCreate(encodingName); - if (parser) { - XmlInitEncodingNS(&initEncoding, &encoding, 0); - ns = 1; - namespaceSeparator = nsSep; - } - if (!setContext(parser, implicitContext)) { - XML_ParserFree(parser); - return 0; - } - return parser; -} - -int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (!encodingName) - protocolEncodingName = 0; - else { - protocolEncodingName = poolCopyString(&tempPool, encodingName); - if (!protocolEncodingName) - return 0; - } - return 1; -} - -XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser, - const XML_Char *context, - const XML_Char *encodingName) -{ - XML_Parser parser = oldParser; - DTD *oldDtd = &dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; - - parser = (ns - ? XML_ParserCreateNS(encodingName, namespaceSeparator) - : XML_ParserCreate(encodingName)); - if (!parser) - return 0; - startElementHandler = oldStartElementHandler; - endElementHandler = oldEndElementHandler; - characterDataHandler = oldCharacterDataHandler; - processingInstructionHandler = oldProcessingInstructionHandler; - commentHandler = oldCommentHandler; - startCdataSectionHandler = oldStartCdataSectionHandler; - endCdataSectionHandler = oldEndCdataSectionHandler; - defaultHandler = oldDefaultHandler; - startNamespaceDeclHandler = oldStartNamespaceDeclHandler; - endNamespaceDeclHandler = oldEndNamespaceDeclHandler; - notStandaloneHandler = oldNotStandaloneHandler; - externalEntityRefHandler = oldExternalEntityRefHandler; - unknownEncodingHandler = oldUnknownEncodingHandler; - userData = oldUserData; - if (oldUserData == oldHandlerArg) - handlerArg = userData; - else - handlerArg = parser; - if (oldExternalEntityRefHandlerArg != oldParser) - externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; - defaultExpandInternalEntities = oldDefaultExpandInternalEntities; - if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) { - XML_ParserFree(parser); - return 0; - } - processor = externalEntityInitProcessor; - return parser; -} - -static -void destroyBindings(BINDING *bindings) -{ - for (;;) { - BINDING *b = bindings; - if (!b) - break; - bindings = b->nextTagBinding; - free(b->uri); - free(b); - } -} - -void XML_ParserFree(XML_Parser parser) -{ - for (;;) { - TAG *p; - if (tagStack == 0) { - if (freeTagList == 0) - break; - tagStack = freeTagList; - freeTagList = 0; - } - p = tagStack; - tagStack = tagStack->parent; - free(p->buf); - destroyBindings(p->bindings); - free(p); - } - destroyBindings(freeBindingList); - destroyBindings(inheritedBindings); - poolDestroy(&tempPool); - poolDestroy(&temp2Pool); - dtdDestroy(&dtd); - free((void *)atts); - free(groupConnector); - free(buffer); - free(dataBuf); - free(unknownEncodingMem); - if (unknownEncodingRelease) - unknownEncodingRelease(unknownEncodingData); - free(parser); -} - -void XML_UseParserAsHandlerArg(XML_Parser parser) -{ - handlerArg = parser; -} - -void XML_SetUserData(XML_Parser parser, void *p) -{ - if (handlerArg == userData) - handlerArg = userData = p; - else - userData = p; -} - -int XML_SetBase(XML_Parser parser, const XML_Char *p) -{ - if (p) { - p = poolCopyString(&dtd.pool, p); - if (!p) - return 0; - dtd.base = p; - } - else - dtd.base = 0; - return 1; -} - -const XML_Char *XML_GetBase(XML_Parser parser) -{ - return dtd.base; -} - -int XML_GetSpecifiedAttributeCount(XML_Parser parser) -{ - return nSpecifiedAtts; -} - -void XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end) -{ - startElementHandler = start; - endElementHandler = end; -} - -void XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler) -{ - characterDataHandler = handler; -} - -void XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler) -{ - processingInstructionHandler = handler; -} - -void XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler) -{ - commentHandler = handler; -} - -void XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end) -{ - startCdataSectionHandler = start; - endCdataSectionHandler = end; -} - -void XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler) -{ - defaultHandler = handler; - defaultExpandInternalEntities = 0; -} - -void XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler) -{ - defaultHandler = handler; - defaultExpandInternalEntities = 1; -} - -void XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler) -{ - unparsedEntityDeclHandler = handler; -} - -void XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler) -{ - notationDeclHandler = handler; -} - -void XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end) -{ - startNamespaceDeclHandler = start; - endNamespaceDeclHandler = end; -} - -void XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler) -{ - notStandaloneHandler = handler; -} - -void XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler) -{ - externalEntityRefHandler = handler; -} - -void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) -{ - if (arg) - externalEntityRefHandlerArg = arg; - else - externalEntityRefHandlerArg = parser; -} - -void XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *data) -{ - unknownEncodingHandler = handler; - unknownEncodingHandlerData = data; -} - -int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) -{ - if (len == 0) { - if (!isFinal) - return 1; - positionPtr = bufferPtr; - errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - else if (bufferPtr == bufferEnd) { - const char *end; - int nLeftOver; - parseEndByteIndex += len; - positionPtr = s; - if (isFinal) { - errorCode = processor(parser, s, parseEndPtr = s + len, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - errorCode = processor(parser, s, parseEndPtr = s + len, &end); - if (errorCode != XML_ERROR_NONE) { - eventEndPtr = eventPtr; - return 0; - } - XmlUpdatePosition(encoding, positionPtr, end, &position); - nLeftOver = s + len - end; - if (nLeftOver) { - if (buffer == 0 || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2); - if (!buffer) { - errorCode = XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = 0; - return 0; - } - bufferLim = buffer + len * 2; - } - memcpy(buffer, end, nLeftOver); - bufferPtr = buffer; - bufferEnd = buffer + nLeftOver; - } - return 1; - } - else { - memcpy(XML_GetBuffer(parser, len), s, len); - return XML_ParseBuffer(parser, len, isFinal); - } -} - -int XML_ParseBuffer(XML_Parser parser, int len, int isFinal) -{ - const char *start = bufferPtr; - positionPtr = start; - bufferEnd += len; - parseEndByteIndex += len; - errorCode = processor(parser, start, parseEndPtr = bufferEnd, - isFinal ? (const char **)0 : &bufferPtr); - if (errorCode == XML_ERROR_NONE) { - if (!isFinal) - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - return 1; - } - else { - eventEndPtr = eventPtr; - return 0; - } -} - -void *XML_GetBuffer(XML_Parser parser, int len) -{ - if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ - int neededSize = len + (bufferEnd - bufferPtr); - if (neededSize <= bufferLim - buffer) { - memmove(buffer, bufferPtr, bufferEnd - bufferPtr); - bufferEnd = buffer + (bufferEnd - bufferPtr); - bufferPtr = buffer; - } - else { - char *newBuf; - int bufferSize = bufferLim - bufferPtr; - if (bufferSize == 0) - bufferSize = INIT_BUFFER_SIZE; - do { - bufferSize *= 2; - } while (bufferSize < neededSize); - newBuf = malloc(bufferSize); - if (newBuf == 0) { - errorCode = XML_ERROR_NO_MEMORY; - return 0; - } - bufferLim = newBuf + bufferSize; - if (bufferPtr) { - memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); - free(buffer); - } - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; - } - } - return bufferEnd; -} - -enum XML_Error XML_GetErrorCode(XML_Parser parser) -{ - return errorCode; -} - -long XML_GetCurrentByteIndex(XML_Parser parser) -{ - if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); - return -1; -} - -int XML_GetCurrentByteCount(XML_Parser parser) -{ - if (eventEndPtr && eventPtr) - return eventEndPtr - eventPtr; - return 0; -} - -int XML_GetCurrentLineNumber(XML_Parser parser) -{ - if (eventPtr) { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.lineNumber + 1; -} - -int XML_GetCurrentColumnNumber(XML_Parser parser) -{ - if (eventPtr) { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.columnNumber; -} - -void XML_DefaultCurrent(XML_Parser parser) -{ - if (defaultHandler) { - if (openInternalEntities) - reportDefault(parser, - ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(), - openInternalEntities->internalEventPtr, - openInternalEntities->internalEventEndPtr); - else - reportDefault(parser, encoding, eventPtr, eventEndPtr); - } -} - -const XML_LChar *XML_ErrorString(int code) -{ - static const XML_LChar *message[] = { - 0, - XML_T("out of memory"), - XML_T("syntax error"), - XML_T("no element found"), - XML_T("not well-formed"), - XML_T("unclosed token"), - XML_T("unclosed token"), - XML_T("mismatched tag"), - XML_T("duplicate attribute"), - XML_T("junk after document element"), - XML_T("illegal parameter entity reference"), - XML_T("undefined entity"), - XML_T("recursive entity reference"), - XML_T("asynchronous entity"), - XML_T("reference to invalid character number"), - XML_T("reference to binary entity"), - XML_T("reference to external entity in attribute"), - XML_T("xml processing instruction not at start of external entity"), - XML_T("unknown encoding"), - XML_T("encoding specified in XML declaration is incorrect"), - XML_T("unclosed CDATA section"), - XML_T("error in processing external entity reference"), - XML_T("document is not standalone") - }; - if (code > 0 && code < (int)(sizeof(message)/sizeof(message[0]))) - return message[code]; - return 0; -} - -static -enum XML_Error contentProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - return doContent(parser, 0, encoding, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = externalEntityInitProcessor2; - return externalEntityInitProcessor2(parser, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor2(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - const char *next; - int tok = XmlContentTok(encoding, start, end, &next); - switch (tok) { - case XML_TOK_BOM: - start = next; - break; - case XML_TOK_PARTIAL: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_PARTIAL_CHAR; - } - processor = externalEntityInitProcessor3; - return externalEntityInitProcessor3(parser, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor3(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - const char *next; - int tok = XmlContentTok(encoding, start, end, &next); - switch (tok) { - case XML_TOK_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 1, start, next); - if (result != XML_ERROR_NONE) - return result; - start = next; - } - break; - case XML_TOK_PARTIAL: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_PARTIAL_CHAR; - } - processor = externalEntityContentProcessor; - tagLevel = 1; - return doContent(parser, 1, encoding, start, end, endPtr); -} - -static -enum XML_Error externalEntityContentProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - return doContent(parser, 1, encoding, start, end, endPtr); -} - -static enum XML_Error -doContent(XML_Parser parser, - int startTagLevel, - const ENCODING *enc, - const char *s, - const char *end, - const char **nextPtr) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - for (;;) { - const char *next = s; /* XmlContentTok doesn't always set the last arg */ - int tok = XmlContentTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - *eventEndPP = end; - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) - return XML_ERROR_NO_ELEMENTS; - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (startTagLevel > 0) { - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - } - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (characterDataHandler) - characterDataHandler(handlerArg, &ch, 1); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - name = poolStoreString(&dtd.pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&dtd.pool); - if (!entity) { - if (dtd.complete || dtd.standalone) - return XML_ERROR_UNDEFINED_ENTITY; - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - if (entity->open) - return XML_ERROR_RECURSIVE_ENTITY_REF; - if (entity->notation) - return XML_ERROR_BINARY_ENTITY_REF; - if (entity) { - if (entity->textPtr) { - enum XML_Error result; - OPEN_INTERNAL_ENTITY openEntity; - if (defaultHandler && !defaultExpandInternalEntities) { - reportDefault(parser, enc, s, next); - break; - } - entity->open = 1; - openEntity.next = openInternalEntities; - openInternalEntities = &openEntity; - openEntity.entity = entity; - openEntity.internalEventPtr = 0; - openEntity.internalEventEndPtr = 0; - result = doContent(parser, - tagLevel, - internalEnc, - (char *)entity->textPtr, - (char *)(entity->textPtr + entity->textLen), - 0); - entity->open = 0; - openInternalEntities = openEntity.next; - if (result) - return result; - } - else if (externalEntityRefHandler) { - const XML_Char *context; - entity->open = 1; - context = getContext(parser); - entity->open = 0; - if (!context) - return XML_ERROR_NO_MEMORY; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - context, - dtd.base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - poolDiscard(&tempPool); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_START_TAG_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_START_TAG_NO_ATTS: - { - TAG *tag; - if (freeTagList) { - tag = freeTagList; - freeTagList = freeTagList->parent; - } - else { - tag = malloc(sizeof(TAG)); - if (!tag) - return XML_ERROR_NO_MEMORY; - tag->buf = malloc(INIT_TAG_BUF_SIZE); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; - } - tag->bindings = 0; - tag->parent = tagStack; - tagStack = tag; - tag->name.localPart = 0; - tag->rawName = s + enc->minBytesPerChar; - tag->rawNameLength = XmlNameLength(enc, tag->rawName); - if (nextPtr) { - /* Need to guarantee that: - tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */ - if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { - int bufSize = tag->rawNameLength * 4; - bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - } - memcpy(tag->buf, tag->rawName, tag->rawNameLength); - tag->rawName = tag->buf; - } - ++tagLevel; - if (startElementHandler) { - enum XML_Error result; - XML_Char *toPtr; - for (;;) { - const char *rawNameEnd = tag->rawName + tag->rawNameLength; - const char *fromPtr = tag->rawName; - int bufSize; - if (nextPtr) - toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char))); - else - toPtr = (XML_Char *)tag->buf; - tag->name.str = toPtr; - XmlConvert(enc, - &fromPtr, rawNameEnd, - (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - if (fromPtr == rawNameEnd) - break; - bufSize = (tag->bufEnd - tag->buf) << 1; - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - if (nextPtr) - tag->rawName = tag->buf; - } - *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); - if (result) - return result; - startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); - poolClear(&tempPool); - } - else { - tag->name.str = 0; - if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_EMPTY_ELEMENT_NO_ATTS: - if (startElementHandler || endElementHandler) { - const char *rawName = s + enc->minBytesPerChar; - enum XML_Error result; - BINDING *bindings = 0; - TAG_NAME name; - name.str = poolStoreString(&tempPool, enc, rawName, - rawName + XmlNameLength(enc, rawName)); - if (!name.str) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); - if (result) - return result; - poolFinish(&tempPool); - if (startElementHandler) - startElementHandler(handlerArg, name.str, (const XML_Char **)atts); - if (endElementHandler) { - if (startElementHandler) - *eventPP = *eventEndPP; - endElementHandler(handlerArg, name.str); - } - poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - break; - case XML_TOK_END_TAG: - if (tagLevel == startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - else { - int len; - const char *rawName; - TAG *tag = tagStack; - tagStack = tag->parent; - tag->parent = freeTagList; - freeTagList = tag; - rawName = s + enc->minBytesPerChar*2; - len = XmlNameLength(enc, rawName); - if (len != tag->rawNameLength - || memcmp(tag->rawName, rawName, len) != 0) { - *eventPP = rawName; - return XML_ERROR_TAG_MISMATCH; - } - --tagLevel; - if (endElementHandler && tag->name.str) { - if (tag->name.localPart) { - XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen; - const XML_Char *from = tag->name.localPart; - while ((*to++ = *from++) != 0) - ; - } - endElementHandler(handlerArg, tag->name.str); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - while (tag->bindings) { - BINDING *b = tag->bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - tag->bindings = tag->bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - } - break; - case XML_TOK_CHAR_REF: - { - int n = XmlCharRefNumber(enc, s); - if (n < 0) - return XML_ERROR_BAD_CHAR_REF; - if (characterDataHandler) { - XML_Char buf[XML_ENCODE_MAX]; - characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_CDATA_SECT_OPEN: - { - enum XML_Error result; - if (startCdataSectionHandler) - startCdataSectionHandler(handlerArg); -#if 0 - /* Suppose you doing a transformation on a document that involves - changing only the character data. You set up a defaultHandler - and a characterDataHandler. The defaultHandler simply copies - characters through. The characterDataHandler does the transformation - and writes the characters out escaping them as necessary. This case - will fail to work if we leave out the following two lines (because & - and < inside CDATA sections will be incorrectly escaped). - - However, now we have a start/endCdataSectionHandler, so it seems - easier to let the user deal with this. */ - - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr); - if (!next) { - processor = cdataSectionProcessor; - return result; - } - } - break; - case XML_TOK_TRAILING_RSQB: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)end - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) { - *eventPP = end; - return XML_ERROR_NO_ELEMENTS; - } - if (tagLevel != startTagLevel) { - *eventPP = end; - return XML_ERROR_ASYNC_ENTITY; - } - return XML_ERROR_NONE; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - default: - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - *eventPP = s = next; - } - /* not reached */ -} - -/* If tagNamePtr is non-null, build a real list of attributes, -otherwise just check the attributes for well-formedness. */ - -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, - const char *s, TAG_NAME *tagNamePtr, - BINDING **bindingsPtr) -{ - ELEMENT_TYPE *elementType = 0; - int nDefaultAtts = 0; - const XML_Char **appAtts; - int attIndex = 0; - int i; - int n; - int nPrefixes = 0; - BINDING *binding; - const XML_Char *localPart; - - if (tagNamePtr) { - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0); - if (!elementType) { - tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); - if (!tagNamePtr->str) - return XML_ERROR_NO_MEMORY; - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); - if (!elementType) - return XML_ERROR_NO_MEMORY; - if (ns && !setElementTypePrefix(parser, elementType)) - return XML_ERROR_NO_MEMORY; - } - nDefaultAtts = elementType->nDefaultAtts; - } - n = XmlGetAttributes(enc, s, attsSize, atts); - if (n + nDefaultAtts > attsSize) { - int oldAttsSize = attsSize; - attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE)); - if (!atts) - return XML_ERROR_NO_MEMORY; - if (n > oldAttsSize) - XmlGetAttributes(enc, s, n, atts); - } - appAtts = (const XML_Char **)atts; - for (i = 0; i < n; i++) { - ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, - atts[i].name - + XmlNameLength(enc, atts[i].name)); - if (!attId) - return XML_ERROR_NO_MEMORY; - if ((attId->name)[-1]) { - if (enc == encoding) - eventPtr = atts[i].name; - return XML_ERROR_DUPLICATE_ATTRIBUTE; - } - (attId->name)[-1] = 1; - appAtts[attIndex++] = attId->name; - if (!atts[i].normalized) { - enum XML_Error result; - int isCdata = 1; - - if (attId->maybeTokenized) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - if (attId == elementType->defaultAtts[j].id) { - isCdata = elementType->defaultAtts[j].isCdata; - break; - } - } - } - - result = storeAttributeValue(parser, enc, isCdata, - atts[i].valuePtr, atts[i].valueEnd, - &tempPool); - if (result) - return result; - if (tagNamePtr) { - appAtts[attIndex] = poolStart(&tempPool); - poolFinish(&tempPool); - } - else - poolDiscard(&tempPool); - } - else if (tagNamePtr) { - appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); - if (appAtts[attIndex] == 0) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - if (attId->prefix && tagNamePtr) { - if (attId->xmlns) { - if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr)) - return XML_ERROR_NO_MEMORY; - --attIndex; - } - else { - attIndex++; - nPrefixes++; - (attId->name)[-1] = 2; - } - } - else - attIndex++; - } - nSpecifiedAtts = attIndex; - if (tagNamePtr) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; - if (!(da->id->name)[-1] && da->value) { - if (da->id->prefix) { - if (da->id->xmlns) { - if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr)) - return XML_ERROR_NO_MEMORY; - } - else { - (da->id->name)[-1] = 2; - nPrefixes++; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - else { - (da->id->name)[-1] = 1; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - } - appAtts[attIndex] = 0; - } - i = 0; - if (nPrefixes) { - for (; i < attIndex; i += 2) { - if (appAtts[i][-1] == 2) { - ATTRIBUTE_ID *id; - ((XML_Char *)(appAtts[i]))[-1] = 0; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); - if (id->prefix->binding) { - int j; - const BINDING *b = id->prefix->binding; - const XML_Char *s = appAtts[i]; - for (j = 0; j < b->uriLen; j++) { - if (!poolAppendChar(&tempPool, b->uri[j])) - return XML_ERROR_NO_MEMORY; - } - while (*s++ != ':') - ; - do { - if (!poolAppendChar(&tempPool, *s)) - return XML_ERROR_NO_MEMORY; - } while (*s++); - appAtts[i] = poolStart(&tempPool); - poolFinish(&tempPool); - } - if (!--nPrefixes) - break; - } - else - ((XML_Char *)(appAtts[i]))[-1] = 0; - } - } - for (; i < attIndex; i += 2) - ((XML_Char *)(appAtts[i]))[-1] = 0; - if (!tagNamePtr) - return XML_ERROR_NONE; - for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) - binding->attId->name[-1] = 0; - if (elementType->prefix) { - binding = elementType->prefix->binding; - if (!binding) - return XML_ERROR_NONE; - localPart = tagNamePtr->str; - while (*localPart++ != XML_T(':')) - ; - } - else if (dtd.defaultPrefix.binding) { - binding = dtd.defaultPrefix.binding; - localPart = tagNamePtr->str; - } - else - return XML_ERROR_NONE; - tagNamePtr->localPart = localPart; - tagNamePtr->uriLen = binding->uriLen; - i = binding->uriLen; - do { - if (i == binding->uriAlloc) { - binding->uri = realloc(binding->uri, binding->uriAlloc *= 2); - if (!binding->uri) - return XML_ERROR_NO_MEMORY; - } - binding->uri[i++] = *localPart; - } while (*localPart++); - tagNamePtr->str = binding->uri; - return XML_ERROR_NONE; -} - -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) -{ - BINDING *b; - int len; - for (len = 0; uri[len]; len++) - ; - if (namespaceSeparator) - len++; - if (freeBindingList) { - b = freeBindingList; - if (len > b->uriAlloc) { - b->uri = realloc(b->uri, len + EXPAND_SPARE); - if (!b->uri) - return 0; - b->uriAlloc = len + EXPAND_SPARE; - } - freeBindingList = b->nextTagBinding; - } - else { - b = malloc(sizeof(BINDING)); - if (!b) - return 0; - b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE); - if (!b->uri) { - free(b); - return 0; - } - b->uriAlloc = len; - } - b->uriLen = len; - memcpy(b->uri, uri, len * sizeof(XML_Char)); - if (namespaceSeparator) - b->uri[len - 1] = namespaceSeparator; - b->prefix = prefix; - b->attId = attId; - b->prevPrefixBinding = prefix->binding; - if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) - prefix->binding = 0; - else - prefix->binding = b; - b->nextTagBinding = *bindingsPtr; - *bindingsPtr = b; - if (startNamespaceDeclHandler) - startNamespaceDeclHandler(handlerArg, prefix->name, - prefix->binding ? uri : 0); - return 1; -} - -/* The idea here is to avoid using stack for each CDATA section when -the whole file is parsed with one call. */ - -static -enum XML_Error cdataSectionProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); - if (start) { - processor = contentProcessor; - return contentProcessor(parser, start, end, endPtr); - } - return result; -} - -/* startPtr gets set to non-null is the section is closed, and to null if -the section is not yet closed. */ - -static -enum XML_Error doCdataSection(XML_Parser parser, - const ENCODING *enc, - const char **startPtr, - const char *end, - const char **nextPtr) -{ - const char *s = *startPtr; - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - *eventPP = s; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - *startPtr = 0; - for (;;) { - const char *next; - int tok = XmlCdataSectionTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_CDATA_SECT_CLOSE: - if (endCdataSectionHandler) - endCdataSectionHandler(handlerArg); -#if 0 - /* see comment under XML_TOK_CDATA_SECT_OPEN */ - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - *startPtr = next; - return XML_ERROR_NONE; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = next; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_PARTIAL: - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_CDATA_SECTION; - default: - abort(); - } - *eventPP = s = next; - } - /* not reached */ -} - -static enum XML_Error -initializeEncoding(XML_Parser parser) -{ - const char *s; -#ifdef XML_UNICODE - char encodingBuf[128]; - if (!protocolEncodingName) - s = 0; - else { - int i; - for (i = 0; protocolEncodingName[i]; i++) { - if (i == sizeof(encodingBuf) - 1 - || protocolEncodingName[i] >= 0x80 - || protocolEncodingName[i] < 0) { - encodingBuf[0] = '\0'; - break; - } - encodingBuf[i] = (char)protocolEncodingName[i]; - } - encodingBuf[i] = '\0'; - s = encodingBuf; - } -#else -s = protocolEncodingName; -#endif - if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) - return XML_ERROR_NONE; - return handleUnknownEncoding(parser, protocolEncodingName); -} - -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, - const char *s, const char *next) -{ - const char *encodingName = 0; - const ENCODING *newEncoding = 0; - const char *version; - int standalone = -1; - if (!(ns - ? XmlParseXmlDeclNS - : XmlParseXmlDecl)(isGeneralTextEntity, - encoding, - s, - next, - &eventPtr, - &version, - &encodingName, - &newEncoding, - &standalone)) - return XML_ERROR_SYNTAX; - if (!isGeneralTextEntity && standalone == 1) - dtd.standalone = 1; - if (defaultHandler) - reportDefault(parser, encoding, s, next); - if (!protocolEncodingName) { - if (newEncoding) { - if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { - eventPtr = encodingName; - return XML_ERROR_INCORRECT_ENCODING; - } - encoding = newEncoding; - } - else if (encodingName) { - enum XML_Error result; - const XML_Char *s = poolStoreString(&tempPool, - encoding, - encodingName, - encodingName - + XmlNameLength(encoding, encodingName)); - if (!s) - return XML_ERROR_NO_MEMORY; - result = handleUnknownEncoding(parser, s); - poolDiscard(&tempPool); - if (result == XML_ERROR_UNKNOWN_ENCODING) - eventPtr = encodingName; - return result; - } - } - return XML_ERROR_NONE; -} - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (unknownEncodingHandler) { - XML_Encoding info; - int i; - for (i = 0; i < 256; i++) - info.map[i] = -1; - info.convert = 0; - info.data = 0; - info.release = 0; - if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { - ENCODING *enc; - unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding()); - if (!unknownEncodingMem) { - if (info.release) - info.release(info.data); - return XML_ERROR_NO_MEMORY; - } - enc = (ns - ? XmlInitUnknownEncodingNS - : XmlInitUnknownEncoding)(unknownEncodingMem, - info.map, - info.convert, - info.data); - if (enc) { - unknownEncodingData = info.data; - unknownEncodingRelease = info.release; - encoding = enc; - return XML_ERROR_NONE; - } - } - if (info.release) - info.release(info.data); - } - return XML_ERROR_UNKNOWN_ENCODING; -} - -static enum XML_Error -prologInitProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = prologProcessor; - return prologProcessor(parser, s, end, nextPtr); -} - -static enum XML_Error -prologProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) { - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_NONE: - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_TRAILING_CR: - eventPtr = s + encoding->minBytesPerChar; - return XML_ERROR_NO_ELEMENTS; - default: - abort(); - } - } - switch (XmlTokenRole(&prologState, tok, s, next, encoding)) { - case XML_ROLE_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 0, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_DOCTYPE_SYSTEM_ID: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - hadExternalDoctype = 1; - break; - case XML_ROLE_DOCTYPE_PUBLIC_ID: - case XML_ROLE_ENTITY_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declEntity) { - XML_Char *tem = poolStoreString(&dtd.pool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declEntity->publicId = tem; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_INSTANCE_START: - processor = contentProcessor; - if (hadExternalDoctype) - dtd.complete = 0; - return contentProcessor(parser, s, end, nextPtr); - case XML_ROLE_ATTLIST_ELEMENT_NAME: - { - const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); - if (!declElementType) - return XML_ERROR_NO_MEMORY; - if (declElementType->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!setElementTypePrefix(parser, declElementType)) - return XML_ERROR_NO_MEMORY; - } - break; - } - case XML_ROLE_ATTRIBUTE_NAME: - declAttributeId = getAttributeId(parser, encoding, s, next); - if (!declAttributeId) - return XML_ERROR_NO_MEMORY; - declAttributeIsCdata = 0; - break; - case XML_ROLE_ATTRIBUTE_TYPE_CDATA: - declAttributeIsCdata = 1; - break; - case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: - case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0)) - return XML_ERROR_NO_MEMORY; - break; - case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: - case XML_ROLE_FIXED_ATTRIBUTE_VALUE: - { - const XML_Char *attVal; - enum XML_Error result - = storeAttributeValue(parser, encoding, declAttributeIsCdata, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar, - &dtd.pool); - if (result) - return result; - attVal = poolStart(&dtd.pool); - poolFinish(&dtd.pool); - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal)) - return XML_ERROR_NO_MEMORY; - break; - } - case XML_ROLE_ENTITY_VALUE: - { - enum XML_Error result = storeEntityValue(parser, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_ENTITY_SYSTEM_ID: - if (declEntity) { - declEntity->systemId = poolStoreString(&dtd.pool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!declEntity->systemId) - return XML_ERROR_NO_MEMORY; - declEntity->base = dtd.base; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_ENTITY_NOTATION_NAME: - if (declEntity) { - declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next); - if (!declEntity->notation) - return XML_ERROR_NO_MEMORY; - poolFinish(&dtd.pool); - if (unparsedEntityDeclHandler) { - eventPtr = eventEndPtr = s; - unparsedEntityDeclHandler(handlerArg, - declEntity->name, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - declEntity->notation); - } - - } - break; - case XML_ROLE_GENERAL_ENTITY_NAME: - { - const XML_Char *name; - if (XmlPredefinedEntityName(encoding, s, next)) { - declEntity = 0; - break; - } - name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - if (dtd.complete) { - declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - if (declEntity->name != name) { - poolDiscard(&dtd.pool); - declEntity = 0; - } - else - poolFinish(&dtd.pool); - } - else { - poolDiscard(&dtd.pool); - declEntity = 0; - } - } - break; - case XML_ROLE_PARAM_ENTITY_NAME: - declEntity = 0; - break; - case XML_ROLE_NOTATION_NAME: - declNotationPublicId = 0; - declNotationName = 0; - if (notationDeclHandler) { - declNotationName = poolStoreString(&tempPool, encoding, s, next); - if (!declNotationName) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declNotationName) { - XML_Char *tem = poolStoreString(&tempPool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declNotationPublicId = tem; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_SYSTEM_ID: - if (declNotationName && notationDeclHandler) { - const XML_Char *systemId - = poolStoreString(&tempPool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!systemId) - return XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - systemId, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_NOTATION_NO_SYSTEM_ID: - if (declNotationPublicId && notationDeclHandler) { - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - 0, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_ERROR: - eventPtr = s; - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - return XML_ERROR_PARAM_ENTITY_REF; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - default: - return XML_ERROR_SYNTAX; - } - case XML_ROLE_GROUP_OPEN: - if (prologState.level >= groupSize) { - if (groupSize) - groupConnector = realloc(groupConnector, groupSize *= 2); - else - groupConnector = malloc(groupSize = 32); - if (!groupConnector) - return XML_ERROR_NO_MEMORY; - } - groupConnector[prologState.level] = 0; - break; - case XML_ROLE_GROUP_SEQUENCE: - if (groupConnector[prologState.level] == '|') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = ','; - break; - case XML_ROLE_GROUP_CHOICE: - if (groupConnector[prologState.level] == ',') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = '|'; - break; - case XML_ROLE_PARAM_ENTITY_REF: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - dtd.complete = 0; - break; - case XML_ROLE_NONE: - switch (tok) { - case XML_TOK_PI: - eventPtr = s; - eventEndPtr = next; - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - eventPtr = s; - eventEndPtr = next; - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - } - break; - } - if (defaultHandler) { - switch (tok) { - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - case XML_TOK_XML_DECL: - break; - default: - eventPtr = s; - eventEndPtr = next; - reportDefault(parser, encoding, s, next); - } - } - s = next; - } - /* not reached */ -} - -static -enum XML_Error epilogProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - processor = epilogProcessor; - eventPtr = s; - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - eventEndPtr = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (defaultHandler) { - eventEndPtr = end; - reportDefault(parser, encoding, s, end); - } - /* fall through */ - case XML_TOK_NONE: - if (nextPtr) - *nextPtr = end; - return XML_ERROR_NONE; - case XML_TOK_PROLOG_S: - if (defaultHandler) - reportDefault(parser, encoding, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - default: - return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; - } - eventPtr = s = next; - } -} - -/* -static -enum XML_Error errorProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - return errorCode; -} -*/ - -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); - if (result) - return result; - if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) - poolChop(pool); - if (!poolAppendChar(pool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - return XML_ERROR_NONE; -} - -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - for (;;) { - const char *next; - int tok = XmlAttributeValueTok(enc, ptr, end, &next); - switch (tok) { - case XML_TOK_NONE: - return XML_ERROR_NONE; - case XML_TOK_INVALID: - if (enc == encoding) - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(enc, ptr); - if (n < 0) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - if (!isCdata - && n == 0x20 /* space */ - && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (!poolAppendChar(pool, buf[i])) - return XML_ERROR_NO_MEMORY; - } - } - break; - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, enc, ptr, next)) - return XML_ERROR_NO_MEMORY; - break; - break; - case XML_TOK_TRAILING_CR: - next = ptr + enc->minBytesPerChar; - /* fall through */ - case XML_TOK_ATTRIBUTE_VALUE_S: - case XML_TOK_DATA_NEWLINE: - if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - if (!poolAppendChar(pool, 0x20)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (!poolAppendChar(pool, ch)) - return XML_ERROR_NO_MEMORY; - break; - } - name = poolStoreString(&temp2Pool, enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&temp2Pool); - if (!entity) { - if (dtd.complete) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_UNDEFINED_ENTITY; - } - } - else if (entity->open) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_RECURSIVE_ENTITY_REF; - } - else if (entity->notation) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BINARY_ENTITY_REF; - } - else if (!entity->textPtr) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; - } - else { - enum XML_Error result; - const XML_Char *textEnd = entity->textPtr + entity->textLen; - entity->open = 1; - result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); - entity->open = 0; - if (result) - return result; - } - } - break; - default: - abort(); - } - ptr = next; - } - /* not reached */ -} - -static -enum XML_Error storeEntityValue(XML_Parser parser, - const char *entityTextPtr, - const char *entityTextEnd) -{ - /* const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); */ - STRING_POOL *pool = &(dtd.pool); - entityTextPtr += encoding->minBytesPerChar; - entityTextEnd -= encoding->minBytesPerChar; - for (;;) { - const char *next; - int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next); - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - eventPtr = entityTextPtr; - return XML_ERROR_SYNTAX; - case XML_TOK_NONE: - if (declEntity) { - declEntity->textPtr = pool->start; - declEntity->textLen = pool->ptr - pool->start; - poolFinish(pool); - } - else - poolDiscard(pool); - return XML_ERROR_NONE; - case XML_TOK_ENTITY_REF: - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, encoding, entityTextPtr, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_TRAILING_CR: - next = entityTextPtr + encoding->minBytesPerChar; - /* fall through */ - case XML_TOK_DATA_NEWLINE: - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = 0xA; - break; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(encoding, entityTextPtr); - if (n < 0) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = buf[i]; - } - } - break; - case XML_TOK_PARTIAL: - eventPtr = entityTextPtr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - default: - abort(); - } - entityTextPtr = next; - } - /* not reached */ -} - -static void -normalizeLines(XML_Char *s) -{ - XML_Char *p; - for (;; s++) { - if (*s == XML_T('\0')) - return; - if (*s == 0xD) - break; - } - p = s; - do { - if (*s == 0xD) { - *p++ = 0xA; - if (*++s == 0xA) - s++; - } - else - *p++ = *s++; - } while (*s); - *p = XML_T('\0'); -} - -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - const XML_Char *target; - XML_Char *data; - const char *tem; - if (!processingInstructionHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - start += enc->minBytesPerChar * 2; - tem = start + XmlNameLength(enc, start); - target = poolStoreString(&tempPool, enc, start, tem); - if (!target) - return 0; - poolFinish(&tempPool); - data = poolStoreString(&tempPool, enc, - XmlSkipS(enc, tem), - end - enc->minBytesPerChar*2); - if (!data) - return 0; - normalizeLines(data); - processingInstructionHandler(handlerArg, target, data); - poolClear(&tempPool); - return 1; -} - -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - XML_Char *data; - if (!commentHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - data = poolStoreString(&tempPool, - enc, - start + enc->minBytesPerChar * 4, - end - enc->minBytesPerChar * 3); - if (!data) - return 0; - normalizeLines(data); - commentHandler(handlerArg, data); - poolClear(&tempPool); - return 1; -} - -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) -{ - if (MUST_CONVERT(enc, s)) { - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - do { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - *eventPP = s; - } while (s != end); - } - else - defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); -} - - -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value) -{ - DEFAULT_ATTRIBUTE *att; - if (type->nDefaultAtts == type->allocDefaultAtts) { - if (type->allocDefaultAtts == 0) { - type->allocDefaultAtts = 8; - type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - else { - type->allocDefaultAtts *= 2; - type->defaultAtts = realloc(type->defaultAtts, - type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - if (!type->defaultAtts) - return 0; - } - att = type->defaultAtts + type->nDefaultAtts; - att->id = attId; - att->value = value; - att->isCdata = isCdata; - if (!isCdata) - attId->maybeTokenized = 1; - type->nDefaultAtts += 1; - return 1; -} - -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) -{ - const XML_Char *name; - for (name = elementType->name; *name; name++) { - if (*name == XML_T(':')) { - PREFIX *prefix; - const XML_Char *s; - for (s = elementType->name; s != name; s++) { - if (!poolAppendChar(&dtd.pool, *s)) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - elementType->prefix = prefix; - - } - } - return 1; -} - -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - ATTRIBUTE_ID *id; - const XML_Char *name; - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - name = poolStoreString(&dtd.pool, enc, start, end); - if (!name) - return 0; - ++name; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); - if (!id) - return 0; - if (id->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!ns) - ; - else if (name[0] == 'x' - && name[1] == 'm' - && name[2] == 'l' - && name[3] == 'n' - && name[4] == 's' - && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { - if (name[5] == '\0') - id->prefix = &dtd.defaultPrefix; - else - id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); - id->xmlns = 1; - } - else { - int i; - for (i = 0; name[i]; i++) { - if (name[i] == XML_T(':')) { - int j; - for (j = 0; j < i; j++) { - if (!poolAppendChar(&dtd.pool, name[j])) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (id->prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - break; - } - } - } - } - return id; -} - -#define CONTEXT_SEP XML_T('\f') - -static -const XML_Char *getContext(XML_Parser parser) -{ - HASH_TABLE_ITER iter; - int needSep = 0; - - if (dtd.defaultPrefix.binding) { - int i; - int len; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = dtd.defaultPrefix.binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) - return 0; - needSep = 1; - } - - hashTableIterInit(&iter, &(dtd.prefixes)); - for (;;) { - int i; - int len; - const XML_Char *s; - PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); - if (!prefix) - break; - if (!prefix->binding) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = prefix->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = prefix->binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) - return 0; - needSep = 1; - } - - - hashTableIterInit(&iter, &(dtd.generalEntities)); - for (;;) { - const XML_Char *s; - ENTITY *e = (ENTITY *)hashTableIterNext(&iter); - if (!e) - break; - if (!e->open) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = e->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - needSep = 1; - } - - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - return tempPool.start; -} - -static -int setContext(XML_Parser parser, const XML_Char *context) -{ - const XML_Char *s = context; - - while (*context != XML_T('\0')) { - if (*s == CONTEXT_SEP || *s == XML_T('\0')) { - ENTITY *e; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0); - if (e) - e->open = 1; - if (*s != XML_T('\0')) - s++; - context = s; - poolDiscard(&tempPool); - } - else if (*s == '=') { - PREFIX *prefix; - if (poolLength(&tempPool) == 0) - prefix = &dtd.defaultPrefix; - else { - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&tempPool)) - poolFinish(&tempPool); - else - poolDiscard(&tempPool); - } - for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) - if (!poolAppendChar(&tempPool, *context)) - return 0; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings)) - return 0; - poolDiscard(&tempPool); - if (*context != XML_T('\0')) - ++context; - s = context; - } - else { - if (!poolAppendChar(&tempPool, *s)) - return 0; - s++; - } - } - return 1; -} - - -static -void normalizePublicId(XML_Char *publicId) -{ - XML_Char *p = publicId; - XML_Char *s; - for (s = publicId; *s; s++) { - switch (*s) { - case 0x20: - case 0xD: - case 0xA: - if (p != publicId && p[-1] != 0x20) - *p++ = 0x20; - break; - default: - *p++ = *s; - } - } - if (p != publicId && p[-1] == 0x20) - --p; - *p = XML_T('\0'); -} - -static int dtdInit(DTD *p) -{ - poolInit(&(p->pool)); - hashTableInit(&(p->generalEntities)); - hashTableInit(&(p->elementTypes)); - hashTableInit(&(p->attributeIds)); - hashTableInit(&(p->prefixes)); - p->complete = 1; - p->standalone = 0; - p->base = 0; - p->defaultPrefix.name = 0; - p->defaultPrefix.binding = 0; - return 1; -} - -static void dtdDestroy(DTD *p) -{ - HASH_TABLE_ITER iter; - hashTableIterInit(&iter, &(p->elementTypes)); - for (;;) { - ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!e) - break; - if (e->allocDefaultAtts != 0) - free(e->defaultAtts); - } - hashTableDestroy(&(p->generalEntities)); - hashTableDestroy(&(p->elementTypes)); - hashTableDestroy(&(p->attributeIds)); - hashTableDestroy(&(p->prefixes)); - poolDestroy(&(p->pool)); -} - -/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise. -The new DTD has already been initialized. */ - -static int dtdCopy(DTD *newDtd, const DTD *oldDtd) -{ - HASH_TABLE_ITER iter; - - if (oldDtd->base) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldDtd->base); - if (!tem) - return 0; - newDtd->base = tem; - } - - /* Copy the prefix table. */ - - hashTableIterInit(&iter, &(oldDtd->prefixes)); - for (;;) { - const XML_Char *name; - const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); - if (!oldP) - break; - name = poolCopyString(&(newDtd->pool), oldP->name); - if (!name) - return 0; - if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) - return 0; - } - - hashTableIterInit(&iter, &(oldDtd->attributeIds)); - - /* Copy the attribute id table. */ - - for (;;) { - ATTRIBUTE_ID *newA; - const XML_Char *name; - const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); - - if (!oldA) - break; - /* Remember to allocate the scratch byte before the name. */ - if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) - return 0; - name = poolCopyString(&(newDtd->pool), oldA->name); - if (!name) - return 0; - ++name; - newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); - if (!newA) - return 0; - newA->maybeTokenized = oldA->maybeTokenized; - if (oldA->prefix) { - newA->xmlns = oldA->xmlns; - if (oldA->prefix == &oldDtd->defaultPrefix) - newA->prefix = &newDtd->defaultPrefix; - else - newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0); - } - } - - /* Copy the element type table. */ - - hashTableIterInit(&iter, &(oldDtd->elementTypes)); - - for (;;) { - int i; - ELEMENT_TYPE *newE; - const XML_Char *name; - const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(&(newDtd->pool), oldE->name); - if (!name) - return 0; - newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); - if (!newE) - return 0; - if (oldE->nDefaultAtts) { - newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); - if (!newE->defaultAtts) - return 0; - } - newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; - if (oldE->prefix) - newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0); - for (i = 0; i < newE->nDefaultAtts; i++) { - newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); - newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; - if (oldE->defaultAtts[i].value) { - newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); - if (!newE->defaultAtts[i].value) - return 0; - } - else - newE->defaultAtts[i].value = 0; - } - } - - /* Copy the entity table. */ - - hashTableIterInit(&iter, &(oldDtd->generalEntities)); - - for (;;) { - ENTITY *newE; - const XML_Char *name; - const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(&(newDtd->pool), oldE->name); - if (!name) - return 0; - newE = (ENTITY *)lookup(&(newDtd->generalEntities), name, sizeof(ENTITY)); - if (!newE) - return 0; - if (oldE->systemId) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->systemId); - if (!tem) - return 0; - newE->systemId = tem; - if (oldE->base) { - if (oldE->base == oldDtd->base) - newE->base = newDtd->base; - tem = poolCopyString(&(newDtd->pool), oldE->base); - if (!tem) - return 0; - newE->base = tem; - } - } - else { - const XML_Char *tem = poolCopyStringN(&(newDtd->pool), oldE->textPtr, oldE->textLen); - if (!tem) - return 0; - newE->textPtr = tem; - newE->textLen = oldE->textLen; - } - if (oldE->notation) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->notation); - if (!tem) - return 0; - newE->notation = tem; - } - } - - newDtd->complete = oldDtd->complete; - newDtd->standalone = oldDtd->standalone; - return 1; -} - -static -void poolInit(STRING_POOL *pool) -{ - pool->blocks = 0; - pool->freeBlocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolClear(STRING_POOL *pool) -{ - if (!pool->freeBlocks) - pool->freeBlocks = pool->blocks; - else { - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - p->next = pool->freeBlocks; - pool->freeBlocks = p; - p = tem; - } - } - pool->blocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolDestroy(STRING_POOL *pool) -{ - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - free(p); - p = tem; - } - pool->blocks = 0; - p = pool->freeBlocks; - while (p) { - BLOCK *tem = p->next; - free(p); - p = tem; - } - pool->freeBlocks = 0; - pool->ptr = 0; - pool->start = 0; - pool->end = 0; -} - -static -XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!pool->ptr && !poolGrow(pool)) - return 0; - for (;;) { - XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); - if (ptr == end) - break; - if (!poolGrow(pool)) - return 0; - } - return pool->start; -} - -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) -{ - do { - if (!poolAppendChar(pool, *s)) - return 0; - } while (*s++); - s = pool->start; - poolFinish(pool); - return s; -} - -static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) -{ - if (!pool->ptr && !poolGrow(pool)) - return 0; - for (; n > 0; --n, s++) { - if (!poolAppendChar(pool, *s)) - return 0; - - } - s = pool->start; - poolFinish(pool); - return s; -} - -static -XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!poolAppend(pool, enc, ptr, end)) - return 0; - if (pool->ptr == pool->end && !poolGrow(pool)) - return 0; - *(pool->ptr)++ = 0; - return pool->start; -} - -static -int poolGrow(STRING_POOL *pool) -{ - if (pool->freeBlocks) { - if (pool->start == 0) { - pool->blocks = pool->freeBlocks; - pool->freeBlocks = pool->freeBlocks->next; - pool->blocks->next = 0; - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - pool->ptr = pool->start; - return 1; - } - if (pool->end - pool->start < pool->freeBlocks->size) { - BLOCK *tem = pool->freeBlocks->next; - pool->freeBlocks->next = pool->blocks; - pool->blocks = pool->freeBlocks; - pool->freeBlocks = tem; - memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - return 1; - } - } - if (pool->blocks && pool->start == pool->blocks->s) { - int blockSize = (pool->end - pool->start)*2; - pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!pool->blocks) - return 0; - pool->blocks->size = blockSize; - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + blockSize; - } - else { - BLOCK *tem; - int blockSize = pool->end - pool->start; - if (blockSize < INIT_BLOCK_SIZE) - blockSize = INIT_BLOCK_SIZE; - else - blockSize *= 2; - tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!tem) - return 0; - tem->size = blockSize; - tem->next = pool->blocks; - pool->blocks = tem; - memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); - pool->ptr = tem->s + (pool->ptr - pool->start); - pool->start = tem->s; - pool->end = tem->s + blockSize; - } - return 1; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmlparse.h --- a/mcabber/libjabber/xmlparse.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlParse_INCLUDED -#define XmlParse_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLPARSEAPI -#define XMLPARSEAPI /* as nothing */ -#endif - -typedef void *XML_Parser; - -#ifdef XML_UNICODE_WCHAR_T - -/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t -uses Unicode. */ -/* Information is UTF-16 encoded as wchar_ts */ - -#ifndef XML_UNICODE -#define XML_UNICODE -#endif - -#include -typedef wchar_t XML_Char; -typedef wchar_t XML_LChar; - -#else /* not XML_UNICODE_WCHAR_T */ - -#ifdef XML_UNICODE - -/* Information is UTF-16 encoded as unsigned shorts */ -typedef unsigned short XML_Char; -typedef char XML_LChar; - -#else /* not XML_UNICODE */ - -/* Information is UTF-8 encoded. */ -typedef char XML_Char; -typedef char XML_LChar; - -#endif /* not XML_UNICODE */ - -#endif /* not XML_UNICODE_WCHAR_T */ - - -/* Constructs a new parser; encoding is the encoding specified by the external -protocol or null if there is none specified. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreate(const XML_Char *encoding); - -/* Constructs a new parser and namespace processor. Element type names -and attribute names that belong to a namespace will be expanded; -unprefixed attribute names are never expanded; unprefixed element type -names are expanded only if there is a default namespace. The expanded -name is the concatenation of the namespace URI, the namespace separator character, -and the local part of the name. If the namespace separator is '\0' then -the namespace URI and the local part will be concatenated without any -separator. When a namespace is not declared, the name and prefix will be -passed through without expansion. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); - - -/* atts is array of name/value pairs, terminated by 0; - names and values are 0 terminated. */ - -typedef void (*XML_StartElementHandler)(void *userData, - const XML_Char *name, - const XML_Char **atts); - -typedef void (*XML_EndElementHandler)(void *userData, - const XML_Char *name); - -/* s is not 0 terminated. */ -typedef void (*XML_CharacterDataHandler)(void *userData, - const XML_Char *s, - int len); - -/* target and data are 0 terminated */ -typedef void (*XML_ProcessingInstructionHandler)(void *userData, - const XML_Char *target, - const XML_Char *data); - -/* data is 0 terminated */ -typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); - -typedef void (*XML_StartCdataSectionHandler)(void *userData); -typedef void (*XML_EndCdataSectionHandler)(void *userData); - -/* This is called for any characters in the XML document for -which there is no applicable handler. This includes both -characters that are part of markup which is of a kind that is -not reported (comments, markup declarations), or characters -that are part of a construct which could be reported but -for which no handler has been supplied. The characters are passed -exactly as they were in the XML document except that -they will be encoded in UTF-8. Line boundaries are not normalized. -Note that a byte order mark character is not passed to the default handler. -There are no guarantees about how characters are divided between calls -to the default handler: for example, a comment might be split between -multiple calls. */ - -typedef void (*XML_DefaultHandler)(void *userData, - const XML_Char *s, - int len); - -/* This is called for a declaration of an unparsed (NDATA) -entity. The base argument is whatever was set by XML_SetBase. -The entityName, systemId and notationName arguments will never be null. -The other arguments may be. */ - -typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); - -/* This is called for a declaration of notation. -The base argument is whatever was set by XML_SetBase. -The notationName will never be null. The other arguments can be. */ - -typedef void (*XML_NotationDeclHandler)(void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* When namespace processing is enabled, these are called once for -each namespace declaration. The call to the start and end element -handlers occur between the calls to the start and end namespace -declaration handlers. For an xmlns attribute, prefix will be null. -For an xmlns="" attribute, uri will be null. */ - -typedef void (*XML_StartNamespaceDeclHandler)(void *userData, - const XML_Char *prefix, - const XML_Char *uri); - -typedef void (*XML_EndNamespaceDeclHandler)(void *userData, - const XML_Char *prefix); - -/* This is called if the document is not standalone (it has an -external subset or a reference to a parameter entity, but does not -have standalone="yes"). If this handler returns 0, then processing -will not continue, and the parser will return a -XML_ERROR_NOT_STANDALONE error. */ - -typedef int (*XML_NotStandaloneHandler)(void *userData); - -/* This is called for a reference to an external parsed general entity. -The referenced entity is not automatically parsed. -The application can parse it immediately or later using -XML_ExternalEntityParserCreate. -The parser argument is the parser parsing the entity containing the reference; -it can be passed as the parser argument to XML_ExternalEntityParserCreate. -The systemId argument is the system identifier as specified in the entity declaration; -it will not be null. -The base argument is the system identifier that should be used as the base for -resolving systemId if systemId was relative; this is set by XML_SetBase; -it may be null. -The publicId argument is the public identifier as specified in the entity declaration, -or null if none was specified; the whitespace in the public identifier -will have been normalized as required by the XML spec. -The context argument specifies the parsing context in the format -expected by the context argument to -XML_ExternalEntityParserCreate; context is valid only until the handler -returns, so if the referenced entity is to be parsed later, it must be copied. -The handler should return 0 if processing should not continue because of -a fatal error in the handling of the external entity. -In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING -error. -Note that unlike other handlers the first argument is the parser, not userData. */ - -typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* This structure is filled in by the XML_UnknownEncodingHandler -to provide information to the parser about encodings that are unknown -to the parser. -The map[b] member gives information about byte sequences -whose first byte is b. -If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. -If map[b] is -1, then the byte sequence is malformed. -If map[b] is -n, where n >= 2, then b is the first byte of an n-byte -sequence that encodes a single Unicode scalar value. -The data member will be passed as the first argument to the convert function. -The convert function is used to convert multibyte sequences; -s will point to a n-byte sequence where map[(unsigned char)*s] == -n. -The convert function must return the Unicode scalar value -represented by this byte sequence or -1 if the byte sequence is malformed. -The convert function may be null if the encoding is a single-byte encoding, -that is if map[b] >= -1 for all bytes b. -When the parser is finished with the encoding, then if release is not null, -it will call release passing it the data member; -once release has been called, the convert function will not be called again. - -Expat places certain restrictions on the encodings that are supported -using this mechanism. - -1. Every ASCII character that can appear in a well-formed XML document, -other than the characters - - $@\^`{}~ - -must be represented by a single byte, and that byte must be the -same byte that represents that character in ASCII. - -2. No character may require more than 4 bytes to encode. - -3. All characters encoded must have Unicode scalar values <= 0xFFFF, -(ie characters that would be encoded by surrogates in UTF-16 -are not allowed). Note that this restriction doesn't apply to -the built-in support for UTF-8 and UTF-16. - -4. No Unicode character may be encoded by more than one distinct sequence -of bytes. */ - -typedef struct { - int map[256]; - void *data; - int (*convert)(void *data, const char *s); - void (*release)(void *data); -} XML_Encoding; - -/* This is called for an encoding that is unknown to the parser. -The encodingHandlerData argument is that which was passed as the -second argument to XML_SetUnknownEncodingHandler. -The name argument gives the name of the encoding as specified in -the encoding declaration. -If the callback can provide information about the encoding, -it must fill in the XML_Encoding structure, and return 1. -Otherwise it must return 0. -If info does not describe a suitable encoding, -then the parser will return an XML_UNKNOWN_ENCODING error. */ - -typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info); - -void XMLPARSEAPI -XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end); - -void XMLPARSEAPI -XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler); - -void XMLPARSEAPI -XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler); -void XMLPARSEAPI -XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler); - -void XMLPARSEAPI -XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end); - -/* This sets the default handler and also inhibits expansion of internal entities. -The entity reference will be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler); - -/* This sets the default handler but does not inhibit expansion of internal entities. -The entity reference will not be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler); - -void XMLPARSEAPI -XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler); - -void XMLPARSEAPI -XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler); - -void XMLPARSEAPI -XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end); - -void XMLPARSEAPI -XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler); - -void XMLPARSEAPI -XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler); - -/* If a non-null value for arg is specified here, then it will be passed -as the first argument to the external entity ref handler instead -of the parser object. */ -void XMLPARSEAPI -XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); - -void XMLPARSEAPI -XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *encodingHandlerData); - -/* This can be called within a handler for a start element, end element, -processing instruction or character data. It causes the corresponding -markup to be passed to the default handler. */ -void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser); - -/* This value is passed as the userData argument to callbacks. */ -void XMLPARSEAPI -XML_SetUserData(XML_Parser parser, void *userData); - -/* Returns the last value set by XML_SetUserData or null. */ -#define XML_GetUserData(parser) (*(void **)(parser)) - -/* This is equivalent to supplying an encoding argument -to XML_CreateParser. It must not be called after XML_Parse -or XML_ParseBuffer. */ - -int XMLPARSEAPI -XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); - -/* If this function is called, then the parser will be passed -as the first argument to callbacks instead of userData. -The userData will still be accessible using XML_GetUserData. */ - -void XMLPARSEAPI -XML_UseParserAsHandlerArg(XML_Parser parser); - -/* Sets the base to be used for resolving relative URIs in system identifiers in -declarations. Resolving relative identifiers is left to the application: -this value will be passed through as the base argument to the -XML_ExternalEntityRefHandler, XML_NotationDeclHandler -and XML_UnparsedEntityDeclHandler. The base argument will be copied. -Returns zero if out of memory, non-zero otherwise. */ - -int XMLPARSEAPI -XML_SetBase(XML_Parser parser, const XML_Char *base); - -const XML_Char XMLPARSEAPI * -XML_GetBase(XML_Parser parser); - -/* Returns the number of the attributes passed in last call to the -XML_StartElementHandler that were specified in the start-tag rather -than defaulted. */ - -int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser); - -/* Parses some input. Returns 0 if a fatal error is detected. -The last call to XML_Parse must have isFinal true; -len may be zero for this call (or any other). */ -int XMLPARSEAPI -XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); - -void XMLPARSEAPI * -XML_GetBuffer(XML_Parser parser, int len); - -int XMLPARSEAPI -XML_ParseBuffer(XML_Parser parser, int len, int isFinal); - -/* Creates an XML_Parser object that can parse an external general entity; -context is a '\0'-terminated string specifying the parse context; -encoding is a '\0'-terminated string giving the name of the externally specified encoding, -or null if there is no externally specified encoding. -The context string consists of a sequence of tokens separated by formfeeds (\f); -a token consisting of a name specifies that the general entity of the name -is open; a token of the form prefix=uri specifies the namespace for a particular -prefix; a token of the form =uri specifies the default namespace. -This can be called at any point after the first call to an ExternalEntityRefHandler -so longer as the parser has not yet been freed. -The new parser is completely independent and may safely be used in a separate thread. -The handlers and userData are initialized from the parser argument. -Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ -XML_Parser XMLPARSEAPI -XML_ExternalEntityParserCreate(XML_Parser parser, - const XML_Char *context, - const XML_Char *encoding); - -enum XML_Error { - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE -}; - -/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode -returns information about the error. */ - -enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser); - -/* These functions return information about the current parse location. -They may be called when XML_Parse or XML_ParseBuffer return 0; -in this case the location is the location of the character at which -the error was detected. -They may also be called from any other callback called to report -some parse event; in this the location is the location of the first -of the sequence of characters that generated the event. */ - -int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser); -int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser); -long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser); - -/* Return the number of bytes in the current event. -Returns 0 if the event is in an internal entity. */ - -int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser); - -/* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex - -/* Frees memory used by the parser. */ -void XMLPARSEAPI -XML_ParserFree(XML_Parser parser); - -/* Returns a string describing the error. */ -const XML_LChar XMLPARSEAPI *XML_ErrorString(int code); - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlParse_INCLUDED */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmlrole.c --- a/mcabber/libjabber/xmlrole.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1113 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include "xmldef.h" -#include "xmlrole.h" - -/* Doesn't check: - - that ,| are not mixed in a model group - content of literals - -*/ - -#ifndef MIN_BYTES_PER_CHAR -#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) -#endif - -typedef int PROLOG_HANDLER(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - -static PROLOG_HANDLER -prolog0, prolog1, prolog2, -doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, -internalSubset, -entity0, entity1, entity2, entity3, entity4, entity5, entity6, -entity7, entity8, entity9, -notation0, notation1, notation2, notation3, notation4, -attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, -attlist7, attlist8, attlist9, -element0, element1, element2, element3, element4, element5, element6, -element7, -declClose, -error; - -static -int syntaxError(PROLOG_STATE *); - -static -int prolog0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_XML_DECL: - state->handler = prolog1; - return XML_ROLE_XML_DECL; - case XML_TOK_PI: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_COMMENT: - state->handler = prolog1; - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int doctype0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = doctype1; - return XML_ROLE_DOCTYPE_NAME; - } - return syntaxError(state); -} - -static -int doctype1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = doctype3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = doctype2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int doctype2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype3; - return XML_ROLE_DOCTYPE_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int doctype3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype4; - return XML_ROLE_DOCTYPE_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int doctype4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int doctype5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int internalSubset(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ENTITY")) { - state->handler = entity0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ATTLIST")) { - state->handler = attlist0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ELEMENT")) { - state->handler = element0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "NOTATION")) { - state->handler = notation0; - return XML_ROLE_NONE; - } - break; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_PARAM_ENTITY_REF: - return XML_ROLE_PARAM_ENTITY_REF; - case XML_TOK_CLOSE_BRACKET: - state->handler = doctype5; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int entity0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PERCENT: - state->handler = entity1; - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity2; - return XML_ROLE_GENERAL_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity7; - return XML_ROLE_PARAM_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity4; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity3; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity4; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - - -static -int entity4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity5; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int entity5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "NDATA")) { - state->handler = entity6; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int entity6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = declClose; - return XML_ROLE_ENTITY_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int entity7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity9; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity8; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity9; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int entity9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = notation1; - return XML_ROLE_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int notation1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = notation3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = notation2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int notation2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = notation4; - return XML_ROLE_NOTATION_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int notation3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NOTATION_NO_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int attlist0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist1; - return XML_ROLE_ATTLIST_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int attlist1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist2; - return XML_ROLE_ATTRIBUTE_NAME; - } - return syntaxError(state); -} - -static -int attlist2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - { - static const char *types[] = { - "CDATA", - "ID", - "IDREF", - "IDREFS", - "ENTITY", - "ENTITIES", - "NMTOKEN", - "NMTOKENS", - }; - int i; - for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) - if (XmlNameMatchesAscii(enc, ptr, types[i])) { - state->handler = attlist8; - return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; - } - } - if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) { - state->handler = attlist5; - return XML_ROLE_NONE; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NMTOKEN: - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist4; - return XML_ROLE_ATTRIBUTE_ENUM_VALUE; - } - return syntaxError(state); -} - -static -int attlist4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - - -static -int attlist6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = attlist7; - return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; - } - return syntaxError(state); -} - -static -int attlist7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -/* default value */ -static -int attlist8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "IMPLIED")) { - state->handler = attlist1; - return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "REQUIRED")) { - state->handler = attlist1; - return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "FIXED")) { - state->handler = attlist9; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int attlist9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_FIXED_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int element0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element1; - return XML_ROLE_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int element1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_EMPTY; - } - if (XmlNameMatchesAscii(enc, ptr, "ANY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_ANY; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = element2; - state->level = 1; - return XML_ROLE_GROUP_OPEN; - } - return syntaxError(state); -} - -static -int element2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "PCDATA")) { - state->handler = element3; - return XML_ROLE_CONTENT_PCDATA; - } - break; - case XML_TOK_OPEN_PAREN: - state->level = 2; - state->handler = element6; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element5; - return XML_ROLE_CONTENT_ELEMENT; - } - return syntaxError(state); -} - -static -int element5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->level += 1; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_CLOSE_PAREN_QUESTION: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_OPT; - case XML_TOK_CLOSE_PAREN_PLUS: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_PLUS; - case XML_TOK_COMMA: - state->handler = element6; - return XML_ROLE_GROUP_SEQUENCE; - case XML_TOK_OR: - state->handler = element6; - return XML_ROLE_GROUP_CHOICE; - } - return syntaxError(state); -} - -static -int declClose(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -#if 0 - -static -int ignore(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return 0; - default: - return XML_ROLE_NONE; - } - return syntaxError(state); -} -#endif - -static -int error(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - return XML_ROLE_NONE; -} - -static -int syntaxError(PROLOG_STATE *state) -{ - state->handler = error; - return XML_ROLE_ERROR; -} - -void XmlPrologStateInit(PROLOG_STATE *state) -{ - state->handler = prolog0; -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmlrole.h --- a/mcabber/libjabber/xmlrole.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 - -#include "xmltok.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - XML_ROLE_ERROR = -1, - XML_ROLE_NONE = 0, - XML_ROLE_XML_DECL, - XML_ROLE_INSTANCE_START, - XML_ROLE_DOCTYPE_NAME, - XML_ROLE_DOCTYPE_SYSTEM_ID, - XML_ROLE_DOCTYPE_PUBLIC_ID, - XML_ROLE_DOCTYPE_CLOSE, - XML_ROLE_GENERAL_ENTITY_NAME, - XML_ROLE_PARAM_ENTITY_NAME, - XML_ROLE_ENTITY_VALUE, - XML_ROLE_ENTITY_SYSTEM_ID, - XML_ROLE_ENTITY_PUBLIC_ID, - XML_ROLE_ENTITY_NOTATION_NAME, - XML_ROLE_NOTATION_NAME, - XML_ROLE_NOTATION_SYSTEM_ID, - XML_ROLE_NOTATION_NO_SYSTEM_ID, - XML_ROLE_NOTATION_PUBLIC_ID, - XML_ROLE_ATTRIBUTE_NAME, - XML_ROLE_ATTRIBUTE_TYPE_CDATA, - XML_ROLE_ATTRIBUTE_TYPE_ID, - XML_ROLE_ATTRIBUTE_TYPE_IDREF, - XML_ROLE_ATTRIBUTE_TYPE_IDREFS, - XML_ROLE_ATTRIBUTE_TYPE_ENTITY, - XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, - XML_ROLE_ATTRIBUTE_ENUM_VALUE, - XML_ROLE_ATTRIBUTE_NOTATION_VALUE, - XML_ROLE_ATTLIST_ELEMENT_NAME, - XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, - XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, - XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, - XML_ROLE_FIXED_ATTRIBUTE_VALUE, - XML_ROLE_ELEMENT_NAME, - XML_ROLE_CONTENT_ANY, - XML_ROLE_CONTENT_EMPTY, - XML_ROLE_CONTENT_PCDATA, - XML_ROLE_GROUP_OPEN, - XML_ROLE_GROUP_CLOSE, - XML_ROLE_GROUP_CLOSE_REP, - XML_ROLE_GROUP_CLOSE_OPT, - XML_ROLE_GROUP_CLOSE_PLUS, - XML_ROLE_GROUP_CHOICE, - XML_ROLE_GROUP_SEQUENCE, - XML_ROLE_CONTENT_ELEMENT, - XML_ROLE_CONTENT_ELEMENT_REP, - XML_ROLE_CONTENT_ELEMENT_OPT, - XML_ROLE_CONTENT_ELEMENT_PLUS, - XML_ROLE_PARAM_ENTITY_REF -}; - -typedef struct prolog_state { - int (*handler)(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - unsigned level; -} PROLOG_STATE; - -void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *); - -#define XmlTokenRole(state, tok, ptr, end, enc) \ - (((state)->handler)(state, tok, ptr, end, enc)) - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlRole_INCLUDED */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmltok.c --- a/mcabber/libjabber/xmltok.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1527 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include "xmldef.h" -#include "xmltok.h" -#include "nametab.h" - -#define VTABLE1 \ - { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \ - { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ - PREFIX(sameName), \ - PREFIX(nameMatchesAscii), \ - PREFIX(nameLength), \ - PREFIX(skipS), \ - PREFIX(getAtts), \ - PREFIX(charRefNumber), \ - PREFIX(predefinedEntityName), \ - PREFIX(updatePosition), \ - PREFIX(isPublicId) - -#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) - -#define UCS2_GET_NAMING(pages, hi, lo) \ - (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) - -/* A 2 byte UTF-8 representation splits the characters 11 bits -between the bottom 5 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING2(pages, byte) \ - (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ - + ((((byte)[0]) & 3) << 1) \ - + ((((byte)[1]) >> 5) & 1)] \ - & (1 << (((byte)[1]) & 0x1F))) - -/* A 3 byte UTF-8 representation splits the characters 16 bits -between the bottom 4, 6 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING3(pages, byte) \ - (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ - + ((((byte)[1]) >> 2) & 0xF)] \ - << 3) \ - + ((((byte)[1]) & 3) << 1) \ - + ((((byte)[2]) >> 5) & 1)] \ - & (1 << (((byte)[2]) & 0x1F))) - -#define UTF8_GET_NAMING(pages, p, n) \ - ((n) == 2 \ - ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ - : ((n) == 3 \ - ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ - : 0)) - -#define UTF8_INVALID3(p) \ - ((*p) == 0xED \ - ? (((p)[1] & 0x20) != 0) \ - : ((*p) == 0xEF \ - ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ - : 0)) - -#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) - -static -int isNever(const ENCODING *enc, const char *p) -{ - return 0; -} - -static -int utf8_isName2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); -} - -static -int utf8_isName3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); -} - -#define utf8_isName4 isNever - -static -int utf8_isNmstrt2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); -} - -static -int utf8_isNmstrt3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); -} - -#define utf8_isNmstrt4 isNever - -#define utf8_isInvalid2 isNever - -static -int utf8_isInvalid3(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID3((const unsigned char *)p); -} - -static -int utf8_isInvalid4(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID4((const unsigned char *)p); -} - -struct normal_encoding { - ENCODING enc; - unsigned char type[256]; -#ifdef XML_MIN_SIZE - int (*byteType)(const ENCODING *, const char *); - int (*isNameMin)(const ENCODING *, const char *); - int (*isNmstrtMin)(const ENCODING *, const char *); - int (*byteToAscii)(const ENCODING *, const char *); - int (*charMatches)(const ENCODING *, const char *, int); -#endif /* XML_MIN_SIZE */ - int (*isName2)(const ENCODING *, const char *); - int (*isName3)(const ENCODING *, const char *); - int (*isName4)(const ENCODING *, const char *); - int (*isNmstrt2)(const ENCODING *, const char *); - int (*isNmstrt3)(const ENCODING *, const char *); - int (*isNmstrt4)(const ENCODING *, const char *); - int (*isInvalid2)(const ENCODING *, const char *); - int (*isInvalid3)(const ENCODING *, const char *); - int (*isInvalid4)(const ENCODING *, const char *); -}; - -#ifdef XML_MIN_SIZE - -#define STANDARD_VTABLE(E) \ - E ## byteType, \ - E ## isNameMin, \ - E ## isNmstrtMin, \ - E ## byteToAscii, \ - E ## charMatches, - -#else - -#define STANDARD_VTABLE(E) /* as nothing */ - -#endif - -#define NORMAL_VTABLE(E) \ - E ## isName2, \ - E ## isName3, \ - E ## isName4, \ - E ## isNmstrt2, \ - E ## isNmstrt3, \ - E ## isNmstrt4, \ - E ## isInvalid2, \ - E ## isInvalid3, \ - E ## isInvalid4 - -static int checkCharRefNumber(int); - -#include "xmltok_impl.h" - -#ifdef XML_MIN_SIZE -#define sb_isNameMin isNever -#define sb_isNmstrtMin isNever -#endif - -#ifdef XML_MIN_SIZE -#define MINBPC(enc) ((enc)->minBytesPerChar) -#else -/* minimum bytes per character */ -#define MINBPC(enc) 1 -#endif - -#define SB_BYTE_TYPE(enc, p) \ - (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) - -#ifdef XML_MIN_SIZE -static -int sb_byteType(const ENCODING *enc, const char *p) -{ - return SB_BYTE_TYPE(enc, p); -} -#define BYTE_TYPE(enc, p) \ - (((const struct normal_encoding *)(enc))->byteType(enc, p)) -#else -#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) -#endif - -#ifdef XML_MIN_SIZE -#define BYTE_TO_ASCII(enc, p) \ - (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) -static -int sb_byteToAscii(const ENCODING *enc, const char *p) -{ - return *p; -} -#else -#define BYTE_TO_ASCII(enc, p) (*p) -#endif - -#define IS_NAME_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) -#define IS_NMSTRT_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) -#define IS_INVALID_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) - -#ifdef XML_MIN_SIZE -#define IS_NAME_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) -#else -#define IS_NAME_CHAR_MINBPC(enc, p) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) -#endif - -#ifdef XML_MIN_SIZE -#define CHAR_MATCHES(enc, p, c) \ - (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) -static -int sb_charMatches(const ENCODING *enc, const char *p, int c) -{ - return *p == c; -} -#else -/* c is an ASCII character */ -#define CHAR_MATCHES(enc, p, c) (*(p) == c) -#endif - -#define PREFIX(ident) normal_ ## ident -#include "xmltok_impl_c.h" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ - UTF8_cval1 = 0x00, - UTF8_cval2 = 0xc0, - UTF8_cval3 = 0xe0, - UTF8_cval4 = 0xf0 -}; - -static -void utf8_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char *to; - const char *from; - if (fromLim - *fromP > toLim - *toP) { - /* Avoid copying partial characters. */ - for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) - if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) - break; - } - for (to = *toP, from = *fromP; from != fromLim; from++, to++) - *to = *from; - *fromP = from; - *toP = to; -} - -static -void utf8_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - unsigned short *to = *toP; - const char *from = *fromP; - while (from != fromLim && to != toLim) { - switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { - case BT_LEAD2: - *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); - from += 2; - break; - case BT_LEAD3: - *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); - from += 3; - break; - case BT_LEAD4: - { - unsigned long n; - if (to + 1 == toLim) - break; - n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); - n -= 0x10000; - to[0] = (unsigned short)((n >> 10) | 0xD800); - to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); - to += 2; - from += 4; - } - break; - default: - *to++ = *from++; - break; - } - } - *fromP = from; - *toP = to; -} - -#ifdef XML_NS -static const struct normal_encoding utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; -#endif - -static const struct normal_encoding utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#ifdef XML_NS - -static const struct normal_encoding internal_utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "iasciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#endif - -static const struct normal_encoding internal_utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -static -void latin1_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - for (;;) { - unsigned char c; - if (*fromP == fromLim) - break; - c = (unsigned char)**fromP; - if (c & 0x80) { - if (toLim - *toP < 2) - break; - *(*toP)++ = ((c >> 6) | UTF8_cval2); - *(*toP)++ = ((c & 0x3f) | 0x80); - (*fromP)++; - } - else { - if (*toP == toLim) - break; - *(*toP)++ = *(*fromP)++; - } - } -} - -static -void latin1_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = (unsigned char)*(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding latin1_encoding_ns = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding latin1_encoding = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -static -void ascii_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = *(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding ascii_encoding_ns = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding ascii_encoding = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -static int unicode_byte_type(char hi, char lo) -{ - switch ((unsigned char)hi) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: - return BT_LEAD4; -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return BT_TRAIL; - case 0xFF: - switch ((unsigned char)lo) { - case 0xFF: - case 0xFE: - return BT_NONXML; - } - break; - } - return BT_NONASCII; -} - -#define DEFINE_UTF16_TO_UTF8(E) \ -static \ -void E ## toUtf8(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - char **toP, const char *toLim) \ -{ \ - const char *from; \ - for (from = *fromP; from != fromLim; from += 2) { \ - int plane; \ - unsigned char lo2; \ - unsigned char lo = GET_LO(from); \ - unsigned char hi = GET_HI(from); \ - switch (hi) { \ - case 0: \ - if (lo < 0x80) { \ - if (*toP == toLim) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = lo; \ - break; \ - } \ - /* fall through */ \ - case 0x1: case 0x2: case 0x3: \ - case 0x4: case 0x5: case 0x6: case 0x7: \ - if (toLim - *toP < 2) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - default: \ - if (toLim - *toP < 3) { \ - *fromP = from; \ - return; \ - } \ - /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ - *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ - *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ - if (toLim - *toP < 4) { \ - *fromP = from; \ - return; \ - } \ - plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ - *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ - *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ - from += 2; \ - lo2 = GET_LO(from); \ - *(*toP)++ = (((lo & 0x3) << 4) \ - | ((GET_HI(from) & 0x3) << 2) \ - | (lo2 >> 6) \ - | 0x80); \ - *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ - break; \ - } \ - } \ - *fromP = from; \ -} - -#define DEFINE_UTF16_TO_UTF16(E) \ -static \ -void E ## toUtf16(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - unsigned short **toP, const unsigned short *toLim) \ -{ \ - /* Avoid copying first half only of surrogate */ \ - if (fromLim - *fromP > ((toLim - *toP) << 1) \ - && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ - fromLim -= 2; \ - for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ - *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ -} - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) -#define GET_LO(ptr) ((unsigned char)(ptr)[0]) -#define GET_HI(ptr) ((unsigned char)(ptr)[1]) - -DEFINE_UTF16_TO_UTF8(little2_) -DEFINE_UTF16_TO_UTF16(little2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) -#define GET_LO(ptr) ((unsigned char)(ptr)[1]) -#define GET_HI(ptr) ((unsigned char)(ptr)[0]) - -DEFINE_UTF16_TO_UTF8(big2_) -DEFINE_UTF16_TO_UTF16(big2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define LITTLE2_BYTE_TYPE(enc, p) \ - ((p)[1] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ - : unicode_byte_type((p)[1], (p)[0])) -#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) -#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) -#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) -#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) - -#ifdef XML_MIN_SIZE - -static -int little2_byteType(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TYPE(enc, p); -} - -static -int little2_byteToAscii(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TO_ASCII(enc, p); -} - -static -int little2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return LITTLE2_CHAR_MATCHES(enc, p, c); -} - -static -int little2_isNameMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int little2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) little2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl_c.h" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding little2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding little2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#if XML_BYTE_ORDER != 21 - -#ifdef XML_NS - -static const struct normal_encoding internal_little2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding internal_little2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - - -#define BIG2_BYTE_TYPE(enc, p) \ - ((p)[0] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ - : unicode_byte_type((p)[0], (p)[1])) -#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) -#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) -#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) -#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) - -#ifdef XML_MIN_SIZE - -static -int big2_byteType(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TYPE(enc, p); -} - -static -int big2_byteToAscii(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TO_ASCII(enc, p); -} - -static -int big2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return BIG2_CHAR_MATCHES(enc, p, c); -} - -static -int big2_isNameMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int big2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) big2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl_c.h" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding big2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding big2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#if XML_BYTE_ORDER != 12 - -#ifdef XML_NS - -static const struct normal_encoding internal_big2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding internal_big2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -#undef PREFIX - -static -int streqci(const char *s1, const char *s2) -{ - for (;;) { - char c1 = *s1++; - char c2 = *s2++; - if ('a' <= c1 && c1 <= 'z') - c1 += 'A' - 'a'; - if ('a' <= c2 && c2 <= 'z') - c2 += 'A' - 'a'; - if (c1 != c2) - return 0; - if (!c1) - break; - } - return 1; -} - -static -void initUpdatePosition(const ENCODING *enc, const char *ptr, - const char *end, POSITION *pos) -{ - normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); -} - -static -int toAscii(const ENCODING *enc, const char *ptr, const char *end) -{ - char buf[1]; - char *p = buf; - XmlUtf8Convert(enc, &ptr, end, &p, p + 1); - if (p == buf) - return -1; - else - return buf[0]; -} - -static -int isSpace(int c) -{ - switch (c) { - case 0x20: - case 0xD: - case 0xA: - case 0x9: - return 1; - } - return 0; -} - -/* Return 1 if there's just optional white space -or there's an S followed by name=val. */ -static -int parsePseudoAttribute(const ENCODING *enc, - const char *ptr, - const char *end, - const char **namePtr, - const char **valPtr, - const char **nextTokPtr) -{ - int c; - char open; - if (ptr == end) { - *namePtr = 0; - return 1; - } - if (!isSpace(toAscii(enc, ptr, end))) { - *nextTokPtr = ptr; - return 0; - } - do { - ptr += enc->minBytesPerChar; - } while (isSpace(toAscii(enc, ptr, end))); - if (ptr == end) { - *namePtr = 0; - return 1; - } - *namePtr = ptr; - for (;;) { - c = toAscii(enc, ptr, end); - if (c == -1) { - *nextTokPtr = ptr; - return 0; - } - if (c == '=') - break; - if (isSpace(c)) { - do { - ptr += enc->minBytesPerChar; - } while (isSpace(c = toAscii(enc, ptr, end))); - if (c != '=') { - *nextTokPtr = ptr; - return 0; - } - break; - } - ptr += enc->minBytesPerChar; - } - if (ptr == *namePtr) { - *nextTokPtr = ptr; - return 0; - } - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - while (isSpace(c)) { - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - } - if (c != '"' && c != '\'') { - *nextTokPtr = ptr; - return 0; - } - open = c; - ptr += enc->minBytesPerChar; - *valPtr = ptr; - for (;; ptr += enc->minBytesPerChar) { - c = toAscii(enc, ptr, end); - if (c == open) - break; - if (!('a' <= c && c <= 'z') - && !('A' <= c && c <= 'Z') - && !('0' <= c && c <= '9') - && c != '.' - && c != '-' - && c != '_') { - *nextTokPtr = ptr; - return 0; - } - } - *nextTokPtr = ptr + enc->minBytesPerChar; - return 1; -} - -static -int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, - const char *, - const char *), - int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - const char *val = 0; - const char *name = 0; - ptr += 5 * enc->minBytesPerChar; - end -= 2 * enc->minBytesPerChar; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) { - *badPtr = ptr; - return 0; - } - if (!XmlNameMatchesAscii(enc, name, "version")) { - if (!isGeneralTextEntity) { - *badPtr = name; - return 0; - } - } - else { - if (versionPtr) - *versionPtr = val; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) { - if (isGeneralTextEntity) { - /* a TextDecl must have an EncodingDecl */ - *badPtr = ptr; - return 0; - } - return 1; - } - } - if (XmlNameMatchesAscii(enc, name, "encoding")) { - int c = toAscii(enc, val, end); - if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) { - *badPtr = val; - return 0; - } - if (encodingName) - *encodingName = val; - if (encoding) - *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) - return 1; - } - if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) { - *badPtr = name; - return 0; - } - if (XmlNameMatchesAscii(enc, val, "yes")) { - if (standalone) - *standalone = 1; - } - else if (XmlNameMatchesAscii(enc, val, "no")) { - if (standalone) - *standalone = 0; - } - else { - *badPtr = val; - return 0; - } - while (isSpace(toAscii(enc, ptr, end))) - ptr += enc->minBytesPerChar; - if (ptr != end) { - *badPtr = ptr; - return 0; - } - return 1; -} - -static -int checkCharRefNumber(int result) -{ - switch (result >> 8) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return -1; - case 0: - if (latin1_encoding.type[result] == BT_NONXML) - return -1; - break; - case 0xFF: - if (result == 0xFFFE || result == 0xFFFF) - return -1; - break; - } - return result; -} - -int XmlUtf8Encode(int c, char *buf) -{ - enum { - /* minN is minimum legal resulting value for N byte sequence */ - min2 = 0x80, - min3 = 0x800, - min4 = 0x10000 - }; - - if (c < 0) - return 0; - if (c < min2) { - buf[0] = (c | UTF8_cval1); - return 1; - } - if (c < min3) { - buf[0] = ((c >> 6) | UTF8_cval2); - buf[1] = ((c & 0x3f) | 0x80); - return 2; - } - if (c < min4) { - buf[0] = ((c >> 12) | UTF8_cval3); - buf[1] = (((c >> 6) & 0x3f) | 0x80); - buf[2] = ((c & 0x3f) | 0x80); - return 3; - } - if (c < 0x110000) { - buf[0] = ((c >> 18) | UTF8_cval4); - buf[1] = (((c >> 12) & 0x3f) | 0x80); - buf[2] = (((c >> 6) & 0x3f) | 0x80); - buf[3] = ((c & 0x3f) | 0x80); - return 4; - } - return 0; -} - -int XmlUtf16Encode(int charNum, unsigned short *buf) -{ - if (charNum < 0) - return 0; - if (charNum < 0x10000) { - buf[0] = charNum; - return 1; - } - if (charNum < 0x110000) { - charNum -= 0x10000; - buf[0] = (charNum >> 10) + 0xD800; - buf[1] = (charNum & 0x3FF) + 0xDC00; - return 2; - } - return 0; -} - -struct unknown_encoding { - struct normal_encoding normal; - int (*convert)(void *userData, const char *p); - void *userData; - unsigned short utf16[256]; - char utf8[256][4]; -}; - -int XmlSizeOfUnknownEncoding() -{ - return sizeof(struct unknown_encoding); -} - -static -int unknown_isName(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); -} - -static -int unknown_isNmstrt(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); -} - -static -int unknown_isInvalid(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; -} - -static -void unknown_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char buf[XML_UTF8_ENCODE_MAX]; - for (;;) { - const char *utf8; - int n; - if (*fromP == fromLim) - break; - utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; - n = *utf8++; - if (n == 0) { - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - n = XmlUtf8Encode(c, buf); - if (n > toLim - *toP) - break; - utf8 = buf; - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else { - if (n > toLim - *toP) - break; - (*fromP)++; - } - do { - *(*toP)++ = *utf8++; - } while (--n != 0); - } -} - -static -void unknown_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) { - unsigned short c - = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; - if (c == 0) { - c = (unsigned short)((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else - (*fromP)++; - *(*toP)++ = c; - } -} - -ENCODING * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - int i; - struct unknown_encoding *e = mem; - for (i = 0; i < (int)sizeof(struct normal_encoding); i++) - ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; - for (i = 0; i < 128; i++) - if (latin1_encoding.type[i] != BT_OTHER - && latin1_encoding.type[i] != BT_NONXML - && table[i] != i) - return 0; - for (i = 0; i < 256; i++) { - int c = table[i]; - if (c == -1) { - e->normal.type[i] = BT_MALFORM; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else if (c < 0) { - if (c < -4) - return 0; - e->normal.type[i] = BT_LEAD2 - (c + 2); - e->utf8[i][0] = 0; - e->utf16[i] = 0; - } - else if (c < 0x80) { - if (latin1_encoding.type[c] != BT_OTHER - && latin1_encoding.type[c] != BT_NONXML - && c != i) - return 0; - e->normal.type[i] = latin1_encoding.type[c]; - e->utf8[i][0] = 1; - e->utf8[i][1] = (char)c; - e->utf16[i] = c == 0 ? 0xFFFF : c; - } - else if (checkCharRefNumber(c) < 0) { - e->normal.type[i] = BT_NONXML; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else { - if (c > 0xFFFF) - return 0; - if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NMSTRT; - else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NAME; - else - e->normal.type[i] = BT_OTHER; - e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); - e->utf16[i] = c; - } - } - e->userData = userData; - e->convert = convert; - if (convert) { - e->normal.isName2 = unknown_isName; - e->normal.isName3 = unknown_isName; - e->normal.isName4 = unknown_isName; - e->normal.isNmstrt2 = unknown_isNmstrt; - e->normal.isNmstrt3 = unknown_isNmstrt; - e->normal.isNmstrt4 = unknown_isNmstrt; - e->normal.isInvalid2 = unknown_isInvalid; - e->normal.isInvalid3 = unknown_isInvalid; - e->normal.isInvalid4 = unknown_isInvalid; - } - e->normal.enc.utf8Convert = unknown_toUtf8; - e->normal.enc.utf16Convert = unknown_toUtf16; - return &(e->normal.enc); -} - -/* If this enumeration is changed, getEncodingIndex and encodings -must also be changed. */ -enum { - UNKNOWN_ENC = -1, - ISO_8859_1_ENC = 0, - US_ASCII_ENC, - UTF_8_ENC, - UTF_16_ENC, - UTF_16BE_ENC, - UTF_16LE_ENC, - /* must match encodingNames up to here */ - NO_ENC -}; - -static -int getEncodingIndex(const char *name) -{ - static const char *encodingNames[] = { - "ISO-8859-1", - "US-ASCII", - "UTF-8", - "UTF-16", - "UTF-16BE" - "UTF-16LE", - }; - int i; - if (name == 0) - return NO_ENC; - for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) - if (streqci(name, encodingNames[i])) - return i; - return UNKNOWN_ENC; -} - -/* For binary compatibility, we store the index of the encoding specified -at initialization in the isUtf16 member. */ - -#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16) - -/* This is what detects the encoding. -encodingTable maps from encoding indices to encodings; -INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; -state is XML_CONTENT_STATE if we're parsing an external text entity, -and XML_PROLOG_STATE otherwise. -*/ - - -static -int initScan(const ENCODING **encodingTable, - const INIT_ENCODING *enc, - int state, - const char *ptr, - const char *end, - const char **nextTokPtr) -{ - const ENCODING **encPtr; - - if (ptr == end) - return XML_TOK_NONE; - encPtr = enc->encPtr; - if (ptr + 1 == end) { - /* only a single byte available for auto-detection */ - /* a well-formed document entity must have more than one byte */ - if (state != XML_CONTENT_STATE) - return XML_TOK_PARTIAL; - /* so we're parsing an external text entity... */ - /* if UTF-16 was externally specified, then we need at least 2 bytes */ - switch (INIT_ENC_INDEX(enc)) { - case UTF_16_ENC: - case UTF_16LE_ENC: - case UTF_16BE_ENC: - return XML_TOK_PARTIAL; - } - switch ((unsigned char)*ptr) { - case 0xFE: - case 0xFF: - case 0xEF: /* possibly first byte of UTF-8 BOM */ - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - /* fall through */ - case 0x00: - case 0x3C: - return XML_TOK_PARTIAL; - } - } - else { - switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { - case 0xFEFF: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XML_TOK_BOM; - /* 00 3C is handled in the default case */ - case 0x3C00: - if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC - || INIT_ENC_INDEX(enc) == UTF_16_ENC) - && state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - case 0xFFFE: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XML_TOK_BOM; - case 0xEFBB: - /* Maybe a UTF-8 BOM (EF BB BF) */ - /* If there's an explicitly specified (external) encoding - of ISO-8859-1 or some flavour of UTF-16 - and this is an external text entity, - don't look for the BOM, - because it might be a legal data. */ - if (state == XML_CONTENT_STATE) { - int e = INIT_ENC_INDEX(enc); - if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) - break; - } - if (ptr + 2 == end) - return XML_TOK_PARTIAL; - if ((unsigned char)ptr[2] == 0xBF) { - *encPtr = encodingTable[UTF_8_ENC]; - return XML_TOK_BOM; - } - break; - default: - if (ptr[0] == '\0') { - /* 0 isn't a legal data character. Furthermore a document entity can only - start with ASCII characters. So the only way this can fail to be big-endian - UTF-16 if it it's an external parsed general entity that's labelled as - UTF-16LE. */ - if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) - break; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - else if (ptr[1] == '\0') { - /* We could recover here in the case: - - parsing an external entity - - second byte is 0 - - no externally specified encoding - - no encoding declaration - by assuming UTF-16LE. But we don't, because this would mean when - presented just with a single byte, we couldn't reliably determine - whether we needed further bytes. */ - if (state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - break; - } - } - *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); -} - - -#define NS(x) x -#define ns(x) x -#include "xmltok_ns_c.h" -#undef NS -#undef ns - -#ifdef XML_NS - -#define NS(x) x ## NS -#define ns(x) x ## _ns - -#include "xmltok_ns_c.h" - -#undef NS -#undef ns - -ENCODING * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); - if (enc) - ((struct normal_encoding *)enc)->type[':'] = BT_COLON; - return enc; -} - -#endif /* XML_NS */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmltok.h --- a/mcabber/libjabber/xmltok.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLTOKAPI -#define XMLTOKAPI /* as nothing */ -#endif - -/* The following token may be returned by XmlContentTok */ -#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of - illegal ]]> sequence */ -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_NONE -4 /* The string to be scanned is empty */ -#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; - might be part of CRLF sequence */ -#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ -#define XML_TOK_PARTIAL -1 /* only part of a token */ -#define XML_TOK_INVALID 0 - -/* The following tokens are returned by XmlContentTok; some are also - returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ - -#define XML_TOK_START_TAG_WITH_ATTS 1 -#define XML_TOK_START_TAG_NO_ATTS 2 -#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ -#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 -#define XML_TOK_END_TAG 5 -#define XML_TOK_DATA_CHARS 6 -#define XML_TOK_DATA_NEWLINE 7 -#define XML_TOK_CDATA_SECT_OPEN 8 -#define XML_TOK_ENTITY_REF 9 -#define XML_TOK_CHAR_REF 10 /* numeric character reference */ - -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_PI 11 /* processing instruction */ -#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ -#define XML_TOK_COMMENT 13 -#define XML_TOK_BOM 14 /* Byte order mark */ - -/* The following tokens are returned only by XmlPrologTok */ -#define XML_TOK_PROLOG_S 15 -#define XML_TOK_DECL_OPEN 16 /* */ -#define XML_TOK_NAME 18 -#define XML_TOK_NMTOKEN 19 -#define XML_TOK_POUND_NAME 20 /* #name */ -#define XML_TOK_OR 21 /* | */ -#define XML_TOK_PERCENT 22 -#define XML_TOK_OPEN_PAREN 23 -#define XML_TOK_CLOSE_PAREN 24 -#define XML_TOK_OPEN_BRACKET 25 -#define XML_TOK_CLOSE_BRACKET 26 -#define XML_TOK_LITERAL 27 -#define XML_TOK_PARAM_ENTITY_REF 28 -#define XML_TOK_INSTANCE_START 29 - -/* The following occur only in element type declarations */ -#define XML_TOK_NAME_QUESTION 30 /* name? */ -#define XML_TOK_NAME_ASTERISK 31 /* name* */ -#define XML_TOK_NAME_PLUS 32 /* name+ */ -#define XML_TOK_COND_SECT_OPEN 33 /* */ -#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ -#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ -#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ -#define XML_TOK_COMMA 38 - -/* The following token is returned only by XmlAttributeValueTok */ -#define XML_TOK_ATTRIBUTE_VALUE_S 39 - -/* The following token is returned only by XmlCdataSectionTok */ -#define XML_TOK_CDATA_SECT_CLOSE 40 - -/* With namespace processing this is returned by XmlPrologTok - for a name with a colon. */ -#define XML_TOK_PREFIXED_NAME 41 - -#define XML_N_STATES 3 -#define XML_PROLOG_STATE 0 -#define XML_CONTENT_STATE 1 -#define XML_CDATA_SECTION_STATE 2 - -#define XML_N_LITERAL_TYPES 2 -#define XML_ATTRIBUTE_VALUE_LITERAL 0 -#define XML_ENTITY_VALUE_LITERAL 1 - -/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ -#define XML_UTF8_ENCODE_MAX 4 -/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ -#define XML_UTF16_ENCODE_MAX 2 - -typedef struct position { - /* first line and first column are 0 not 1 */ - unsigned long lineNumber; - unsigned long columnNumber; -} POSITION; - -typedef struct { - const char *name; - const char *valuePtr; - const char *valueEnd; - char normalized; -} ATTRIBUTE; - -struct encoding; -typedef struct encoding ENCODING; - -struct encoding { - int (*scanners[XML_N_STATES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*sameName)(const ENCODING *, - const char *, const char *); - int (*nameMatchesAscii)(const ENCODING *, - const char *, const char *); - int (*nameLength)(const ENCODING *, const char *); - const char *(*skipS)(const ENCODING *, const char *); - int (*getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts); - int (*charRefNumber)(const ENCODING *enc, const char *ptr); - int (*predefinedEntityName)(const ENCODING *, const char *, const char *); - void (*updatePosition)(const ENCODING *, - const char *ptr, - const char *end, - POSITION *); - int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr); - void (*utf8Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - char **toP, - const char *toLim); - void (*utf16Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - unsigned short **toP, - const unsigned short *toLim); - int minBytesPerChar; - char isUtf8; - char isUtf16; -}; - -/* -Scan the string starting at ptr until the end of the next complete token, -but do not scan past eptr. Return an integer giving the type of token. - -Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. - -Return XML_TOK_PARTIAL when the string does not contain a complete token; -nextTokPtr will not be set. - -Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr -will be set to point to the character which made the token invalid. - -Otherwise the string starts with a valid token; nextTokPtr will be set to point -to the character following the end of that token. - -Each data character counts as a single token, but adjacent data characters -may be returned together. Similarly for characters in the prolog outside -literals, comments and processing instructions. -*/ - - -#define XmlTok(enc, state, ptr, end, nextTokPtr) \ - (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) - -#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) - -#define XmlContentTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) - -#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) - -/* This is used for performing a 2nd-level tokenization on -the content of a literal that has already been returned by XmlTok. */ - -#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ - (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) - -#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) - -#define XmlNameMatchesAscii(enc, ptr1, ptr2) \ - (((enc)->nameMatchesAscii)(enc, ptr1, ptr2)) - -#define XmlNameLength(enc, ptr) \ - (((enc)->nameLength)(enc, ptr)) - -#define XmlSkipS(enc, ptr) \ - (((enc)->skipS)(enc, ptr)) - -#define XmlGetAttributes(enc, ptr, attsMax, atts) \ - (((enc)->getAtts)(enc, ptr, attsMax, atts)) - -#define XmlCharRefNumber(enc, ptr) \ - (((enc)->charRefNumber)(enc, ptr)) - -#define XmlPredefinedEntityName(enc, ptr, end) \ - (((enc)->predefinedEntityName)(enc, ptr, end)) - -#define XmlUpdatePosition(enc, ptr, end, pos) \ - (((enc)->updatePosition)(enc, ptr, end, pos)) - -#define XmlIsPublicId(enc, ptr, end, badPtr) \ - (((enc)->isPublicId)(enc, ptr, end, badPtr)) - -#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) - -#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) - -typedef struct { - ENCODING initEnc; - const ENCODING **encPtr; -} INIT_ENCODING; - -int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); - -int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(); -int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf); -int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf); - -int XMLTOKAPI XmlSizeOfUnknownEncoding(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); - -int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); -int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); -#ifdef __cplusplus -} -#endif - -#endif /* not XmlTok_INCLUDED */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmltok_impl.h --- a/mcabber/libjabber/xmltok_impl.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -enum { - BT_NONXML, - BT_MALFORM, - BT_LT, - BT_AMP, - BT_RSQB, - BT_LEAD2, - BT_LEAD3, - BT_LEAD4, - BT_TRAIL, - BT_CR, - BT_LF, - BT_GT, - BT_QUOT, - BT_APOS, - BT_EQUALS, - BT_QUEST, - BT_EXCL, - BT_SOL, - BT_SEMI, - BT_NUM, - BT_LSQB, - BT_S, - BT_NMSTRT, - BT_COLON, - BT_HEX, - BT_DIGIT, - BT_NAME, - BT_MINUS, - BT_OTHER, /* known not to be a name or name start character */ - BT_NONASCII, /* might be a name or name start character */ - BT_PERCNT, - BT_LPAR, - BT_RPAR, - BT_AST, - BT_PLUS, - BT_COMMA, - BT_VERBAR -}; - -#include diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmltok_impl_c.h --- a/mcabber/libjabber/xmltok_impl_c.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1746 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef IS_INVALID_CHAR -#define IS_INVALID_CHAR(enc, ptr, n) (0) -#endif - -#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_INVALID_CHAR(enc, ptr, n)) { \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define INVALID_CASES(ptr, nextTokPtr) \ - INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ - case BT_NONXML: \ - case BT_MALFORM: \ - case BT_TRAIL: \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; - -#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NAME_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - case BT_DIGIT: \ - case BT_NAME: \ - case BT_MINUS: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) - -#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) - -#ifndef PREFIX -#define PREFIX(ident) ident -#endif - -/* ptr points to character following "')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMENT; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following " */ - switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { -case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* fall through */ -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DECL_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) -{ - int upper = 0; - *tokPtr = XML_TOK_PI; - if (end - ptr != MINBPC(enc)*3) - return 1; - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'x': - break; - case 'X': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'm': - break; - case 'M': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - break; - case 'L': - upper = 1; - break; - default: - return 1; - } - if (upper) - return 0; - *tokPtr = XML_TOK_XML_DECL; - return 1; -} - -/* ptr points to character following "')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; - case BT_QUEST: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - - -static -int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int i; - /* CDATA[ */ - if (end - ptr < 6 * MINBPC(enc)) - return XML_TOK_PARTIAL; - for (i = 0; i < 6; i++, ptr += MINBPC(enc)) { - if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - *nextTokPtr = ptr; - return XML_TOK_CDATA_SECT_OPEN; -} - -static -int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CDATA_SECT_CLOSE; - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - case BT_RSQB: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_WITH_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; - } - break; - } - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "<" */ - -static -int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ -#ifdef XML_NS - int hadColon; -#endif - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_EXCL: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr); - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_SOL: - return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } -#ifdef XML_NS - hadColon = 0; -#endif - /* we have a start-tag */ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -#ifdef XML_NS - case BT_COLON: - if (hadColon) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; -#endif -case BT_S: case BT_CR: case BT_LF: - { - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_GT: - goto gt; - case BT_SOL: - goto sol; - case BT_S: case BT_CR: case BT_LF: - ptr += MINBPC(enc); - continue; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr); - } - return XML_TOK_PARTIAL; - } - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_NO_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_NO_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_LT: - return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_AMP: - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_RSQB: - if (ptr + MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) { - ptr += MINBPC(enc); - break; - } - if (ptr + 2*MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) { - ptr += MINBPC(enc); - break; - } - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_AMP: - case BT_LT: - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "%" */ - -static -int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_PERCENT; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_PARAM_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_CR: case BT_LF: case BT_S: -case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: - *nextTokPtr = ptr; - return XML_TOK_POUND_NAME; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanLit)(int open, const ENCODING *enc, - const char *ptr, const char *end, - const char **nextTokPtr) -{ - while (ptr != end) { - int t = BYTE_TYPE(enc, ptr); - switch (t) { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUOT: - case BT_APOS: - ptr += MINBPC(enc); - if (t != open) - break; - if (ptr == end) - return XML_TOK_PARTIAL; - *nextTokPtr = ptr; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_CR: case BT_LF: - case BT_GT: case BT_PERCNT: case BT_LSQB: - return XML_TOK_LITERAL; - default: - return XML_TOK_INVALID; - } - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int tok; - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_QUOT: - return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_APOS: - return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LT: - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_EXCL: - return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_NMSTRT: - case BT_HEX: - case BT_NONASCII: - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - *nextTokPtr = ptr - MINBPC(enc); - return XML_TOK_INSTANCE_START; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - case BT_CR: - if (ptr + MINBPC(enc) == end) - return XML_TOK_TRAILING_CR; - /* fall through */ -case BT_S: case BT_LF: - for (;;) { - ptr += MINBPC(enc); - if (ptr == end) - break; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_LF: - break; - case BT_CR: - /* don't split CR/LF pair */ - if (ptr + MINBPC(enc) != end) - break; - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - } - } - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - case BT_PERCNT: - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_COMMA: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMA; - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_BRACKET; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ']')) { - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) { - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_COND_SECT_CLOSE; - } - } - *nextTokPtr = ptr; - return XML_TOK_CLOSE_BRACKET; - case BT_LPAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_PAREN; - case BT_RPAR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_AST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_ASTERISK; - case BT_QUEST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_QUESTION; - case BT_PLUS: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_PLUS; -case BT_CR: case BT_LF: case BT_S: -case BT_GT: case BT_COMMA: case BT_VERBAR: - case BT_RPAR: - *nextTokPtr = ptr; - return XML_TOK_CLOSE_PAREN; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_VERBAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OR; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DECL_CLOSE; - case BT_NUM: - return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NAME; \ - break; \ - } \ - if (IS_NAME_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NMTOKEN; \ - break; \ - } \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NMSTRT: - case BT_HEX: - tok = XML_TOK_NAME; - ptr += MINBPC(enc); - break; - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: -#ifdef XML_NS - case BT_COLON: -#endif - tok = XML_TOK_NMTOKEN; - ptr += MINBPC(enc); - break; - case BT_NONASCII: - if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NAME; - break; - } - if (IS_NAME_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NMTOKEN; - break; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_GT: case BT_RPAR: case BT_COMMA: -case BT_VERBAR: case BT_LSQB: case BT_PERCNT: -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return tok; -#ifdef XML_NS - case BT_COLON: - ptr += MINBPC(enc); - switch (tok) { - case XML_TOK_NAME: - if (ptr == end) - return XML_TOK_PARTIAL; - tok = XML_TOK_PREFIXED_NAME; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - default: - tok = XML_TOK_NMTOKEN; - break; - } - break; - case XML_TOK_PREFIXED_NAME: - tok = XML_TOK_NMTOKEN; - break; - } - break; -#endif - case BT_PLUS: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_PLUS; - case BT_AST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_ASTERISK; - case BT_QUEST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_QUESTION; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LT: - /* this is for inside entity references */ - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_S: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ATTRIBUTE_VALUE_S; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_PERCNT: - if (ptr == start) - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr) -{ - ptr += MINBPC(enc); - end -= MINBPC(enc); - for (; ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - case BT_MINUS: - case BT_APOS: - case BT_LPAR: - case BT_RPAR: - case BT_PLUS: - case BT_COMMA: - case BT_SOL: - case BT_EQUALS: - case BT_QUEST: - case BT_CR: - case BT_LF: - case BT_SEMI: - case BT_EXCL: - case BT_AST: - case BT_PERCNT: - case BT_NUM: -#ifdef XML_NS - case BT_COLON: -#endif - break; - case BT_S: - if (CHAR_MATCHES(enc, ptr, '\t')) { - *badPtr = ptr; - return 0; - } - break; - case BT_NAME: - case BT_NMSTRT: - if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) - break; - default: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 0x24: /* $ */ - case 0x40: /* @ */ - break; - default: - *badPtr = ptr; - return 0; - } - break; - } - } - return 1; -} - -/* This must only be called for a well-formed start-tag or empty element tag. -Returns the number of attributes. Pointers to the first attsMax attributes -are stored in atts. */ - -static -int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts) -{ - enum { other, inName, inValue } state = inName; - int nAtts = 0; - int open = 0; - - for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { -#define START_NAME \ - if (state == other) { \ - if (nAtts < attsMax) { \ - atts[nAtts].name = ptr; \ - atts[nAtts].normalized = 1; \ - } \ - state = inName; \ - } -#define LEAD_CASE(n) \ - case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: - case BT_HEX: - START_NAME - break; -#undef START_NAME - case BT_QUOT: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_QUOT; - } - else if (open == BT_QUOT) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_APOS: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_APOS; - } - else if (open == BT_APOS) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_AMP: - if (nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_S: - if (state == inName) - state = other; - else if (state == inValue - && nAtts < attsMax - && atts[nAtts].normalized - && (ptr == atts[nAtts].valuePtr - || BYTE_TO_ASCII(enc, ptr) != ' ' - || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' ' - || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) - atts[nAtts].normalized = 0; - break; - case BT_CR: case BT_LF: - /* This case ensures that the first attribute name is counted - Apart from that we could just change state on the quote. */ - if (state == inName) - state = other; - else if (state == inValue && nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_GT: - case BT_SOL: - if (state != inValue) - return nAtts; - break; - default: - break; - } - } - /* not reached */ -} - -static -int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) -{ - int result = 0; - /* skip &# */ - ptr += 2*MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'x')) { - for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - switch (c) { -case '0': case '1': case '2': case '3': case '4': -case '5': case '6': case '7': case '8': case '9': - result <<= 4; - result |= (c - '0'); - break; -case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - result <<= 4; - result += 10 + (c - 'A'); - break; -case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - result <<= 4; - result += 10 + (c - 'a'); - break; - } - if (result >= 0x110000) - return -1; - } - } - else { - for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - result *= 10; - result += (c - '0'); - if (result >= 0x110000) - return -1; - } - } - return checkCharRefNumber(result); -} - -static -int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) -{ - switch ((end - ptr)/MINBPC(enc)) { - case 2: - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) { - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - return '<'; - case 'g': - return '>'; - } - } - break; - case 3: - if (CHAR_MATCHES(enc, ptr, 'a')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'm')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) - return '&'; - } - } - break; - case 4: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'q': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'u')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 't')) - return '"'; - } - } - break; - case 'a': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 's')) - return '\''; - } - } - break; - } - } - return 0; -} - -static -int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr1)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (*ptr1++ != *ptr2++) \ - return 0; - LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) -#undef LEAD_CASE - /* fall through */ - if (*ptr1++ != *ptr2++) - return 0; - break; - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 1) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 2) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 3) { - if (*ptr2++ != *ptr1++) - return 0; - } - } - } - break; - default: - if (MINBPC(enc) == 1 && *ptr1 == *ptr2) - return 1; - switch (BYTE_TYPE(enc, ptr2)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } - } - } - /* not reached */ -} - -static -int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { - if (!CHAR_MATCHES(enc, ptr1, *ptr2)) - return 0; - } - switch (BYTE_TYPE(enc, ptr1)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } -} - -static -int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) -{ - const char *start = ptr; - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - ptr += MINBPC(enc); - break; - default: - return ptr - start; - } - } -} - -static -const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_LF: - case BT_CR: - case BT_S: - ptr += MINBPC(enc); - break; - default: - return ptr; - } - } -} - -static -void PREFIX(updatePosition)(const ENCODING *enc, - const char *ptr, - const char *end, - POSITION *pos) -{ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_LF: - pos->columnNumber = (unsigned)-1; - pos->lineNumber++; - ptr += MINBPC(enc); - break; - case BT_CR: - pos->lineNumber++; - ptr += MINBPC(enc); - if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - pos->columnNumber = (unsigned)-1; - break; - default: - ptr += MINBPC(enc); - break; - } - pos->columnNumber++; - } -} - -#undef DO_LEAD_CASE -#undef MULTIBYTE_CASES -#undef INVALID_CASES -#undef CHECK_NAME_CASE -#undef CHECK_NAME_CASES -#undef CHECK_NMSTRT_CASE -#undef CHECK_NMSTRT_CASES diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xmltok_ns_c.h --- a/mcabber/libjabber/xmltok_ns_c.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -const ENCODING *NS(XmlGetUtf8InternalEncoding)() -{ - return &ns(internal_utf8_encoding).enc; -} - -const ENCODING *NS(XmlGetUtf16InternalEncoding)() -{ -#if XML_BYTE_ORDER == 12 - return &ns(internal_little2_encoding).enc; -#elif XML_BYTE_ORDER == 21 -return &ns(internal_big2_encoding).enc; -#else -const short n = 1; - return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc; -#endif -} - -static -const ENCODING *NS(encodings)[] = { - &ns(latin1_encoding).enc, - &ns(ascii_encoding).enc, - &ns(utf8_encoding).enc, - &ns(big2_encoding).enc, - &ns(big2_encoding).enc, - &ns(little2_encoding).enc, - &ns(utf8_encoding).enc /* NO_ENC */ -}; - -static -int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); -} - -static -int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); -} - -int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) -{ - int i = getEncodingIndex(name); - if (i == UNKNOWN_ENC) - return 0; - INIT_ENC_INDEX(p) = (char)i; - p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); - p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); - p->initEnc.updatePosition = initUpdatePosition; - p->encPtr = encPtr; - *encPtr = &(p->initEnc); - return 1; -} - -static -const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) -{ -#define ENCODING_MAX 128 - char buf[ENCODING_MAX]; - char *p = buf; - int i; - XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); - if (ptr != end) - return 0; - *p = 0; - if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2) - return enc; - i = getEncodingIndex(buf); - if (i == UNKNOWN_ENC) - return 0; - return NS(encodings)[i]; -} - -int NS(XmlParseXmlDecl)(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - return doParseXmlDecl(NS(findEncoding), - isGeneralTextEntity, - enc, - ptr, - end, - badPtr, - versionPtr, - encodingName, - encoding, - standalone); -} diff -r 4f59a414217e -r a087125d8fc8 mcabber/libjabber/xstream.c --- a/mcabber/libjabber/xstream.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -/* - * 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. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - */ - -/** - * @file xstream.c - * @brief handling of incoming XML stream based events - * - * xstream is a way to have a consistent method of handling incoming XML stream based events ... - * it doesn't handle the generation of an XML stream, but provides some facilities to help doing that - */ - -#include -#include - -/* ========== internal expat callbacks =========== */ - -/** - * internal expat callback for read start tags of an element - */ -void _xstream_startElement(xstream xs, const char* name, const char** atts) -{ - pool p; - - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - if(xs->node == NULL) - { - p = pool_heap(5*1024); /* 5k, typically 1-2k each plus copy of self and workspace */ - xs->node = xmlnode_new_tag_pool(p,name); - xmlnode_put_expat_attribs(xs->node, atts); - - if(xs->status == XSTREAM_ROOT) - { - xs->status = XSTREAM_NODE; /* flag status that we're processing nodes now */ - (xs->f)(XSTREAM_ROOT, xs->node, xs->arg); /* send the root, f must free all nodes */ - xs->node = NULL; - } - }else{ - xs->node = xmlnode_insert_tag(xs->node, name); - xmlnode_put_expat_attribs(xs->node, atts); - } - - /* depth check */ - xs->depth++; - if(xs->depth > XSTREAM_MAXDEPTH) - xs->status = XSTREAM_ERR; -} - -/** - * internal expat callback for read end tags of an element - */ -void _xstream_endElement(xstream xs, const char* name) -{ - xmlnode parent; - - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - /* if it's already NULL we've received , tell the app and we're outta here */ - if(xs->node == NULL) - { - xs->status = XSTREAM_CLOSE; - (xs->f)(XSTREAM_CLOSE, NULL, xs->arg); - }else{ - parent = xmlnode_get_parent(xs->node); - - /* we are the top-most node, feed to the app who is responsible to delete it */ - if(parent == NULL) - (xs->f)(XSTREAM_NODE, xs->node, xs->arg); - - xs->node = parent; - } - xs->depth--; -} - -/** - * internal expat callback for read CDATA - */ -void _xstream_charData(xstream xs, const char *str, int len) -{ - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - if(xs->node == NULL) - { - /* we must be in the root of the stream where CDATA is irrelevant */ - return; - } - - xmlnode_insert_cdata(xs->node, str, len); -} - -/** - * internal function to be registered as pool cleaner, frees a stream if the associated memory pool is freed - * - * @param pointer to the xstream to free - */ -void _xstream_cleanup(void *arg) -{ - xstream xs = (xstream)arg; - - xmlnode_free(xs->node); /* cleanup anything left over */ - XML_ParserFree(xs->parser); -} - - -/** - * creates a new xstream with given pool, xstream will be cleaned up w/ pool - * - * @param p the memory pool to use for the stream - * @param f function pointer to the event handler function - * @param arg parameter to pass to the event handler function - * @return the created xstream - */ -xstream xstream_new(pool p, xstream_onNode f, void *arg) -{ - xstream newx; - - if(p == NULL || f == NULL) - { - fprintf(stderr,"Fatal Programming Error: xstream_new() was improperly called with NULL.\n"); - return NULL; - } - - newx = pmalloco(p, sizeof(_xstream)); - newx->p = p; - newx->f = f; - newx->arg = arg; - - /* create expat parser and ensure cleanup */ - newx->parser = XML_ParserCreate(NULL); - XML_SetUserData(newx->parser, (void *)newx); - XML_SetElementHandler(newx->parser, - (XML_StartElementHandler)_xstream_startElement, - (XML_EndElementHandler)_xstream_endElement); - XML_SetCharacterDataHandler(newx->parser, - (XML_CharacterDataHandler)_xstream_charData); - pool_cleanup(p, _xstream_cleanup, (void *)newx); - - return newx; -} - -/** - * attempts to parse the buff onto this stream firing events to the handler - * - * @param xs the xstream to parse the data on - * @param buff the new data - * @param len length of the data - * @return last known xstream status - */ -int xstream_eat(xstream xs, char *buff, int len) -{ - char *err; - xmlnode xerr; - static char maxerr[] = "maximum node size reached"; - static char deeperr[] = "maximum node depth reached"; - - if(xs == NULL) - { - fprintf(stderr,"Fatal Programming Error: xstream_eat() was improperly called with NULL.\n"); - return XSTREAM_ERR; - } - - if(len == 0 || buff == NULL) - return xs->status; - - if(len == -1) /* easy for hand-fed eat calls */ - len = strlen(buff); - - if(!XML_Parse(xs->parser, buff, len, 0)) - { - err = (char *)XML_ErrorString(XML_GetErrorCode(xs->parser)); - xs->status = XSTREAM_ERR; - }else if(pool_size(xmlnode_pool(xs->node)) > XSTREAM_MAXNODE || xs->cdata_len > XSTREAM_MAXNODE){ - err = maxerr; - xs->status = XSTREAM_ERR; - }else if(xs->status == XSTREAM_ERR){ /* set within expat handlers */ - err = deeperr; - } - - /* fire parsing error event, make a node containing the error string */ - if(xs->status == XSTREAM_ERR) - { - xerr = xmlnode_new_tag("error"); - xmlnode_insert_cdata(xerr,err,-1); - (xs->f)(XSTREAM_ERR, xerr, xs->arg); - } - - return xs->status; -} - - -/* STREAM CREATION UTILITIES */ - -/** give a standard template xmlnode to work from - * - * @param namespace ("jabber:client", "jabber:server", ...) - * @param to where the stream is sent to - * @param from where we are (source of the stream) - * @return the xmlnode that has been generated as the template - */ -xmlnode xstream_header(char *namespace, char *to, char *from) -{ - xmlnode x; - char id[11]; - - sprintf(id,"%X",(int)time(NULL)); - - x = xmlnode_new_tag("stream:stream"); - xmlnode_put_attrib(x, "xmlns:stream", "http://etherx.jabber.org/streams"); - xmlnode_put_attrib(x, "id", id); - if(namespace != NULL) - xmlnode_put_attrib(x, "xmlns", namespace); - if(to != NULL) - xmlnode_put_attrib(x, "to", to); - if(from != NULL) - xmlnode_put_attrib(x, "from", from); - - return x; -} - -/** - * trim the xmlnode to only the opening header :) - * - * @note NO CHILDREN ALLOWED - * - * @param x the xmlnode - * @return string representation of the start tag - */ -char *xstream_header_char(xmlnode x) -{ - spool s; - char *fixr, *head; - - if(xmlnode_has_children(x)) { - fprintf(stderr,"Fatal Programming Error: xstream_header_char() was sent a header with children!\n"); - return NULL; - } - - s = spool_new(xmlnode_pool(x)); - spooler(s,"",xmlnode2str(x),s); - head = spool_print(s); - fixr = strstr(head,"/>"); - *fixr = '>'; - ++fixr; - *fixr = '\0'; - - return head; -} - diff -r 4f59a414217e -r a087125d8fc8 mcabber/mcabberrc.example --- a/mcabber/mcabberrc.example Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/mcabberrc.example Sun Oct 11 15:38:32 2009 +0200 @@ -34,26 +34,23 @@ # presence in your roster (default: 0). set ignore_self_presence = 1 -# SSL options: -# Set ssl non-zero to use SSL (this also sets the default port to 5223). -# * Please note that certificate verification is NOT yet supported if -# mcabber is compiled with GnuTLS (only works with OpenSSL). -# You can use mcabber -V to check. -# Set ssl_verify to 0 to disable certificate verification, or non-zero -# to set desired maximum CA verification depth. Use -1 to specify an -# unlimited depth. -# NOTE: You probably need to set ssl_capath for SSL cert verification to work! -# Set ssl_cafile to a path to a CA certificate file (may contain multiple -# CA certificates). -# Set ssl_capath to a directory containing CA certificates (use c_rehash -# to generate hash links). -# Set ssl_ciphers to a list of desired SSL ciphers (run "openssl ciphers" -# for candidate values). +# SSL/TLS options: +# TLS is now regarded as the default encryption for connecting to jabber. +# You can require TLS by setting tls to 1. If your jabber server +# still doesn't support TLS, you can use the old-style SSL by setting +# ssl to 1. It's not possible to use old-style SSL and TLS together. set ssl = 0 -#set ssl_verify = -1 -#set ssl_cafile = /usr/share/ssl/certs/ca-bundle.crt -#set ssl_capath = -#set ssl_ciphers = +set tls = 1 +# Moreover, it's possible to check whether the fingerprint of the +# ssl certificate matches ssl_fingerprint. +# You can get the fingerprint of your server either with gnutls or openssl: +# 1. gnutls-cli -p 5223 $your_server +# 2. openssl s_client -connect $your_server:5223 | \ +# openssl x509 -fingerprint -md5 -noout +set ssl_fingerprint = 97:5C:00:3F:1D:77:45:25:E2:C5:70:EC:83:C8:87:EE +# Set ssl_ignore_checks to 1 to disable all certificate checks except the +# fingerprint check. +#set ssl_ignore_checks = 0 # PGP support # Set pgp to 1 to enable OpenPGP. diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/Makefile.am --- a/mcabber/src/Makefile.am Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/Makefile.am Sun Oct 11 15:38:32 2009 +0200 @@ -1,29 +1,27 @@ bin_PROGRAMS = mcabber mcabber_SOURCES = main.c roster.c roster.h events.c events.h \ - jabglue.c jabglue.h jab_iq.c jab_priv.h \ commands.c commands.h compl.c compl.h \ hbuf.c hbuf.h screen.c screen.h logprint.h \ settings.c settings.h hooks.c hooks.h utf8.c utf8.h \ histolog.c histolog.h utils.c utils.h pgp.c pgp.h \ - fifo.c fifo.h help.c help.h + fifo.c fifo.h help.c help.h \ + xmpp.c xmpp.h xmpp_helper.h if OTR mcabber_SOURCES += otr.c otr.h nohtml.c nohtml.h endif -LDADD = $(GLIB_LIBS) $(GPGME_LIBS) $(LIBOTR_LIBS) $(ENCHANT_LIBS) \ - ../libjabber/liblibjabber.a ../connwrap/libconnwrap.a +LDADD = $(GLIB_LIBS) $(LOUDMOUTH_LIBS) $(GPGME_LIBS) $(LIBOTR_LIBS) \ + $(ENCHANT_LIBS) -AM_CPPFLAGS = $(GLIB_CFLAGS) $(GPGME_CFLAGS) $(LIBOTR_CFLAGS) $(ENCHANT_CFLAGS) +AM_CPPFLAGS = $(GLIB_CFLAGS) $(LOUDMOUTH_CFLAGS) $(GPGME_CFLAGS) \ + $(LIBOTR_CFLAGS) $(ENCHANT_CFLAGS) CLEANFILES = hgcset.h if HGCSET BUILT_SOURCES = hgcset.h -#mcabber_DEPENDENCIES = hgcset.h \ -# ../libjabber/liblibjabber.a ../connwrap/libconnwrap.a - hgcset.h: ../hgcset.sh diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/commands.c --- a/mcabber/src/commands.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/commands.c Sun Oct 11 15:38:32 2009 +0200 @@ -20,13 +20,13 @@ */ #include +#include #include #include #include #include "commands.h" #include "help.h" -#include "jabglue.h" #include "roster.h" #include "screen.h" #include "compl.h" @@ -37,6 +37,7 @@ #include "events.h" #include "otr.h" #include "utf8.h" +#include "xmpp.h" #define IMSTATUS_AWAY "away" #define IMSTATUS_ONLINE "online" @@ -575,7 +576,7 @@ static void display_all_annotations(void) { GSList *notes; - notes = jb_get_all_storage_rosternotes(); + notes = xmpp_get_all_storage_rosternotes(); if (!notes) return; @@ -620,10 +621,10 @@ notetxt = NULL; // delete note else notetxt = msg; - jb_set_storage_rosternotes(bjid, notetxt); + xmpp_set_storage_rosternotes(bjid, notetxt); g_free(msg); } else { // Display a note - struct annotation *note = jb_get_storage_rosternotes(bjid, FALSE); + struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE); if (note) { display_and_free_note(note, bjid); } else { @@ -819,7 +820,7 @@ char *msg; enum imstatus st; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -854,7 +855,7 @@ free_arg_lst(paramlst); return; } - st = jb_getstatus(); // Preserve current status + st = xmpp_getstatus(); // Preserve current status } else { scr_LogPrint(LPRINT_NORMAL, "Unrecognized status!"); free_arg_lst(paramlst); @@ -870,7 +871,7 @@ if (recipient && !msg) msg = ""; - jb_setstatus(st, recipient, msg, FALSE); + xmpp_setstatus(st, recipient, msg, FALSE); free_arg_lst(paramlst); } @@ -878,9 +879,9 @@ static void do_status(char *arg) { if (!*arg) { - const char *sm = jb_getstatusmsg(); + const char *sm = xmpp_getstatusmsg(); scr_LogPrint(LPRINT_NORMAL, "Your status is: [%c] %s", - imstatus2char[jb_getstatus()], + imstatus2char[xmpp_getstatus()], (sm ? sm : "")); return; } @@ -953,7 +954,7 @@ char *id, *nick; char *jid_utf8 = NULL; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -992,7 +993,7 @@ if (id) { // 2nd parameter = optional nickname - jb_addbuddy(id, nick, NULL); + xmpp_addbuddy(id, nick, NULL); scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.", id); } @@ -1030,7 +1031,7 @@ scr_BufferPurge(1, NULL); scr_LogPrint(LPRINT_LOGNORM, "Removing <%s>...", bjid); - jb_delbuddy(bjid); + xmpp_delbuddy(bjid); scr_UpdateBuddyWindow(); } @@ -1106,7 +1107,7 @@ } static int send_message_to(const char *fjid, const char *msg, const char *subj, - const char *type_overwrite, bool quiet) + LmMessageSubType type_overwrite, bool quiet) { char *bare_jid, *rp; char *hmsg; @@ -1114,7 +1115,7 @@ gint retval = 0; int isroom; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return 1; } @@ -1160,8 +1161,8 @@ hmsg = (char*)msg; // Network part - jb_send_msg(fjid, msg, (isroom ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER), - subj, NULL, &crypted, type_overwrite); + xmpp_send_msg(fjid, msg, (isroom ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER), + subj, FALSE, &crypted, type_overwrite); if (crypted == -1) { scr_LogPrint(LPRINT_LOGNORM, "Encryption error. Message was not sent."); @@ -1183,7 +1184,7 @@ // Write the message in the buddy's window and send the message on // the network. static void send_message(const char *msg, const char *subj, - const char *type_overwrite) + LmMessageSubType type_overwrite) { const char *bjid; @@ -1201,19 +1202,19 @@ send_message_to(bjid, msg, subj, type_overwrite, FALSE); } -static const char *scan_mtype(char **arg) +static LmMessageSubType scan_mtype(char **arg) { //Try splitting it char **parlist = split_arg(*arg, 2, 1); - const char *result = NULL; + LmMessageSubType result = LM_MESSAGE_SUB_TYPE_NOT_SET; //Is it any good parameter? if (parlist && *parlist) { if (!strcmp("-n", *parlist)) { - result = TMSG_NORMAL; + result = LM_MESSAGE_SUB_TYPE_NORMAL; } else if (!strcmp("-h", *parlist)) { - result = TMSG_HEADLINE; + result = LM_MESSAGE_SUB_TYPE_HEADLINE; } - if (result || (!strcmp("--", *parlist))) + if (result != LM_MESSAGE_SUB_TYPE_NOT_SET || (!strcmp("--", *parlist))) *arg += strlen(*arg) - (parlist[1] ? strlen(parlist[1]) : 0); } //Anything found? -> skip it @@ -1224,7 +1225,7 @@ static void do_say_internal(char *arg, int parse_flags) { gpointer bud; - const char *msgtype = NULL; + LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET; scr_set_chatmode(TRUE); scr_ShowBuddyWindow(); @@ -1330,7 +1331,7 @@ if (!strcasecmp(subcmd, "send_to")) { int err = FALSE; gchar *msg_utf8; - const char *msg_type = scan_mtype(&arg); + LmMessageSubType msg_type = scan_mtype(&arg); // Let's send to the specified JID. We leave now if there // has been an error (so we don't leave multi-line mode). arg = to_utf8(arg); @@ -1456,10 +1457,10 @@ char **paramlst; char *fjid, *msg; char *file = NULL; - const char *msg_type = NULL; + LmMessageSubType msg_type = LM_MESSAGE_SUB_TYPE_NOT_SET; bool quiet = FALSE; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -1799,7 +1800,7 @@ if (type == ROSTER_TYPE_USER || type == ROSTER_TYPE_ROOM || type == ROSTER_TYPE_AGENT) { - struct annotation *note = jb_get_storage_rosternotes(bjid, TRUE); + struct annotation *note = xmpp_get_storage_rosternotes(bjid, TRUE); if (note) { // We do not display the note, we just tell the user. g_free(note->text); @@ -1908,7 +1909,7 @@ bjid = buddy_getjid(bud); name = buddy_getname(bud); - jb_updatebuddy(bjid, name, *groupname ? groupname : NULL); + xmpp_updatebuddy(bjid, name, *groupname ? groupname : NULL); } static void do_rename(char *arg) @@ -1942,7 +1943,7 @@ scr_LogPrint(LPRINT_NORMAL, "Note: this item will be added to your server roster."); // If this is a MUC room w/o bookmark, let's give a small hint... - if (!jb_is_bookmarked(bjid)) { + if (!xmpp_is_bookmarked(bjid)) { scr_LogPrint(LPRINT_NORMAL, "You should add a room bookmark or it will not be " "recognized as a MUC room next time you run mcabber."); @@ -1970,7 +1971,7 @@ if (!*newname || !strcmp(arg, "-")) del_name = TRUE; buddy_setname(bud, (del_name ? (char*)bjid : name_utf8)); - jb_updatebuddy(bjid, (del_name ? NULL : name_utf8), group); + xmpp_updatebuddy(bjid, (del_name ? NULL : name_utf8), group); } g_free(name_utf8); @@ -2016,7 +2017,7 @@ if (strcmp(oldgroupname, group_utf8)) { guint msgflag; - jb_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL); + xmpp_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL); scr_RosterUpDown(-1, 1); // If the buddy has a pending message flag, @@ -2167,7 +2168,7 @@ char **paramlst; char *subcmd; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -2198,7 +2199,7 @@ buffer = to_utf8(arg); if (buffer) { scr_LogPrint(LPRINT_NORMAL, "Sending XML string"); - jb_send_raw(buffer); + lm_connection_send_raw(lconnection, buffer, NULL); g_free(buffer); } else { scr_LogPrint(LPRINT_NORMAL, "Conversion error in XML string."); @@ -2290,7 +2291,7 @@ pass_utf8 = to_utf8(pass); - jb_room_join(roomname, nick, pass_utf8); + xmpp_room_join(roomname, nick, pass_utf8); scr_LogPrint(LPRINT_LOGNORM, "Sent a join request to <%s>...", roomname); @@ -2324,7 +2325,7 @@ roomname = buddy_getjid(bud); reason_utf8 = to_utf8(arg); - jb_room_invite(roomname, fjid, reason_utf8); + xmpp_room_invite(roomname, fjid, reason_utf8); scr_LogPrint(LPRINT_LOGNORM, "Invitation sent to <%s>.", fjid); g_free(reason_utf8); free_arg_lst(paramlst); @@ -2358,7 +2359,7 @@ gchar *jid_utf8, *reason_utf8; jid_utf8 = to_utf8(fjid); reason_utf8 = to_utf8(arg); - jb_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); + xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); g_free(jid_utf8); g_free(reason_utf8); } else @@ -2395,7 +2396,7 @@ gchar *jid_utf8, *reason_utf8; jid_utf8 = to_utf8(fjid); reason_utf8 = to_utf8(arg); - jb_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); + xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); g_free(jid_utf8); g_free(reason_utf8); } else @@ -2451,7 +2452,7 @@ scr_LogPrint(LPRINT_NORMAL, "Requesting a ban for %s", banjid); reason_utf8 = to_utf8(arg); - jb_room_setattrib(roomid, banjid, NULL, ra, reason_utf8); + xmpp_room_setattrib(roomid, banjid, NULL, ra, reason_utf8); g_free(reason_utf8); room_ban_return: @@ -2477,7 +2478,7 @@ ra.val.affil = affil_none; jid_utf8 = to_utf8(fjid); - jb_room_setattrib(roomid, jid_utf8, NULL, ra, NULL); + xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, NULL); g_free(jid_utf8); } @@ -2505,7 +2506,7 @@ nick_utf8 = to_utf8(nick); reason_utf8 = to_utf8(arg); - jb_room_setattrib(roomid, NULL, nick_utf8, ra, reason_utf8); + xmpp_room_setattrib(roomid, NULL, nick_utf8, ra, reason_utf8); g_free(nick_utf8); g_free(reason_utf8); @@ -2525,7 +2526,7 @@ roomid = g_strdup_printf("%s/%s", buddy_getjid(bud), nickname); desc = to_utf8(arg); - jb_setstatus(offline, roomid, desc, TRUE); + xmpp_setstatus(offline, roomid, desc, TRUE); g_free(desc); g_free(roomid); } @@ -2553,7 +2554,7 @@ nick = to_utf8(arg); strip_arg_special_chars(nick); - jb_room_join(roomname, nick, NULL); + xmpp_room_join(roomname, nick, NULL); g_free(roomname); g_free(nick); } @@ -2578,7 +2579,7 @@ fjid = g_strdup_printf("%s/%s", buddy_getjid(bud), nick); fjid_utf8 = to_utf8(fjid); msg = to_utf8(arg); - send_message_to(fjid_utf8, msg, NULL, NULL, FALSE); + send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE); g_free(fjid); g_free(fjid_utf8); g_free(msg); @@ -2628,8 +2629,8 @@ arg = to_utf8(arg); // Set the topic - jb_send_msg(buddy_getjid(bud), NULL, ROSTER_TYPE_ROOM, arg ? arg : "", - NULL, NULL, NULL); + xmpp_send_msg(buddy_getjid(bud), NULL, ROSTER_TYPE_ROOM, arg ? arg : "", + FALSE, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET); g_free(arg); } @@ -2642,7 +2643,7 @@ else msg = NULL; - jb_room_destroy(buddy_getjid(bud), NULL, msg); + xmpp_room_destroy(buddy_getjid(bud), NULL, msg); g_free(msg); } @@ -2653,7 +2654,7 @@ return; } - jb_room_unlock(buddy_getjid(bud)); + xmpp_room_unlock(buddy_getjid(bud)); } static void room_setopt(gpointer bud, char *arg) @@ -2848,8 +2849,8 @@ autowhois = buddy_getautowhois(bud); } - jb_set_storage_bookmark(roomid, name, nick, NULL, autojoin, - printstatus, autowhois); + xmpp_set_storage_bookmark(roomid, name, nick, NULL, autojoin, + printstatus, autowhois); } static void display_all_bookmarks(void) @@ -2858,7 +2859,7 @@ GString *sbuf; struct bookmark *bm_elt; - bm = jb_get_all_storage_bookmarks(); + bm = xmpp_get_all_storage_bookmarks(); if (!bm) return; @@ -2897,7 +2898,7 @@ char *subcmd; gpointer bud; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -2994,7 +2995,7 @@ char *subcmd; char *jid_utf8; - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); return; } @@ -3042,21 +3043,21 @@ } if (!strcasecmp(subcmd, "allow")) { - jb_subscr_send_auth(jid_utf8); + xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_SUBSCRIBED); scr_LogPrint(LPRINT_LOGNORM, "<%s> is now allowed to receive your presence updates.", jid_utf8); } else if (!strcasecmp(subcmd, "cancel")) { - jb_subscr_cancel_auth(jid_utf8); + xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED); scr_LogPrint(LPRINT_LOGNORM, "<%s> will no longer receive your presence updates.", jid_utf8); } else if (!strcasecmp(subcmd, "request")) { - jb_subscr_request_auth(jid_utf8); + xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_SUBSCRIBE); scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.", jid_utf8); } else if (!strcasecmp(subcmd, "request_unsubscribe")) { - jb_subscr_request_cancel(jid_utf8); + xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE); scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification unsubscription request to <%s>.", jid_utf8); @@ -3099,12 +3100,6 @@ numtype = iqreq_last; else if (!strcasecmp(type, "vcard")) numtype = iqreq_vcard; - else if (!strcasecmp(type, "show_list")) { - // Undocumented command, for debugging purposes only - jb_iqs_display_list(); - free_arg_lst(paramlst); - return; - } } if (!type || !numtype) { @@ -3114,7 +3109,7 @@ return; } - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { scr_LogPrint(LPRINT_NORMAL, "You are not connected."); free_arg_lst(paramlst); return; @@ -3151,7 +3146,7 @@ case iqreq_time: case iqreq_last: case iqreq_vcard: - jb_request(fjid, numtype); + xmpp_request(fjid, numtype); break; default: break; @@ -3462,7 +3457,7 @@ } #ifdef HAVE_LIBOTR -static char * string_for_otrpolicy(enum otr_policy p) +static char *string_for_otrpolicy(enum otr_policy p) { switch (p) { case plain: return "plain"; @@ -3473,7 +3468,7 @@ } } -static void dump_otrpolicy(char * k, char * v, void * nothing) +static void dump_otrpolicy(char *k, char *v, void *nothing) { scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, "otrpolicy for %s: %s", k, string_for_otrpolicy(*(enum otr_policy*)v)); @@ -3670,13 +3665,12 @@ static void do_connect(char *arg) { - mcabber_connect(); + xmpp_connect(); } static void do_disconnect(char *arg) { - jb_disconnect(); - AutoConnection = FALSE; + xmpp_disconnect(); } static void do_help(char *arg) diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/commands.h --- a/mcabber/src/commands.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/commands.h Sun Oct 11 15:38:32 2009 +0200 @@ -18,7 +18,6 @@ char *expandalias(const char *line); extern char *mcabber_version(void); -extern void mcabber_connect(void); extern void mcabber_set_terminate_ui(void); void cmd_room_whois(gpointer bud, char *nick_locale, guint interactive); diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/events.c --- a/mcabber/src/events.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/events.c Sun Oct 11 15:38:32 2009 +0200 @@ -20,6 +20,7 @@ */ #include +#include #include "events.h" #include "logprint.h" @@ -54,6 +55,8 @@ new_evs->type = type; new_evs->id = stridn; + if(!g_slist_length(evs_list)) + g_timeout_add_seconds(20, evs_check_timeout, NULL); evs_list = g_slist_append(evs_list, new_evs); return new_evs; } @@ -72,7 +75,6 @@ } if (p) { g_free(i->id); - if (i->xmldata) xmlnode_free(i->xmldata); g_free(i->data); g_free(i->desc); g_free(i); @@ -116,12 +118,16 @@ return 0; } -void evs_check_timeout(time_t now_t) +gboolean evs_check_timeout() { + time_t now_t; GSList *p; eviqs *i; + time(&now_t); p = evs_list; + if (!p) + return FALSE; while (p) { i = p->data; // We must get next IQ eviqs element now because the current one @@ -133,6 +139,7 @@ evs_callback(i->id, EVS_CONTEXT_TIMEOUT); } } + return TRUE; } void evs_display_list(void) diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/events.h --- a/mcabber/src/events.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/events.h Sun Oct 11 15:38:32 2009 +0200 @@ -1,7 +1,7 @@ #ifndef __EVENTS_H__ #define __EVENTS_H__ 1 -#include "jabglue.h" +#include "xmpp.h" #define EVS_DEFAULT_TIMEOUT 90 @@ -24,7 +24,6 @@ guint8 type; gpointer data; int (*callback)(); - xmlnode xmldata; char *desc; } eviqs; @@ -35,12 +34,12 @@ char* reason; } event_muc_invitation; -eviqs *evs_new(guint8 type, time_t timeout); -int evs_del(const char *evid); -int evs_callback(const char *evid, guint evcontext); -void evs_check_timeout(time_t now_t); -void evs_display_list(void); -GSList *evs_geteventslist(int forcompl); +eviqs *evs_new(guint8 type, time_t timeout); +int evs_del(const char *evid); +int evs_callback(const char *evid, guint evcontext); +gboolean evs_check_timeout(); +void evs_display_list(void); +GSList *evs_geteventslist(int forcompl); #endif /* __EVENTS_H__ */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/fifo.c --- a/mcabber/src/fifo.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/fifo.c Sun Oct 11 15:38:32 2009 +0200 @@ -20,6 +20,7 @@ */ #include +#include #include #include #include diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/histolog.c --- a/mcabber/src/histolog.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/histolog.c Sun Oct 11 15:38:32 2009 +0200 @@ -19,23 +19,24 @@ * USA */ -#include +#include +#include +#include #include -#include -#include +#include #include #include -#include +#include #include #include "histolog.h" #include "hbuf.h" -#include "jabglue.h" #include "utils.h" #include "screen.h" #include "settings.h" #include "utils.h" #include "roster.h" +#include "xmpp.h" static guint UseFileLogging; static guint FileLoadLogs; @@ -76,7 +77,7 @@ if (S_ISLNK(bufstat.st_mode)) { g_free(log_jid); log_jid = g_new0(char, bufstat.st_size+1); - readlink(path, log_jid, bufstat.st_size); + if (readlink(path, log_jid, bufstat.st_size) < 0) return NULL; g_free(path); path = user_histo_file(log_jid); } else @@ -444,7 +445,7 @@ goto hlog_save_state_return; } - if (!jb_getonline()) { + if (!lm_connection_is_authenticated(lconnection)) { // We're not connected. Let's use the unread_jids hash. GList *unread_jid = unread_jid_get_list(); unread_ptr = unread_jid; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/histolog.h --- a/mcabber/src/histolog.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/histolog.h Sun Oct 11 15:38:32 2009 +0200 @@ -3,7 +3,7 @@ #include -#include "jabglue.h" +#include "xmpp.h" void hlog_enable(guint enable, const char *root_dir, guint loadfile); char *hlog_get_log_jid(const char *bjid); diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/hooks.c --- a/mcabber/src/hooks.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/hooks.c Sun Oct 11 15:38:32 2009 +0200 @@ -19,9 +19,11 @@ * USA */ +#include +#include +#include #include #include -#include #include "hooks.h" #include "screen.h" @@ -55,8 +57,8 @@ } void hk_message_in(const char *bjid, const char *resname, - time_t timestamp, const char *msg, const char *type, - guint encrypted) + time_t timestamp, const char *msg, LmMessageSubType type, + guint encrypted) { int new_guy = FALSE; int is_groupchat = FALSE; // groupchat message @@ -75,7 +77,7 @@ else if (encrypted == ENCRYPTED_OTR) message_flags |= HBB_PREFIX_OTRCRYPT; - if (type && !strcmp(type, "groupchat")) { + if (type == LM_MESSAGE_SUB_TYPE_GROUPCHAT) { rtype = ROSTER_TYPE_ROOM; is_groupchat = TRUE; log_muc_conf = settings_opt_get_int("log_muc_conf"); @@ -172,7 +174,7 @@ } } - if (type && !strcmp(type, "error")) { + if (type == LM_MESSAGE_SUB_TYPE_ERROR) { message_flags = HBB_PREFIX_ERR | HBB_PREFIX_IN; scr_LogPrint(LPRINT_LOGNORM, "Error message received from <%s>", bjid); } @@ -292,8 +294,8 @@ } void hk_statuschange(const char *bjid, const char *resname, gchar prio, - time_t timestamp, enum imstatus status, - const char *status_msg) + time_t timestamp, enum imstatus status, + const char *status_msg) { int st_in_buf; enum imstatus oldstat; @@ -477,8 +479,15 @@ scr_LogPrint(LPRINT_LOGNORM, "Unable to create temp file for external command."); } else { - write(fd, data_locale, strlen(data_locale)); - write(fd, "\n", 1); + size_t data_locale_len = strlen(data_locale); + ssize_t a = write(fd, data_locale, data_locale_len); + ssize_t b = write(fd, "\n", 1); + if (a != data_locale_len || b != 1) { + g_free(datafname); + datafname = NULL; + scr_LogPrint(LPRINT_LOGNORM, + "Unable to write to temp file for external command."); + } close(fd); arg_data = datafname; } diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/hooks.h --- a/mcabber/src/hooks.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/hooks.h Sun Oct 11 15:38:32 2009 +0200 @@ -2,7 +2,8 @@ #define __HOOKS_H__ 1 #include -#include "jabglue.h" +#include +#include "xmpp.h" // These two defines are used by hk_message_{in,out} arguments #define ENCRYPTED_PGP 1 @@ -10,13 +11,13 @@ void hk_mainloop(void); void hk_message_in(const char *bjid, const char *resname, - time_t timestamp, const char *msg, const char *type, - guint encrypted); + time_t timestamp, const char *msg, LmMessageSubType type, + guint encrypted); void hk_message_out(const char *bjid, const char *nickname, time_t timestamp, const char *msg, guint encrypted); void hk_statuschange(const char *bjid, const char *resname, gchar prio, - time_t timestamp, enum imstatus status, - char const *status_msg); + time_t timestamp, enum imstatus status, + char const *status_msg); void hk_mystatuschange(time_t timestamp, enum imstatus old_status, enum imstatus new_status, const char *msg); diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/jab_iq.c --- a/mcabber/src/jab_iq.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1801 +0,0 @@ -/* - * jab_iq.c -- Jabber protocol IQ-related fonctions - * - * Copyright (C) 2005-2008 Mikael Berthe - * Some parts initially came from the centericq project: - * Copyright (C) 2002-2005 by Konstantin Klyagin - * Some small parts come from the Pidgin project - * - * 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 -#include - -#include "jabglue.h" -#include "jab_priv.h" -#include "roster.h" -#include "utils.h" -#include "screen.h" -#include "settings.h" -#include "hbuf.h" -#include "commands.h" -#include "hooks.h" - -#ifdef ENABLE_HGCSET -# include "hgcset.h" -#endif - - -// Bookmarks for IQ:private storage -xmlnode bookmarks; -// Roster notes for IQ:private storage -xmlnode rosternotes; - -static GSList *iqs_list; - -time_t iqlast; // last message/status change time - -// Enum for vCard attributes -enum vcard_attr { - vcard_home = 1<<0, - vcard_work = 1<<1, - vcard_postal = 1<<2, - vcard_voice = 1<<3, - vcard_fax = 1<<4, - vcard_cell = 1<<5, - vcard_inet = 1<<6, - vcard_pref = 1<<7, -}; - -static void handle_iq_command_set_status(jconn conn, char *from, - const char *id, xmlnode xmldata); - -static void handle_iq_command_leave_groupchats(jconn conn, char *from, - const char *id, xmlnode xmldata); - -typedef void (*adhoc_command_callback)(jconn, char*, const char*, xmlnode); - -inline double seconds_since_last_use(void); - -struct adhoc_command { - char *name; - char *description; - bool only_for_self; - adhoc_command_callback callback; -}; - -const struct adhoc_command adhoc_command_list[] = { - { "http://jabber.org/protocol/rc#set-status", - "Change client status", - 1, - &handle_iq_command_set_status }, - { "http://jabber.org/protocol/rc#leave-groupchats", - "Leave groupchat(s)", - 1, - &handle_iq_command_leave_groupchats }, - { NULL, NULL, 0, NULL }, -}; - -struct adhoc_status { - char *name; // the name used by adhoc - char *description; - char *status; // the string, used by setstus -}; - -const struct adhoc_status adhoc_status_list[] = { - {"online", "Online", "avail"}, - {"chat", "Chat", "free"}, - {"away", "Away", "away"}, - {"xd", "Extended away", "notavail"}, - {"dnd", "Do not disturb", "dnd"}, - {"invisible", "Invisible", "invisible"}, - {"offline", "Offline", "offline"}, - {NULL, NULL, NULL}, -}; - -// entity_version() -// Return a static version string for Entity Capabilities. -// It should be specific to the client version, please change the id -// if you alter mcabber's disco support (or add something to the version -// number) so that it doesn't conflict with the official client. -const char *entity_version(void) -{ - static char *ver; - const char *PVERSION = PACKAGE_VERSION; // "+xxx"; - - if (ver) - return ver; - -#ifdef HGCSET - ver = g_strdup_printf("%s-%s", PVERSION, HGCSET); -#else - ver = g_strdup(PVERSION); -#endif - - return ver; -} - -// iqs_new(type, namespace, prefix, timeout) -// Create a query (GET, SET) IQ structure. This function should not be used -// for RESULT packets. -eviqs *iqs_new(guint8 type, const char *ns, const char *prefix, time_t tmout) -{ - static guint iqs_idn; - eviqs *new_iqs; - time_t now_t; - - iqs_idn++; - - new_iqs = g_new0(eviqs, 1); - time(&now_t); - new_iqs->ts_create = now_t; - if (tmout) - new_iqs->ts_expire = now_t + tmout; - new_iqs->type = type; - new_iqs->xmldata = jutil_iqnew(type, (char*)ns); - if (prefix) - new_iqs->id = g_strdup_printf("%s_%d", prefix, iqs_idn); - else - new_iqs->id = g_strdup_printf("%d", iqs_idn); - xmlnode_put_attrib(new_iqs->xmldata, "id", new_iqs->id); - - iqs_list = g_slist_append(iqs_list, new_iqs); - return new_iqs; -} - -int iqs_del(const char *iqid) -{ - GSList *p; - eviqs *i; - - if (!iqid) return 1; - - for (p = iqs_list; p; p = g_slist_next(p)) { - i = p->data; - if (!strcmp(iqid, i->id)) - break; - } - if (p) { - g_free(i->id); - xmlnode_free(i->xmldata); - g_free(i->data); - g_free(i); - iqs_list = g_slist_remove(iqs_list, p->data); - return 0; // Ok, deleted - } - return -1; // Not found -} - -static eviqs *iqs_find(const char *iqid) -{ - GSList *p; - eviqs *i; - - if (!iqid) return NULL; - - for (p = iqs_list; p; p = g_slist_next(p)) { - i = p->data; - if (!strcmp(iqid, i->id)) - return i; - } - return NULL; -} - -// iqs_callback(iqid, xml_result, iqcontext) -// Callback processing for the iqid message. -// If we've received an answer, xml_result should point to the xmldata packet. -// If this is a timeout, xml_result should be NULL. -// Return 0 in case of success, -1 if the iqid hasn't been found. -int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext) -{ - eviqs *i; - int retval = 0; - - i = iqs_find(iqid); - if (!i) return -1; - - // IQ processing - // Note: If xml_result is NULL, this is a timeout - if (i->callback) - retval = (*i->callback)(i, xml_result, iqcontext); - - iqs_del(iqid); - return retval; -} - -void iqs_check_timeout(time_t now_t) -{ - GSList *p; - eviqs *i; - - p = iqs_list; - while (p) { - i = p->data; - // We must get next IQ eviqs element now because the current one - // could be freed. - p = g_slist_next(p); - - if ((!i->ts_expire && now_t > i->ts_create + (time_t)IQS_MAX_TIMEOUT) || - (i->ts_expire && now_t > i->ts_expire)) { - iqs_callback(i->id, NULL, IQS_CONTEXT_TIMEOUT); - } - } -} - -void jb_iqs_display_list(void) -{ - GSList *p; - eviqs *i; - - scr_LogPrint(LPRINT_LOGNORM, "IQ list:"); - for (p = iqs_list; p; p = g_slist_next(p)) { - i = p->data; - scr_LogPrint(LPRINT_LOGNORM, "Id [%s]", i->id); - } - scr_LogPrint(LPRINT_LOGNORM, "End of IQ list."); -} - -static void handle_iq_roster(xmlnode x) -{ - xmlnode y; - const char *fjid, *name, *group, *sub, *ask; - char *cleanalias; - enum subscr esub; - int need_refresh = FALSE; - guint roster_type; - - for (y = xmlnode_get_tag(x, "item"); y; y = xmlnode_get_nextsibling(y)) { - char *name_tmp = NULL; - - fjid = xmlnode_get_attrib(y, "jid"); - name = xmlnode_get_attrib(y, "name"); - sub = xmlnode_get_attrib(y, "subscription"); - ask = xmlnode_get_attrib(y, "ask"); - - group = xmlnode_get_tag_data(y, "group"); - - if (!fjid) - continue; - - cleanalias = jidtodisp(fjid); - - esub = sub_none; - if (sub) { - if (!strcmp(sub, "to")) esub = sub_to; - else if (!strcmp(sub, "from")) esub = sub_from; - else if (!strcmp(sub, "both")) esub = sub_both; - else if (!strcmp(sub, "remove")) esub = sub_remove; - } - - if (esub == sub_remove) { - roster_del_user(cleanalias); - scr_LogPrint(LPRINT_LOGNORM, "Buddy <%s> has been removed " - "from the roster", cleanalias); - g_free(cleanalias); - need_refresh = TRUE; - continue; - } - - if (ask && !strcmp(ask, "subscribe")) - esub |= sub_pending; - - if (!name) { - if (!settings_opt_get_int("roster_hide_domain")) { - name = cleanalias; - } else { - char *p; - name = name_tmp = g_strdup(cleanalias); - p = strchr(name_tmp, JID_DOMAIN_SEPARATOR); - if (p) *p = '\0'; - } - } - - // Tricky... :-\ My guess is that if there is no JID_DOMAIN_SEPARATOR, - // this is an agent. - if (strchr(cleanalias, JID_DOMAIN_SEPARATOR)) - roster_type = ROSTER_TYPE_USER; - else - roster_type = ROSTER_TYPE_AGENT; - - roster_add_user(cleanalias, name, group, roster_type, esub, 1); - - g_free(name_tmp); - g_free(cleanalias); - } - - buddylist_build(); - update_roster = TRUE; - if (need_refresh) - scr_UpdateBuddyWindow(); -} - -// This callback is reached when mcabber receives the first roster update -// after the connection. -static int iqscallback_gotroster(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - xmlnode x; - char *ns; - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return -1; - - // Only execute the hook if the roster has been successfully retrieved - if (iqcontext != IQS_CONTEXT_RESULT) - return 0; - - x = xmlnode_get_tag(xml_result, "query"); - if (!x) - return -1; - - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_ROSTER)) - handle_iq_roster(x); - - // Post-login stuff - jb_setprevstatus(); - hook_execute_internal("hook-post-connect"); - - return 0; -} - -static void request_roster(void) -{ - eviqs *iqn = iqs_new(JPACKET__GET, NS_ROSTER, "Roster", IQS_DEFAULT_TIMEOUT); - iqn->callback = &iqscallback_gotroster; - jab_send(jc, iqn->xmldata); -} - -static int iqscallback_version(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - xmlnode ansqry; - char *p; - char *bjid; - char *buf; - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return -1; - - ansqry = xmlnode_get_tag(xml_result, "query"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!"); - return 0; - } - // Display IQ result sender... - p = xmlnode_get_attrib(xml_result, "from"); - if (!p) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name)."); - return 0; - } - bjid = p; - - buf = g_strdup_printf("Received IQ:version result from <%s>", bjid); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - - // bjid should now really be the "bare JID", let's strip the resource - p = strchr(bjid, JID_RESOURCE_SEPARATOR); - if (p) *p = '\0'; - - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); - g_free(buf); - - // Get result data... - p = xmlnode_get_tag_data(ansqry, "name"); - if (p) { - buf = g_strdup_printf("Name: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - p = xmlnode_get_tag_data(ansqry, "version"); - if (p) { - buf = g_strdup_printf("Version: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - p = xmlnode_get_tag_data(ansqry, "os"); - if (p) { - buf = g_strdup_printf("OS: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - return 0; -} - -void request_version(const char *fulljid) -{ - eviqs *iqn; - - iqn = iqs_new(JPACKET__GET, NS_VERSION, "version", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", fulljid); - iqn->callback = &iqscallback_version; - jab_send(jc, iqn->xmldata); -} - -static int iqscallback_time(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - xmlnode ansqry; - char *p; - char *bjid; - char *buf; - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return -1; - - ansqry = xmlnode_get_tag(xml_result, "query"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!"); - return 0; - } - // Display IQ result sender... - p = xmlnode_get_attrib(xml_result, "from"); - if (!p) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name)."); - return 0; - } - bjid = p; - - buf = g_strdup_printf("Received IQ:time result from <%s>", bjid); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - - // bjid should now really be the "bare JID", let's strip the resource - p = strchr(bjid, JID_RESOURCE_SEPARATOR); - if (p) *p = '\0'; - - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); - g_free(buf); - - // Get result data... - p = xmlnode_get_tag_data(ansqry, "utc"); - if (p) { - buf = g_strdup_printf("UTC: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - p = xmlnode_get_tag_data(ansqry, "tz"); - if (p) { - buf = g_strdup_printf("TZ: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - p = xmlnode_get_tag_data(ansqry, "display"); - if (p) { - buf = g_strdup_printf("Time: %s", p); - scr_WriteIncomingMessage(bjid, buf, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); - } - return 0; -} - -void request_time(const char *fulljid) -{ - eviqs *iqn; - - iqn = iqs_new(JPACKET__GET, NS_TIME, "time", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", fulljid); - iqn->callback = &iqscallback_time; - jab_send(jc, iqn->xmldata); -} - -static int iqscallback_last(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - xmlnode ansqry; - char *p; - char *bjid; - char *buf; - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return -1; - - ansqry = xmlnode_get_tag(xml_result, "query"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!"); - return 0; - } - // Display IQ result sender... - p = xmlnode_get_attrib(xml_result, "from"); - if (!p) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name)."); - return 0; - } - bjid = p; - - buf = g_strdup_printf("Received IQ:last result from <%s>", bjid); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - - // bjid should now really be the "bare JID", let's strip the resource - p = strchr(bjid, JID_RESOURCE_SEPARATOR); - if (p) *p = '\0'; - - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); - g_free(buf); - - // Get result data... - p = xmlnode_get_attrib(ansqry, "seconds"); - if (p) { - long int s; - GString *sbuf; - sbuf = g_string_new("Idle time: "); - s = atol(p); - // Days - if (s > 86400L) { - g_string_append_printf(sbuf, "%ldd ", s/86400L); - s %= 86400L; - } - // hh:mm:ss - g_string_append_printf(sbuf, "%02ld:", s/3600L); - s %= 3600L; - g_string_append_printf(sbuf, "%02ld:%02ld", s/60L, s%60L); - scr_WriteIncomingMessage(bjid, sbuf->str, - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_string_free(sbuf, TRUE); - } else { - scr_WriteIncomingMessage(bjid, "No idle time reported.", - 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - } - p = xmlnode_get_data(ansqry); - if (p) { - buf = g_strdup_printf("Status message: %s", p); - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); - g_free(buf); - } - return 0; -} - -void request_last(const char *fulljid) -{ - eviqs *iqn; - - iqn = iqs_new(JPACKET__GET, NS_LAST, "last", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", fulljid); - iqn->callback = &iqscallback_last; - jab_send(jc, iqn->xmldata); -} - -static void display_vcard_item(const char *bjid, const char *label, - enum vcard_attr vcard_attrib, const char *text) -{ - char *buf; - - if (!text || !bjid || !label) - return; - - buf = g_strdup_printf("%s: %s%s%s%s%s%s%s%s%s%s", label, - (vcard_attrib & vcard_home ? "[home]" : ""), - (vcard_attrib & vcard_work ? "[work]" : ""), - (vcard_attrib & vcard_postal ? "[postal]" : ""), - (vcard_attrib & vcard_voice ? "[voice]" : ""), - (vcard_attrib & vcard_fax ? "[fax]" : ""), - (vcard_attrib & vcard_cell ? "[cell]" : ""), - (vcard_attrib & vcard_inet ? "[inet]" : ""), - (vcard_attrib & vcard_pref ? "[pref]" : ""), - (vcard_attrib ? " " : ""), - text); - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); - g_free(buf); -} - -static void handle_vcard_node(const char *barejid, xmlnode vcardnode) -{ - xmlnode x; - const char *p; - - x = xmlnode_get_firstchild(vcardnode); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *data; - enum vcard_attr vcard_attrib = 0; - - p = xmlnode_get_name(x); - data = xmlnode_get_data(x); - if (!p || !data) - continue; - - if (!strcmp(p, "FN")) - display_vcard_item(barejid, "Name", vcard_attrib, data); - else if (!strcmp(p, "NICKNAME")) - display_vcard_item(barejid, "Nickname", vcard_attrib, data); - else if (!strcmp(p, "URL")) - display_vcard_item(barejid, "URL", vcard_attrib, data); - else if (!strcmp(p, "BDAY")) - display_vcard_item(barejid, "Birthday", vcard_attrib, data); - else if (!strcmp(p, "TZ")) - display_vcard_item(barejid, "Timezone", vcard_attrib, data); - else if (!strcmp(p, "TITLE")) - display_vcard_item(barejid, "Title", vcard_attrib, data); - else if (!strcmp(p, "ROLE")) - display_vcard_item(barejid, "Role", vcard_attrib, data); - else if (!strcmp(p, "DESC")) - display_vcard_item(barejid, "Comment", vcard_attrib, data); - else if (!strcmp(p, "N")) { - data = xmlnode_get_tag_data(x, "FAMILY"); - display_vcard_item(barejid, "Family Name", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "GIVEN"); - display_vcard_item(barejid, "Given Name", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "MIDDLE"); - display_vcard_item(barejid, "Middle Name", vcard_attrib, data); - } else if (!strcmp(p, "ORG")) { - data = xmlnode_get_tag_data(x, "ORGNAME"); - display_vcard_item(barejid, "Organisation name", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "ORGUNIT"); - display_vcard_item(barejid, "Organisation unit", vcard_attrib, data); - } else { - // The HOME, WORK and PREF attributes are common to the remaining fields - // (ADR, TEL & EMAIL) - if (xmlnode_get_tag(x, "HOME")) - vcard_attrib |= vcard_home; - if (xmlnode_get_tag(x, "WORK")) - vcard_attrib |= vcard_work; - if (xmlnode_get_tag(x, "PREF")) - vcard_attrib |= vcard_pref; - if (!strcmp(p, "ADR")) { // Address - if (xmlnode_get_tag(x, "POSTAL")) - vcard_attrib |= vcard_postal; - data = xmlnode_get_tag_data(x, "EXTADD"); - display_vcard_item(barejid, "Addr (ext)", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "STREET"); - display_vcard_item(barejid, "Street", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "LOCALITY"); - display_vcard_item(barejid, "Locality", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "REGION"); - display_vcard_item(barejid, "Region", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "PCODE"); - display_vcard_item(barejid, "Postal code", vcard_attrib, data); - data = xmlnode_get_tag_data(x, "CTRY"); - display_vcard_item(barejid, "Country", vcard_attrib, data); - } else if (!strcmp(p, "TEL")) { // Telephone - data = xmlnode_get_tag_data(x, "NUMBER"); - if (data) { - if (xmlnode_get_tag(x, "VOICE")) - vcard_attrib |= vcard_voice; - if (xmlnode_get_tag(x, "FAX")) - vcard_attrib |= vcard_fax; - if (xmlnode_get_tag(x, "CELL")) - vcard_attrib |= vcard_cell; - display_vcard_item(barejid, "Phone", vcard_attrib, data); - } - } else if (!strcmp(p, "EMAIL")) { // Email - if (xmlnode_get_tag(x, "INTERNET")) - vcard_attrib |= vcard_inet; - data = xmlnode_get_tag_data(x, "USERID"); - display_vcard_item(barejid, "Email", vcard_attrib, data); - } - } - } -} - -static int iqscallback_vcard(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - xmlnode ansqry; - char *p; - char *bjid; - char *buf; - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return -1; - - // Display IQ result sender... - p = xmlnode_get_attrib(xml_result, "from"); - if (!p) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name)."); - return 0; - } - bjid = p; - - buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - - // Get the vCard node - ansqry = xmlnode_get_tag(xml_result, "vCard"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!"); - g_free(buf); - return 0; - } - - // bjid should really be the "bare JID", let's strip the resource - p = strchr(bjid, JID_RESOURCE_SEPARATOR); - if (p) *p = '\0'; - - scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); - g_free(buf); - - // Get result data... - handle_vcard_node(bjid, ansqry); - return 0; -} - -void request_vcard(const char *bjid) -{ - eviqs *iqn; - - // Create a new IQ structure. We use NULL for the namespace because - // we'll have to use a special tag, not the usual "query" one. - iqn = iqs_new(JPACKET__GET, NULL, "vcard", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", bjid); - // Remove the useless tag, and insert a vCard one. - xmlnode_hide(xmlnode_get_tag(iqn->xmldata, "query")); - xmlnode_put_attrib(xmlnode_insert_tag(iqn->xmldata, "vCard"), - "xmlns", NS_VCARD); - iqn->callback = &iqscallback_vcard; - jab_send(jc, iqn->xmldata); -} - -static void storage_bookmarks_parse_conference(xmlnode xmldata) -{ - const char *fjid, *name, *autojoin; - const char *pstatus, *awhois; - char *bjid; - GSList *room_elt; - - fjid = xmlnode_get_attrib(xmldata, "jid"); - if (!fjid) - return; - name = xmlnode_get_attrib(xmldata, "name"); - autojoin = xmlnode_get_attrib(xmldata, "autojoin"); - awhois = xmlnode_get_attrib(xmldata, "autowhois"); - pstatus = xmlnode_get_tag_data(xmldata, "print_status"); - - bjid = jidtodisp(fjid); // Bare jid - - // Make sure this is a room (it can be a conversion user->room) - room_elt = roster_find(bjid, jidsearch, 0); - if (!room_elt) { - room_elt = roster_add_user(bjid, name, NULL, ROSTER_TYPE_ROOM, - sub_none, -1); - } else { - buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); - /* - // If the name is available, should we use it? - // I don't think so, it would be confusing because this item is already - // in the roster. - if (name) - buddy_setname(room_elt->data, name); - */ - } - - // Set the print_status and auto_whois values - if (pstatus) { - enum room_printstatus i; - for (i = status_none; i <= status_all; i++) - if (!strcasecmp(pstatus, strprintstatus[i])) - break; - if (i <= status_all) - buddy_setprintstatus(room_elt->data, i); - } - if (awhois) { - enum room_autowhois i = autowhois_default; - if (!strcmp(awhois, "1")) - i = autowhois_on; - else if (!strcmp(awhois, "0")) - i = autowhois_off; - if (i != autowhois_default) - buddy_setautowhois(room_elt->data, i); - } - - // Is autojoin set? - // If it is, we'll look up for more information (nick? password?) and - // try to join the room. - if (autojoin && !strcmp(autojoin, "1")) { - char *nick, *passwd; - char *tmpnick = NULL; - nick = xmlnode_get_tag_data(xmldata, "nick"); - passwd = xmlnode_get_tag_data(xmldata, "password"); - if (!nick || !*nick) - nick = tmpnick = default_muc_nickname(NULL); - // Let's join now - scr_LogPrint(LPRINT_LOGNORM, "Auto-join bookmark <%s>", bjid); - jb_room_join(bjid, nick, passwd); - g_free(tmpnick); - } - g_free(bjid); -} - -static int iqscallback_storage_bookmarks(eviqs *iqp, xmlnode xml_result, - guint iqcontext) -{ - xmlnode x, ansqry; - char *p; - - if (iqcontext == IQS_CONTEXT_ERROR) { - // No server support, or no bookmarks? - p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); - if (p && !strcmp(p, "item-not-found")) { - // item-no-found means the server has Private Storage, but it's - // currently empty. - xmlnode_free(bookmarks); - bookmarks = xmlnode_new_tag("storage"); - xmlnode_put_attrib(bookmarks, "xmlns", "storage:bookmarks"); - // We return 0 so that the IQ error message be - // not displayed, as it isn't a real error. - return 0; - } - return -1; // Unhandled error - } - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return 0; - - ansqry = xmlnode_get_tag(xml_result, "query"); - ansqry = xmlnode_get_tag(ansqry, "storage"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)"); - return 0; - } - - // Walk through the storage tags - x = xmlnode_get_firstchild(ansqry); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - p = xmlnode_get_name(x); - // If the current node is a conference item, parse it and update the roster - if (p && !strcmp(p, "conference")) - storage_bookmarks_parse_conference(x); - } - // Copy the bookmarks node - xmlnode_free(bookmarks); - bookmarks = xmlnode_dup(ansqry); - return 0; -} - -static void request_storage_bookmarks(void) -{ - eviqs *iqn; - xmlnode x; - - iqn = iqs_new(JPACKET__GET, NS_PRIVATE, "storage", IQS_DEFAULT_TIMEOUT); - - x = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "storage"); - xmlnode_put_attrib(x, "xmlns", "storage:bookmarks"); - - iqn->callback = &iqscallback_storage_bookmarks; - jab_send(jc, iqn->xmldata); -} - -static int iqscallback_storage_rosternotes(eviqs *iqp, xmlnode xml_result, - guint iqcontext) -{ - xmlnode ansqry; - - if (iqcontext == IQS_CONTEXT_ERROR) { - const char *p; - // No server support, or no roster notes? - p = xmlnode_get_name(xmlnode_get_firstchild(xml_result)); - if (p && !strcmp(p, "item-not-found")) { - // item-no-found means the server has Private Storage, but it's - // currently empty. - xmlnode_free(rosternotes); - rosternotes = xmlnode_new_tag("storage"); - xmlnode_put_attrib(rosternotes, "xmlns", "storage:rosternotes"); - // We return 0 so that the IQ error message be - // not displayed, as it isn't a real error. - return 0; - } - return -1; // Unhandled error - } - - // Leave now if we cannot process xml_result - if (!xml_result || iqcontext) return 0; - - ansqry = xmlnode_get_tag(xml_result, "query"); - ansqry = xmlnode_get_tag(ansqry, "storage"); - if (!ansqry) { - scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! " - "(storage:rosternotes)"); - return 0; - } - // Copy the rosternotes node - xmlnode_free(rosternotes); - rosternotes = xmlnode_dup(ansqry); - return 0; -} - -static void request_storage_rosternotes(void) -{ - eviqs *iqn; - xmlnode x; - - iqn = iqs_new(JPACKET__GET, NS_PRIVATE, "storage", IQS_DEFAULT_TIMEOUT); - - x = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "storage"); - xmlnode_put_attrib(x, "xmlns", "storage:rosternotes"); - - iqn->callback = &iqscallback_storage_rosternotes; - jab_send(jc, iqn->xmldata); -} - -int iqscallback_auth(eviqs *iqp, xmlnode xml_result, guint iqcontext) -{ - if (iqcontext == IQS_CONTEXT_ERROR) - return -1; - - if (jstate == STATE_GETAUTH) { - eviqs *iqn; - - if (xml_result) { - xmlnode x = xmlnode_get_tag(xml_result, "query"); - if (x && !xmlnode_get_tag(x, "digest")) - jc->sid = 0; - } - - iqn = iqs_new(JPACKET__SET, NS_AUTH, "auth", IQS_DEFAULT_TIMEOUT); - iqn->callback = &iqscallback_auth; - jab_auth_mcabber(jc, iqn->xmldata); - jab_send(jc, iqn->xmldata); - jstate = STATE_SENDAUTH; - } else if (jstate == STATE_SENDAUTH) { - request_roster(); - request_storage_bookmarks(); - request_storage_rosternotes(); - jstate = STATE_LOGGED; - } - return 0; -} - -static void handle_iq_result(jconn conn, char *from, xmlnode xmldata) -{ - char *id = xmlnode_get_attrib(xmldata, "id"); - - if (!id) { - scr_LogPrint(LPRINT_LOG, "IQ result stanza with no ID, ignored."); - return; - } - - (void)iqs_callback(id, xmldata, IQS_CONTEXT_RESULT); -} - -// FIXME highly duplicated code -static void send_iq_not_implemented(jconn conn, char *from, xmlnode xmldata) -{ - xmlnode x, y, z; - // Not implemented. - x = xmlnode_dup(xmldata); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_hide_attrib(x, "from"); - - xmlnode_put_attrib(x, "type", TMSG_ERROR); - y = xmlnode_insert_tag(x, TMSG_ERROR); - xmlnode_put_attrib(y, "code", "501"); - xmlnode_put_attrib(y, "type", "cancel"); - z = xmlnode_insert_tag(y, "feature-not-implemented"); - xmlnode_put_attrib(z, "xmlns", NS_XMPP_STANZAS); - - jab_send(conn, x); - xmlnode_free(x); -} - -// FIXME highly duplicated code -static void send_iq_not_available(jconn conn, char *from, xmlnode xmldata) -{ - xmlnode x, y, z; - // Not available. - x = xmlnode_dup(xmldata); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_hide_attrib(x, "from"); - - xmlnode_put_attrib(x, "type", TMSG_ERROR); - y = xmlnode_insert_tag(x, TMSG_ERROR); - xmlnode_put_attrib(y, "code", "503"); - xmlnode_put_attrib(y, "type", "cancel"); - z = xmlnode_insert_tag(y, "service-unavailable"); - xmlnode_put_attrib(z, "xmlns", NS_XMPP_STANZAS); - - jab_send(conn, x); - xmlnode_free(x); -} - -/* -static void send_iq_commands_bad_action(jconn conn, char *from, xmlnode xmldata) -{ - xmlnode x, y, z; - - x = xmlnode_dup(xmldata); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_hide_attrib(x, "from"); - - xmlnode_put_attrib(x, "type", TMSG_ERROR); - y = xmlnode_insert_tag(x, TMSG_ERROR); - xmlnode_put_attrib(y, "code", "400"); - xmlnode_put_attrib(y, "type", "modify"); - z = xmlnode_insert_tag(y, "bad-request"); - xmlnode_put_attrib(z, "xmlns", NS_XMPP_STANZAS); - z = xmlnode_insert_tag(y, "bad-action"); - xmlnode_put_attrib(z, "xmlns", NS_COMMANDS); - - jab_send(conn, x); - xmlnode_free(x); -} -*/ - -static void send_iq_forbidden(jconn conn, char *from, xmlnode xmldata) -{ - xmlnode x, y, z; - - x = xmlnode_dup(xmldata); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_hide_attrib(x, "from"); - - xmlnode_put_attrib(x, "type", TMSG_ERROR); - y = xmlnode_insert_tag(x, TMSG_ERROR); - xmlnode_put_attrib(y, "code", "403"); - xmlnode_put_attrib(y, "type", "cancel"); - z = xmlnode_insert_tag(y, "forbidden"); - xmlnode_put_attrib(z, "xmlns", NS_XMPP_STANZAS); - - jab_send(conn, x); - xmlnode_free(x); -} - -static void send_iq_commands_malformed_action(jconn conn, char *from, - xmlnode xmldata) -{ - xmlnode x, y, z; - - x = xmlnode_dup(xmldata); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_hide_attrib(x, "from"); - - xmlnode_put_attrib(x, "type", TMSG_ERROR); - y = xmlnode_insert_tag(x, TMSG_ERROR); - xmlnode_put_attrib(y, "code", "400"); - xmlnode_put_attrib(y, "type", "modify"); - z = xmlnode_insert_tag(y, "bad-request"); - xmlnode_put_attrib(z, "xmlns", NS_XMPP_STANZAS); - z = xmlnode_insert_tag(y, "malformed-action"); - xmlnode_put_attrib(z, "xmlns", NS_COMMANDS); - - jab_send(conn, x); - xmlnode_free(x); -} - -static void handle_iq_commands_list(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - jid requester_jid; - const struct adhoc_command *command; - const char *node; - bool from_self; - - x = jutil_iqnew(JPACKET__RESULT, NS_DISCO_ITEMS); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "query"); - - node = xmlnode_get_attrib(xmlnode_get_tag(xmldata, "query"), "node"); - if (node) - xmlnode_put_attrib(myquery, "node", node); - - requester_jid = jid_new(conn->p, xmlnode_get_attrib(xmldata, "from")); - from_self = !jid_cmpx(conn->user, requester_jid, JID_USER | JID_SERVER); - - for (command = adhoc_command_list ; command->name ; command++) { - if (!command->only_for_self || from_self) { - xmlnode item; - item = xmlnode_insert_tag(myquery, "item"); - xmlnode_put_attrib(item, "node", command->name); - xmlnode_put_attrib(item, "name", command->description); - xmlnode_put_attrib(item, "jid", jid_full(conn->user)); - } - } - - jab_send(jc, x); - xmlnode_free(x); -} - -static void xmlnode_insert_dataform_result_message(xmlnode node, char *message) -{ - xmlnode x, field, value; - - x = xmlnode_insert_tag(node, "x"); - xmlnode_put_attrib(x, "type", "result"); - xmlnode_put_attrib(x, "xmlns", "jabber:x:data"); - - field = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(field, "type", "text-single"); - xmlnode_put_attrib(field, "var", "message"); - - value = xmlnode_insert_tag(field, "value"); - xmlnode_insert_cdata(value, message, -1); -} - -static char *generate_session_id(char *prefix) -{ - char *result; - static int counter = 0; - counter++; - // TODO better use timestamp? - result = g_strdup_printf("%s-%i", prefix, counter); - return result; -} - -static void handle_iq_command_set_status(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - char *action, *node, *sessionid; - xmlnode iq, command, x, y; - const struct adhoc_status *s; - - x = xmlnode_get_tag(xmldata, "command"); - action = xmlnode_get_attrib(x, "action"); - node = xmlnode_get_attrib(x, "node"); - sessionid = xmlnode_get_attrib(x, "sessionid"); - - iq = xmlnode_new_tag("iq"); - command = xmlnode_insert_tag(iq, "command"); - xmlnode_put_attrib(command, "node", node); - xmlnode_put_attrib(command, "xmlns", NS_COMMANDS); - - if (!sessionid) { - xmlnode value; - - sessionid = generate_session_id("set-status"); - xmlnode_put_attrib(command, "sessionid", sessionid); - g_free(sessionid); - sessionid = NULL; - xmlnode_put_attrib(command, "status", "executing"); - - x = xmlnode_insert_tag(command, "x"); - xmlnode_put_attrib(x, "type", "form"); - xmlnode_put_attrib(x, "xmlns", "jabber:x:data"); - - y = xmlnode_insert_tag(x, "title"); - xmlnode_insert_cdata(y, "Change Status", -1); - - y = xmlnode_insert_tag(x, "instructions"); - xmlnode_insert_cdata(y, "Choose the status and status message", -1); - - // TODO see if factorisation is possible - // (with xmlnode_insert_dataform_result_message) - y = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(y, "type", "hidden"); - xmlnode_put_attrib(y, "var", "FORM_TYPE"); - - value = xmlnode_insert_tag(y, "value"); - xmlnode_insert_cdata(value, "http://jabber.org/protocol/rc", -1); - - y = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(y, "type", "list-single"); - xmlnode_put_attrib(y, "var", "status"); - xmlnode_put_attrib(y, "label", "Status"); - xmlnode_insert_tag(y, "required"); - - value = xmlnode_insert_tag(y, "value"); - // TODO current status - xmlnode_insert_cdata(value, "online", -1); - for (s = adhoc_status_list; s->name; s++) { - xmlnode option = xmlnode_insert_tag(y, "option"); - value = xmlnode_insert_tag(option, "value"); - xmlnode_insert_cdata(value, s->name, -1); - xmlnode_put_attrib(option, "label", s->description); - } - // TODO add priority ? - // I do not think this is useful, user should not have to care of the - // priority like gossip and gajim do (misc) - y = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(y, "type", "text-single"); - xmlnode_put_attrib(y, "var", "status-message"); - xmlnode_put_attrib(y, "label", "Message"); - } else if (action && !strcmp(action, "cancel")) { - xmlnode_put_attrib(command, "status", "canceled"); - } else { // (if sessionid and not canceled) - y = xmlnode_get_tag(x, "x?xmlns=jabber:x:data"); - if (y) { - char *value, *message; - value = xmlnode_get_tag_data(xmlnode_get_tag(y, "field?var=status"), - "value"); - message = xmlnode_get_tag_data(xmlnode_get_tag(y, - "field?var=status-message"), "value"); - if (value) { - for (s = adhoc_status_list; s->name && strcmp(s->name, value); s++); - if (s->name) { - char *status = g_strdup_printf("%s %s", s->status, - message ? message : ""); - cmd_setstatus(NULL, status); - g_free(status); - xmlnode_put_attrib(command, "status", "completed"); - xmlnode_put_attrib(iq, "type", "result"); - xmlnode_insert_dataform_result_message(command, - "Status has been changed"); - } - } - } - } - if (sessionid) - xmlnode_put_attrib(command, "sessionid", sessionid); - xmlnode_put_attrib(iq, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_put_attrib(iq, "id", id); - jab_send(jc, iq); - xmlnode_free(iq); -} - -static void _callback_foreach_buddy_groupchat(gpointer rosterdata, void *param) -{ - xmlnode value, option; - xmlnode *field; - const char *room_jid, *nickname; - char *desc; - - room_jid = buddy_getjid(rosterdata); - if (!room_jid) return; - nickname = buddy_getnickname(rosterdata); - if (!nickname) return; - field = param; - - option = xmlnode_insert_tag(*field, "option"); - value = xmlnode_insert_tag(option, "value"); - xmlnode_insert_cdata(value, room_jid, -1); - desc = g_strdup_printf("%s on %s", nickname, room_jid); - xmlnode_put_attrib(option, "label", desc); - g_free(desc); -} - -static void handle_iq_command_leave_groupchats(jconn conn, char *from, - const char *id, xmlnode xmldata) -{ - char *action, *node, *sessionid; - xmlnode iq, command, x; - - x = xmlnode_get_tag(xmldata, "command"); - action = xmlnode_get_attrib(x, "action"); - node = xmlnode_get_attrib(x, "node"); - sessionid = xmlnode_get_attrib(x, "sessionid"); - - iq = xmlnode_new_tag("iq"); - command = xmlnode_insert_tag(iq, "command"); - xmlnode_put_attrib(command, "node", node); - xmlnode_put_attrib(command, "xmlns", NS_COMMANDS); - - if (!sessionid) { - xmlnode title, instructions, field, value; - - sessionid = generate_session_id("leave-groupchats"); - xmlnode_put_attrib(command, "sessionid", sessionid); - g_free(sessionid); - sessionid = NULL; - xmlnode_put_attrib(command, "status", "executing"); - - x = xmlnode_insert_tag(command, "x"); - xmlnode_put_attrib(x, "type", "form"); - xmlnode_put_attrib(x, "xmlns", "jabber:x:data"); - - title = xmlnode_insert_tag(x, "title"); - xmlnode_insert_cdata(title, "Leave groupchat(s)", -1); - - instructions = xmlnode_insert_tag(x, "instructions"); - xmlnode_insert_cdata(instructions, "What groupchats do you want to leave?", - -1); - - field = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(field, "type", "hidden"); - xmlnode_put_attrib(field, "var", "FORM_TYPE"); - - value = xmlnode_insert_tag(field, "value"); - xmlnode_insert_cdata(value, "http://jabber.org/protocol/rc", -1); - - field = xmlnode_insert_tag(x, "field"); - xmlnode_put_attrib(field, "type", "list-multi"); - xmlnode_put_attrib(field, "var", "groupchats"); - xmlnode_put_attrib(field, "label", "Groupchats: "); - xmlnode_insert_tag(field, "required"); - - foreach_buddy(ROSTER_TYPE_ROOM, &_callback_foreach_buddy_groupchat, &field); - } else if (action && !strcmp(action, "cancel")) { - xmlnode_put_attrib(command, "status", "canceled"); - } else { // (if sessionid and not canceled) - xmlnode form = xmlnode_get_tag(x, "x?xmlns=jabber:x:data"); - if (form) { - xmlnode x, gc; - - xmlnode_put_attrib(command, "status", "completed"); - gc = xmlnode_get_tag(form, "field?var=groupchats"); - - for (x = xmlnode_get_firstchild(gc) ; x ; x = xmlnode_get_nextsibling(x)) - { - char* to_leave = xmlnode_get_tag_data(x, "value"); - if (to_leave) { - GList* b = buddy_search_jid(to_leave); - if (b) - cmd_room_leave(b->data, "Requested by remote command"); - } - } - xmlnode_put_attrib(iq, "type", "result"); - xmlnode_insert_dataform_result_message(command, - "Groupchats have been left"); - } - } - if (sessionid) - xmlnode_put_attrib(command, "sessionid", sessionid); - xmlnode_put_attrib(iq, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_put_attrib(iq, "id", id); - jab_send(jc, iq); - xmlnode_free(iq); -} - -static void handle_iq_commands(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - jid requester_jid; - xmlnode x; - const struct adhoc_command *command; - - requester_jid = jid_new(conn->p, xmlnode_get_attrib(xmldata, "from")); - x = xmlnode_get_tag(xmldata, "command"); - if (!jid_cmpx(conn->user, requester_jid, JID_USER | JID_SERVER) ) { - char *action, *node; - action = xmlnode_get_attrib(x, "action"); - node = xmlnode_get_attrib(x, "node"); - // action can be NULL, in which case it seems to take the default, - // ie execute - if (!action || !strcmp(action, "execute") || !strcmp(action, "cancel") - || !strcmp(action, "next") || !strcmp(action, "complete")) { - for (command = adhoc_command_list; command->name; command++) { - if (!strcmp(node, command->name)) - command->callback(conn, from, id, xmldata); - } - // "prev" action will get there, as we do not implement it, - // and do not authorize it - } else { - send_iq_commands_malformed_action(conn, from, xmldata); - } - } else { - send_iq_forbidden(conn, from, xmldata); - } -} - -static void handle_iq_disco_items(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - const char *node; - x = xmlnode_get_tag(xmldata, "query"); - node = xmlnode_get_attrib(x, "node"); - if (node) { - if (!strcmp(node, NS_COMMANDS)) { - handle_iq_commands_list(conn, from, id, xmldata); - } else { - send_iq_not_implemented(conn, from, xmldata); - } - } else { - // not sure about this one - send_iq_not_implemented(conn, from, xmldata); - } -} - -// disco_info_set_ext(ansquery, ext) -// Add features attributes to ansquery for extension ext. -static void disco_info_set_ext(xmlnode ansquery, const char *ext) -{ - char *nodename; - nodename = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, ext); - xmlnode_put_attrib(ansquery, "node", nodename); - g_free(nodename); - if (!strcasecmp(ext, "csn")) { - // I guess it's ok to send this even if it's not compiled in. - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_CHATSTATES); - } - if (!strcasecmp(ext, "iql")) { - // I guess it's ok to send this even if it's not compiled in. - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_LAST); - } -} - -// disco_info_set_default(ansquery, entitycaps) -// Add features attributes to ansquery. If entitycaps is TRUE, assume -// that we're answering an Entity Caps request (if not, the request was -// a basic discovery query). -// Please change the entity version string if you modify mcabber disco -// source code, so that it doesn't conflict with the upstream client. -static void disco_info_set_default(xmlnode ansquery, guint entitycaps) -{ - xmlnode y; - char *eversion; - - eversion = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, entity_version()); - xmlnode_put_attrib(ansquery, "node", eversion); - g_free(eversion); - - y = xmlnode_insert_tag(ansquery, "identity"); - xmlnode_put_attrib(y, "category", "client"); - xmlnode_put_attrib(y, "type", "pc"); - xmlnode_put_attrib(y, "name", PACKAGE_NAME); - - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_DISCO_INFO); - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_MUC); -#ifdef JEP0085 - // Advertise ChatStates only if we're not using Entity Capabilities - if (!entitycaps) - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_CHATSTATES); -#endif - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_TIME); - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_XMPP_TIME); - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_VERSION); - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_PING); - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_COMMANDS); - if (!entitycaps) - xmlnode_put_attrib(xmlnode_insert_tag(ansquery, "feature"), - "var", NS_LAST); -} - -static void handle_iq_disco_info(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - char *node; - - x = jutil_iqnew(JPACKET__RESULT, NS_DISCO_INFO); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "query"); - - node = xmlnode_get_attrib(xmlnode_get_tag(xmldata, "query"), "node"); - if (node && startswith(node, MCABBER_CAPS_NODE "#", FALSE)) { - const char *param = node+strlen(MCABBER_CAPS_NODE)+1; - if (!strcmp(param, entity_version())) - disco_info_set_default(myquery, TRUE); // client#version - else - disco_info_set_ext(myquery, param); // client#extension - } else { - // Basic discovery request - disco_info_set_default(myquery, FALSE); - } - - jab_send(jc, x); - xmlnode_free(x); -} - -double seconds_since_last_use(void) -{ - return difftime(time(NULL), iqlast); -} - -static void handle_iq_last(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - char *seconds; - - if (!settings_opt_get_int("iq_hide_requests")) { - scr_LogPrint(LPRINT_LOGNORM, "Received an IQ last time request from <%s>", - from); - } - - x = jutil_iqnew(JPACKET__RESULT, NS_LAST); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "query"); - seconds = g_strdup_printf("%.0f", seconds_since_last_use()); - xmlnode_put_attrib(myquery, "seconds", seconds); - g_free(seconds); - - jab_send(jc, x); - xmlnode_free(x); -} - -static void handle_iq_ping(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - x = jutil_iqresult(xmldata); - jab_send(jc, x); -} - -static void handle_iq_version(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - char *os = NULL; - char *ver = mcabber_version(); - - if (!settings_opt_get_int("iq_hide_requests")) { - scr_LogPrint(LPRINT_LOGNORM, "Received an IQ version request from <%s>", - from); - } - - if (!settings_opt_get_int("iq_version_hide_os")) { - struct utsname osinfo; - uname(&osinfo); - os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, - osinfo.machine); - } - - x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "query"); - - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "name"), PACKAGE_NAME, -1); - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "version"), ver, -1); - if (os) { - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "os"), os, -1); - g_free(os); - } - - g_free(ver); - jab_send(jc, x); - xmlnode_free(x); -} - -// This function borrows some code from the Pidgin project -static void handle_iq_time(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - char *buf, *utf8_buf; - time_t now_t; - struct tm *now; - - time(&now_t); - - if (!settings_opt_get_int("iq_hide_requests")) { - scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", from); - } - - buf = g_new0(char, 512); - - x = jutil_iqnew(JPACKET__RESULT, NS_TIME); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "query"); - - now = gmtime(&now_t); - - strftime(buf, 512, "%Y%m%dT%T", now); - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "utc"), buf, -1); - - now = localtime(&now_t); - - strftime(buf, 512, "%Z", now); - if ((utf8_buf = to_utf8(buf))) { - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "tz"), utf8_buf, -1); - g_free(utf8_buf); - } - - strftime(buf, 512, "%d %b %Y %T", now); - if ((utf8_buf = to_utf8(buf))) { - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "display"), utf8_buf, -1); - g_free(utf8_buf); - } - - jab_send(jc, x); - xmlnode_free(x); - g_free(buf); -} - -// This function borrows some code from the Pidgin project -static void handle_iq_time202(jconn conn, char *from, const char *id, - xmlnode xmldata) -{ - xmlnode x; - xmlnode myquery; - char *buf, *utf8_buf; - time_t now_t; - struct tm *now; - char const *sign; - int diff = 0; - - time(&now_t); - - if (!settings_opt_get_int("iq_hide_requests")) { - scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", from); - } - - buf = g_new0(char, 512); - - x = jutil_iqnew(JPACKET__RESULT, NULL); - xmlnode_hide(xmlnode_get_tag(x, "query")); - xmlnode_put_attrib(xmlnode_insert_tag(x, "time"), "xmlns", NS_XMPP_TIME); - xmlnode_put_attrib(x, "id", id); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - myquery = xmlnode_get_tag(x, "time"); - - now = localtime(&now_t); - - if (now->tm_isdst >= 0) { -#if defined HAVE_TM_GMTOFF - diff = now->tm_gmtoff; -#elif defined HAVE_TIMEZONE - tzset(); - diff = -timezone; -#endif - } - - if (diff < 0) { - sign = "-"; - diff = -diff; - } else { - sign = "+"; - } - diff /= 60; - snprintf(buf, 512, "%c%02d:%02d", *sign, diff / 60, diff % 60); - if ((utf8_buf = to_utf8(buf))) { - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "tzo"), utf8_buf, -1); - g_free(utf8_buf); - } - - now = gmtime(&now_t); - - strftime(buf, 512, "%Y-%m-%dT%TZ", now); - xmlnode_insert_cdata(xmlnode_insert_tag(myquery, "utc"), buf, -1); - - jab_send(jc, x); - xmlnode_free(x); - g_free(buf); -} - -// This function borrows some code from the Pidgin project -static void handle_iq_get(jconn conn, char *from, xmlnode xmldata) -{ - const char *id, *ns; - xmlnode x; - guint iq_not_implemented = FALSE; - - id = xmlnode_get_attrib(xmldata, "id"); - if (!id) { - scr_LogPrint(LPRINT_LOG, "IQ get stanza with no ID, ignored."); - return; - } - - x = xmlnode_get_tag(xmldata, "ping"); - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_PING)) { - handle_iq_ping(conn, from, id, xmldata); - return; - } - - x = xmlnode_get_tag(xmldata, "time"); - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_XMPP_TIME)) { - handle_iq_time202(conn, from, id, xmldata); - return; - } - - x = xmlnode_get_tag(xmldata, "query"); - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_DISCO_INFO)) { - handle_iq_disco_info(conn, from, id, xmldata); - } else if (ns && !strcmp(ns, NS_DISCO_ITEMS)) { - handle_iq_disco_items(conn, from, id, xmldata); - } else if (ns && !strcmp(ns, NS_VERSION)) { - handle_iq_version(conn, from, id, xmldata); - } else if (ns && !strcmp(ns, NS_LAST)) { - if (!settings_opt_get_int("iq_last_disable") && - (!settings_opt_get_int("iq_last_disable_when_notavail") || - jb_getstatus() != notavail)) - handle_iq_last(conn, from, id, xmldata); - else - send_iq_not_available(conn, from, xmldata); - } else if (ns && !strcmp(ns, NS_TIME)) { - handle_iq_time(conn, from, id, xmldata); - } else { - iq_not_implemented = TRUE; - } - - if (!iq_not_implemented) - return; - - send_iq_not_implemented(conn, from, xmldata); -} - -static void handle_iq_set(jconn conn, char *from, xmlnode xmldata) -{ - const char *id, *ns; - xmlnode x; - guint iq_not_implemented = FALSE; - - id = xmlnode_get_attrib(xmldata, "id"); - if (!id) - scr_LogPrint(LPRINT_LOG, "IQ set stanza with no ID..."); - - x = xmlnode_get_tag(xmldata, "query"); - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_ROSTER)) { - handle_iq_roster(x); - } else { - x = xmlnode_get_tag(xmldata, "command"); - ns = xmlnode_get_attrib(x, "xmlns"); - if (ns && !strcmp(ns, NS_COMMANDS)) { - handle_iq_commands(conn, from, id, xmldata); - return; - } else { - iq_not_implemented = TRUE; - } - } - - if (!id) return; - - if (!iq_not_implemented) { - x = xmlnode_new_tag("iq"); - xmlnode_put_attrib(x, "to", xmlnode_get_attrib(xmldata, "from")); - xmlnode_put_attrib(x, "type", "result"); - xmlnode_put_attrib(x, "id", id); - jab_send(conn, x); - xmlnode_free(x); - } else { - send_iq_not_implemented(conn, from, xmldata); - } -} - -void handle_packet_iq(jconn conn, char *type, char *from, xmlnode xmldata) -{ - if (!type) - return; - - if (!strcmp(type, "result")) { - handle_iq_result(conn, from, xmldata); - } else if (!strcmp(type, "get")) { - handle_iq_get(conn, from, xmldata); - } else if (!strcmp(type, "set")) { - handle_iq_set(conn, from, xmldata); - } else if (!strcmp(type, TMSG_ERROR)) { - // Display a message only if the error isn't caught by a callback. - xmlnode x = xmlnode_get_tag(xmldata, TMSG_ERROR); - if (iqs_callback(xmlnode_get_attrib(xmldata, "id"), x, IQS_CONTEXT_ERROR)) - display_server_error(x); - } -} - -// send_storage_bookmarks() -// Send the current bookmarks node to update the server. -// Note: the sender should check we're online. -void send_storage_bookmarks(void) -{ - eviqs *iqn; - - if (!bookmarks) return; - - iqn = iqs_new(JPACKET__SET, NS_PRIVATE, "storage", IQS_DEFAULT_TIMEOUT); - xmlnode_insert_node(xmlnode_get_tag(iqn->xmldata, "query"), bookmarks); - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX -} - -// send_storage_rosternotes() -// Send the current rosternotes node to update the server. -// Note: the sender should check we're online. -void send_storage_rosternotes(void) -{ - eviqs *iqn; - - if (!rosternotes) return; - - iqn = iqs_new(JPACKET__SET, NS_PRIVATE, "storage", IQS_DEFAULT_TIMEOUT); - xmlnode_insert_node(xmlnode_get_tag(iqn->xmldata, "query"), rosternotes); - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX -} - -/* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/jab_priv.h --- a/mcabber/src/jab_priv.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -#ifndef __JAB_PRIV_H__ -#define __JAB_PRIV_H__ 1 - -/* This header file declares functions used by jab*.c only. */ - -#include "jabglue.h" -#include "events.h" - -/* XEP-0115 (Entity Capabilities) node */ -#define MCABBER_CAPS_NODE "http://mcabber.com/caps" - -#define JABBER_AGENT_GROUP "Jabber Agents" - -enum enum_jstate { - STATE_CONNECTING, - STATE_GETAUTH, - STATE_SENDAUTH, - STATE_LOGGED -}; - -struct T_presence { - enum imstatus st; - const char *msg; -}; - - -#define IQS_DEFAULT_TIMEOUT 90U -#define IQS_MAX_TIMEOUT 600U - -#define IQS_CONTEXT_RESULT 0U /* Normal result should be zero */ -#define IQS_CONTEXT_TIMEOUT 1U -#define IQS_CONTEXT_ERROR 2U - -extern enum enum_jstate jstate; -extern xmlnode bookmarks, rosternotes; - -const char *entity_version(void); - -extern time_t iqlast; /* last message/status change time */ - -void handle_packet_iq(jconn conn, char *type, char *from, xmlnode xmldata); -void display_server_error(xmlnode x); -eviqs *iqs_new(guint8 type, const char *ns, const char *prefix, time_t timeout); -int iqs_del(const char *iqid); -int iqs_callback(const char *iqid, xmlnode xml_result, guint iqcontext); -void iqs_check_timeout(time_t now_t); -int iqscallback_auth(eviqs *iqp, xmlnode xml_result, guint iqcontext); -void request_version(const char *fulljid); -void request_time(const char *fulljid); -void request_last(const char *fulljid); -void request_vcard(const char *barejid); -void send_storage_bookmarks(void); -void send_storage_rosternotes(void); - -#endif /* __JAB_PRIV_H__ */ - -/* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3041 +0,0 @@ -/* - * jabglue.c -- Jabber protocol handling - * - * Copyright (C) 2005-2008 Mikael Berthe - * Parts come from the centericq project: - * Copyright (C) 2002-2005 by Konstantin Klyagin - * - * 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 "../libjabber/jabber.h" -#include "jabglue.h" -#include "jab_priv.h" -#include "roster.h" -#include "screen.h" -#include "hooks.h" -#include "utils.h" -#include "settings.h" -#include "hbuf.h" -#include "histolog.h" -#include "commands.h" -#include "pgp.h" -#include "otr.h" -#include "fifo.h" - -#define JABBERPORT 5222 -#define JABBERSSLPORT 5223 - -#define RECONNECTION_TIMEOUT 60L - -jconn jc; -guint AutoConnection; -enum enum_jstate jstate; - -char imstatus2char[imstatus_size+1] = { - '_', 'o', 'f', 'd', 'n', 'a', 'i', '\0' -}; - -static char *imstatus_showmap[] = { - "", - "", - "chat", - "dnd", - "xa", - "away", - "" -}; - -static time_t LastPingTime; -static unsigned int KeepaliveDelay; -static enum imstatus mystatus = offline; -static enum imstatus mywantedstatus = available; -static gchar *mystatusmsg; -static unsigned char online; - -static void statehandler(jconn, int); -static void packethandler(jconn, jpacket); -static void handle_state_events(char* from, xmlnode xmldata); - -static int evscallback_invitation(eviqs *evp, guint evcontext); - -inline void update_last_use(void); - - -static void logger(jconn j, int io, const char *buf) -{ - scr_LogPrint(LPRINT_DEBUG, "%03s: %s", ((io == 0) ? "OUT" : "IN"), buf); -} - -// jidtodisp(jid) -// Strips the resource part from the jid -// The caller should g_free the result after use. -char *jidtodisp(const char *fjid) -{ - char *ptr; - char *alias; - - alias = g_strdup(fjid); - - if ((ptr = strchr(alias, JID_RESOURCE_SEPARATOR)) != NULL) { - *ptr = 0; - } - return alias; -} - -char *compose_jid(const char *username, const char *servername, - const char *resource) -{ - char *fjid; - - if (!strchr(username, JID_DOMAIN_SEPARATOR)) { - fjid = g_strdup_printf("%s%c%s%c%s", username, - JID_DOMAIN_SEPARATOR, servername, - JID_RESOURCE_SEPARATOR, resource); - } else { - fjid = g_strdup_printf("%s%c%s", username, - JID_RESOURCE_SEPARATOR, resource); - } - return fjid; -} - -unsigned char jb_getonline(void) -{ - return online; -} - -jconn jb_connect(const char *fjid, const char *server, unsigned int port, - int ssl, const char *pass) -{ - if (!port) { - if (ssl) - port = JABBERSSLPORT; - else - port = JABBERPORT; - } - - jb_disconnect(); - - if (!fjid) return jc; - - jc = jab_new((char*)fjid, (char*)pass, (char*)server, port, ssl); - - /* These 3 functions can deal with a NULL jc, no worry... */ - jab_logger(jc, logger); - jab_packet_handler(jc, &packethandler); - jab_state_handler(jc, &statehandler); - - if (jc && jc->user) { - online = TRUE; - jstate = STATE_CONNECTING; - statehandler(0, -1); - jab_start(jc); - } - - return jc; -} - -void jb_disconnect(void) -{ - if (!jc) return; - - if (online) { - // Launch pre-disconnect internal hook - hook_execute_internal("hook-pre-disconnect"); - // Announce it to everyone else - jb_setstatus(offline, NULL, "", FALSE); - // End the XML flow - jb_send_raw(""); - /* - // Free status message - g_free(mystatusmsg); - mystatusmsg = NULL; - */ - } - - // Announce it to the user - statehandler(jc, JCONN_STATE_OFF); - - jab_delete(jc); - jc = NULL; -} - -inline void jb_reset_keepalive() -{ - time(&LastPingTime); -} - -void jb_send_raw(const char *str) -{ - if (jc && online && str) - jab_send_raw(jc, str); -} - -void jb_keepalive() -{ - if (jc && online) - jab_send_raw(jc, " \t "); - jb_reset_keepalive(); -} - -void jb_set_keepalive_delay(unsigned int delay) -{ - KeepaliveDelay = delay; -} - -// check_connection() -// Check if we've been disconnected for a while (predefined timeout), -// and if so try to reconnect. -static void check_connection(void) -{ - static time_t disconnection_timestamp = 0L; - time_t now; - - // Maybe we're voluntarily offline... - if (!AutoConnection) - return; - - // Are we totally disconnected? - if (jc && jc->state != JCONN_STATE_OFF) { - disconnection_timestamp = 0L; - return; - } - - time(&now); - if (!disconnection_timestamp) { - disconnection_timestamp = now; - return; - } - - // If the reconnection_timeout is reached, try to reconnect. - if (now > disconnection_timestamp + RECONNECTION_TIMEOUT) { - mcabber_connect(); - disconnection_timestamp = 0L; - } -} - -void jb_main() -{ - time_t now; - fd_set fds; - long tmout; - struct timeval tv; - static time_t last_eviqs_check = 0L; - int maxfd = 0; - int fifofd; - - FD_ZERO(&fds); - FD_SET(0, &fds); - if (jc && jc->fd > 0) { - FD_SET(jc->fd, &fds); - maxfd = jc->fd; - } - - fifofd = fifo_get_fd(); - if (fifofd > 0) { - FD_SET(fifofd, &fds); - maxfd = MAX(maxfd, fifofd); - } - - tv.tv_sec = 60; - tv.tv_usec = 0; - - if (!online || (jc && jc->state == JCONN_STATE_CONNECTING)) { - if (online) { - // We're connecting and we need to reduce the timeout. - tv.tv_sec = 0; - tv.tv_usec = 250000; - } else { - tv.tv_sec = 30; - // Let's first update the screen, we could sleep for a long time... - scr_DoUpdate(); - } - // If we're not connected, sleep for a while... - if (!online) { - select(1, &fds, NULL, NULL, &tv); - check_connection(); - } else { - select(maxfd + 1, &fds, NULL, NULL, &tv); - jab_start(jc); - } - return; - } - - time(&now); - - if (KeepaliveDelay) { - if (now >= LastPingTime + (time_t)KeepaliveDelay) - tv.tv_sec = 0; - else - tv.tv_sec = LastPingTime + (time_t)KeepaliveDelay - now; - } - - // Check auto-away timeout - tmout = scr_GetAutoAwayTimeout(now); - if (tv.tv_sec > tmout) - tv.tv_sec = tmout; - -#if defined JEP0022 || defined JEP0085 - // Check composing timeout - tmout = scr_GetChatStatesTimeout(now); - if (tv.tv_sec > tmout) - tv.tv_sec = tmout; -#endif - - if (!tv.tv_sec) - tv.tv_usec = 350000; - - scr_DoUpdate(); - if (select(maxfd + 1, &fds, NULL, NULL, &tv) > 0) { - if (FD_ISSET(jc->fd, &fds)) - jab_poll(jc, 0); - } - - if (jstate == STATE_CONNECTING) { - if (jc) { - eviqs *iqn; - xmlnode z; - - iqn = iqs_new(JPACKET__GET, NS_AUTH, "auth", IQS_DEFAULT_TIMEOUT); - iqn->callback = &iqscallback_auth; - - z = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), - "username"); - xmlnode_insert_cdata(z, jc->user->user, (unsigned) -1); - jab_send(jc, iqn->xmldata); - - jstate = STATE_GETAUTH; - } - - if (!jc || jc->state == JCONN_STATE_OFF) { - scr_LogPrint(LPRINT_LOGNORM, "Unable to connect to the server"); - online = FALSE; - } - } - - if (!jc) { - statehandler(jc, JCONN_STATE_OFF); - } else if (jc->state == JCONN_STATE_OFF || jc->fd == -1) { - statehandler(jc, JCONN_STATE_OFF); - } - - time(&now); - - // Check for EV & IQ requests timeouts - if (now > last_eviqs_check + 20) { - iqs_check_timeout(now); - evs_check_timeout(now); - last_eviqs_check = now; - } - - // Keepalive - if (KeepaliveDelay) { - if (now > LastPingTime + (time_t)KeepaliveDelay) - jb_keepalive(); - } -} - -inline enum imstatus jb_getstatus() -{ - return mystatus; -} - -inline const char *jb_getstatusmsg() -{ - return mystatusmsg; -} - -void update_last_use(void) -{ - iqlast = time(NULL); -} - -// insert_entity_capabilities(presence_stanza) -// Entity Capabilities (XEP-0115) -static void insert_entity_capabilities(xmlnode x) -{ - xmlnode y; - const char *ver = entity_version(); - char *exts, *exts2; - - exts = NULL; - - y = xmlnode_insert_tag(x, "c"); - xmlnode_put_attrib(y, "xmlns", NS_CAPS); - xmlnode_put_attrib(y, "node", MCABBER_CAPS_NODE); - xmlnode_put_attrib(y, "ver", ver); -#ifdef JEP0085 - if (!chatstates_disabled) { - exts2 = g_strjoin(" ", "csn", exts, NULL); - g_free(exts); - exts = exts2; - } -#endif - if (!settings_opt_get_int("iq_last_disable")) { - exts2 = g_strjoin(" ", "iql", exts, NULL); - g_free(exts); - exts = exts2; - } - if (exts) { - xmlnode_put_attrib(y, "ext", exts); - g_free(exts); - } -} - -static void roompresence(gpointer room, void *presencedata) -{ - const char *bjid; - const char *nickname; - char *to; - struct T_presence *pres = presencedata; - - if (!buddy_getinsideroom(room)) - return; - - bjid = buddy_getjid(room); - if (!bjid) return; - nickname = buddy_getnickname(room); - if (!nickname) return; - - to = g_strdup_printf("%s/%s", bjid, nickname); - jb_setstatus(pres->st, to, pres->msg, TRUE); - g_free(to); -} - -// presnew(status, recipient, message) -// Create an xmlnode with default presence attributes -// Note: the caller must free the node after use -static xmlnode presnew(enum imstatus st, const char *recipient, - const char *msg) -{ - unsigned int prio; - xmlnode x; - - x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); - - if (recipient) { - xmlnode_put_attrib(x, "to", recipient); - } - - switch(st) { - case away: - case notavail: - case dontdisturb: - case freeforchat: - xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), - imstatus_showmap[st], (unsigned) -1); - break; - - case invisible: - xmlnode_put_attrib(x, "type", "invisible"); - break; - - case offline: - xmlnode_put_attrib(x, "type", "unavailable"); - break; - - default: - break; - } - - if (st == away || st == notavail) - prio = settings_opt_get_int("priority_away"); - else - prio = settings_opt_get_int("priority"); - - if (prio) { - char strprio[8]; - snprintf(strprio, 8, "%d", (int)prio); - xmlnode_insert_cdata(xmlnode_insert_tag(x, "priority"), - strprio, (unsigned) -1); - } - - if (msg) - xmlnode_insert_cdata(xmlnode_insert_tag(x, "status"), msg, (unsigned) -1); - - return x; -} - -void jb_setstatus(enum imstatus st, const char *recipient, const char *msg, - int do_not_sign) -{ - xmlnode x; - - if (msg) { - // The status message has been specified. We'll use it, unless it is - // "-" which is a special case (option meaning "no status message"). - if (!strcmp(msg, "-")) - msg = ""; - } else { - // No status message specified; we'll use: - // a) the default status message (if provided by the user); - // b) the current status message; - // c) no status message (i.e. an empty one). - msg = settings_get_status_msg(st); - if (!msg) { - if (mystatusmsg) - msg = mystatusmsg; - else - msg = ""; - } - } - - // Only send the packet if we're online. - // (But we want to update internal status even when disconnected, - // in order to avoid some problems during network failures) - if (online) { - const char *s_msg = (st != invisible ? msg : NULL); - x = presnew(st, recipient, s_msg); - insert_entity_capabilities(x); // Entity Capabilities (XEP-0115) -#ifdef HAVE_GPGME - if (!do_not_sign && gpg_enabled()) { - char *signature; - signature = gpg_sign(s_msg ? s_msg : ""); - if (signature) { - xmlnode y; - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", NS_SIGNED); - xmlnode_insert_cdata(y, signature, (unsigned) -1); - g_free(signature); - } - } -#endif - jab_send(jc, x); - xmlnode_free(x); - } - - // If we didn't change our _global_ status, we are done - if (recipient) return; - - if (online) { - // Send presence to chatrooms - if (st != invisible) { - struct T_presence room_presence; - room_presence.st = st; - room_presence.msg = msg; - foreach_buddy(ROSTER_TYPE_ROOM, &roompresence, &room_presence); - } - - // We'll have to update the roster if we switch to/from offline because - // we don't know the presences of buddies when offline... - if (mystatus == offline || st == offline) - update_roster = TRUE; - - hk_mystatuschange(0, mystatus, st, (st != invisible ? msg : "")); - mystatus = st; - } - - if (st) - mywantedstatus = st; - - if (msg != mystatusmsg) { - g_free(mystatusmsg); - if (*msg) - mystatusmsg = g_strdup(msg); - else - mystatusmsg = NULL; - } - - if (!Autoaway) - update_last_use(); - - // Update status line - scr_UpdateMainStatus(TRUE); -} - -// jb_setprevstatus() -// Set previous status. This wrapper function is used after a disconnection. -inline void jb_setprevstatus(void) -{ - jb_setstatus(mywantedstatus, NULL, mystatusmsg, FALSE); -} - -// new_msgid() -// Generate a new id string. The caller should free it. -// The caller must free the string when no longer needed. -static char *new_msgid(void) -{ - static guint msg_idn; - time_t now; - time(&now); -#if HAVE_ARC4RANDOM - msg_idn += 1U + (unsigned int) (9.0 * (arc4random() / 4294967296.0)); -#else - if (!msg_idn) - srand(now); - msg_idn += 1U + (unsigned int) (9.0 * (rand() / (RAND_MAX + 1.0))); -#endif - return g_strdup_printf("%u%d", msg_idn, (int)(now%10L)); -} - -// jb_send_msg(jid, text, type, subject, msgid, *encrypted, type_overwrite) -// When encrypted is not NULL, the function set *encrypted to 1 if the -// message has been PGP-encrypted. If encryption enforcement is set and -// encryption fails, *encrypted is set to -1. -void jb_send_msg(const char *fjid, const char *text, int type, - const char *subject, const char *msgid, gint *encrypted, - const char *type_overwrite) -{ - xmlnode x; - const gchar *strtype; -#ifdef HAVE_LIBOTR - int otr_msg = 0; -#endif -#if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 - char *rname, *barejid; - GSList *sl_buddy; -#endif -#if defined JEP0022 || defined JEP0085 - xmlnode event; - guint use_jep85 = 0; - struct jep0085 *jep85 = NULL; -#endif -#if defined JEP0022 - gchar *nmsgid = NULL; -#endif - gchar *enc = NULL; - - if (encrypted) - *encrypted = 0; - - if (!online) - return; - - if (!text && type == ROSTER_TYPE_USER) - return; - - if (type_overwrite) - strtype = type_overwrite; - else { - if (type == ROSTER_TYPE_ROOM) - strtype = TMSG_GROUPCHAT; - else - strtype = TMSG_CHAT; - } - -#if defined HAVE_GPGME || defined HAVE_LIBOTR || defined JEP0022 || defined JEP0085 - rname = strchr(fjid, JID_RESOURCE_SEPARATOR); - barejid = jidtodisp(fjid); - sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); - - // If we can get a resource name, we use it. Else we use NULL, - // which hopefully will give us the most likely resource. - if (rname) - rname++; - -#ifdef HAVE_LIBOTR - if (otr_enabled()) { - if (msgid && strcmp(msgid, "otrinject") == 0) - msgid = NULL; - else if (type == ROSTER_TYPE_USER) { - otr_msg = otr_send((char **)&text, barejid); - if (!text) { - g_free(barejid); - if (encrypted) - *encrypted = -1; - return; - } - } - if (otr_msg && encrypted) - *encrypted = ENCRYPTED_OTR; - } -#endif - -#ifdef HAVE_GPGME - if (type == ROSTER_TYPE_USER && sl_buddy && gpg_enabled()) { - if (!settings_pgp_getdisabled(barejid)) { // not disabled for this contact? - guint force; - struct pgp_data *res_pgpdata; - force = settings_pgp_getforce(barejid); - res_pgpdata = buddy_resource_pgp(sl_buddy->data, rname); - if (force || (res_pgpdata && res_pgpdata->sign_keyid)) { - /* Remote client has PGP support (we have a signature) - * OR encryption is enforced (force = TRUE). - * If the contact has a specific KeyId, we'll use it; - * if not, we'll use the key used for the signature. - * Both keys should match, in theory (cf. XEP-0027). */ - const char *key; - key = settings_pgp_getkeyid(barejid); - if (!key && res_pgpdata) - key = res_pgpdata->sign_keyid; - if (key) - enc = gpg_encrypt(text, key); - if (!enc && force) { - if (encrypted) - *encrypted = -1; - g_free(barejid); - return; - } - } - } - } -#endif // HAVE_GPGME - - g_free(barejid); -#endif // HAVE_GPGME || defined JEP0022 || defined JEP0085 - - x = jutil_msgnew((char*)strtype, (char*)fjid, NULL, - (enc ? "This message is PGP-encrypted." : (char*)text)); - if (subject) { - xmlnode y; - y = xmlnode_insert_tag(x, "subject"); - xmlnode_insert_cdata(y, subject, (unsigned) -1); - } - if (enc) { - xmlnode y; - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", NS_ENCRYPTED); - xmlnode_insert_cdata(y, enc, (unsigned) -1); - if (encrypted) - *encrypted = ENCRYPTED_PGP; - g_free(enc); - } - -#if defined JEP0022 || defined JEP0085 - // If typing notifications are disabled, we can skip all this stuff... - if (chatstates_disabled || type == ROSTER_TYPE_ROOM) - goto jb_send_msg_no_chatstates; - - if (sl_buddy) - jep85 = buddy_resource_jep85(sl_buddy->data, rname); -#endif - -#ifdef JEP0085 - /* JEP-0085 5.1 - * "Until receiving a reply to the initial content message (or a standalone - * notification) from the Contact, the User MUST NOT send subsequent chat - * state notifications to the Contact." - * In our implementation support is initially "unknown", then it's "probed" - * and can become "ok". - */ - if (jep85 && (jep85->support == CHATSTATES_SUPPORT_OK || - jep85->support == CHATSTATES_SUPPORT_UNKNOWN)) { - event = xmlnode_insert_tag(x, "active"); - xmlnode_put_attrib(event, "xmlns", NS_CHATSTATES); - if (jep85->support == CHATSTATES_SUPPORT_UNKNOWN) - jep85->support = CHATSTATES_SUPPORT_PROBED; - else - use_jep85 = 1; - jep85->last_state_sent = ROSTER_EVENT_ACTIVE; - } -#endif -#ifdef JEP0022 - /* JEP-22 - * If the Contact supports JEP-0085, we do not use JEP-0022. - * If not, we try to fall back to JEP-0022. - */ - if (!use_jep85) { - struct jep0022 *jep22 = NULL; - event = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(event, "xmlns", NS_EVENT); - xmlnode_insert_tag(event, "composing"); - - if (sl_buddy) - jep22 = buddy_resource_jep22(sl_buddy->data, rname); - if (jep22) - jep22->last_state_sent = ROSTER_EVENT_ACTIVE; - - // An id is mandatory when using JEP-0022. - if (!msgid && (text || subject)) { - msgid = nmsgid = new_msgid(); - // Let's update last_msgid_sent - // (We do not update it when the msgid is provided by the caller, - // because this is probably a special message...) - if (jep22) { - g_free(jep22->last_msgid_sent); - jep22->last_msgid_sent = g_strdup(msgid); - } - } - } -#endif - -jb_send_msg_no_chatstates: - xmlnode_put_attrib(x, "id", msgid); - - if (mystatus != invisible) - update_last_use(); - jab_send(jc, x); - xmlnode_free(x); -#if defined JEP0022 - g_free(nmsgid); -#endif - - jb_reset_keepalive(); -} - - -#ifdef JEP0085 -// jb_send_jep85_chatstate() -// Send a JEP-85 chatstate. -static void jb_send_jep85_chatstate(const char *bjid, const char *resname, - guint state) -{ - xmlnode x; - xmlnode event; - GSList *sl_buddy; - const char *chattag; - char *rjid, *fjid = NULL; - struct jep0085 *jep85 = NULL; - - if (!online) return; - - sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); - - // If we have a resource name, we use it. Else we use NULL, - // which hopefully will give us the most likely resource. - if (sl_buddy) - jep85 = buddy_resource_jep85(sl_buddy->data, resname); - - if (!jep85 || (jep85->support != CHATSTATES_SUPPORT_OK)) - return; - - if (state == jep85->last_state_sent) - return; - - if (state == ROSTER_EVENT_ACTIVE) - chattag = "active"; - else if (state == ROSTER_EVENT_COMPOSING) - chattag = "composing"; - else if (state == ROSTER_EVENT_PAUSED) - chattag = "paused"; - else { - scr_LogPrint(LPRINT_LOGNORM, "Error: unsupported JEP-85 state (%d)", state); - return; - } - - jep85->last_state_sent = state; - - if (resname) - fjid = g_strdup_printf("%s/%s", bjid, resname); - - rjid = resname ? fjid : (char*)bjid; - x = jutil_msgnew(TMSG_CHAT, rjid, NULL, NULL); - - event = xmlnode_insert_tag(x, chattag); - xmlnode_put_attrib(event, "xmlns", NS_CHATSTATES); - - jab_send(jc, x); - xmlnode_free(x); - - g_free(fjid); - jb_reset_keepalive(); -} -#endif - -#ifdef JEP0022 -// jb_send_jep22_event() -// Send a JEP-22 message event (delivered, composing...). -static void jb_send_jep22_event(const char *fjid, guint type) -{ - xmlnode x; - xmlnode event; - const char *msgid; - char *rname, *barejid; - GSList *sl_buddy; - struct jep0022 *jep22 = NULL; - guint jep22_state; - - if (!online) return; - - rname = strchr(fjid, JID_RESOURCE_SEPARATOR); - barejid = jidtodisp(fjid); - sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); - g_free(barejid); - - // If we can get a resource name, we use it. Else we use NULL, - // which hopefully will give us the most likely resource. - if (rname) - rname++; - if (sl_buddy) - jep22 = buddy_resource_jep22(sl_buddy->data, rname); - - if (!jep22) - return; // XXX Maybe we could try harder (other resources?) - - msgid = jep22->last_msgid_rcvd; - - // For composing events (composing, active, inactive, paused...), - // JEP22 only has 2 states; we'll use composing and active. - if (type == ROSTER_EVENT_COMPOSING) - jep22_state = ROSTER_EVENT_COMPOSING; - else if (type == ROSTER_EVENT_ACTIVE || - type == ROSTER_EVENT_PAUSED) - jep22_state = ROSTER_EVENT_ACTIVE; - else - jep22_state = 0; // ROSTER_EVENT_NONE - - if (jep22_state) { - // Do not re-send a same event - if (jep22_state == jep22->last_state_sent) - return; - jep22->last_state_sent = jep22_state; - } - - x = jutil_msgnew(TMSG_CHAT, (char*)fjid, NULL, NULL); - - event = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(event, "xmlns", NS_EVENT); - if (type == ROSTER_EVENT_DELIVERED) - xmlnode_insert_tag(event, "delivered"); - else if (type == ROSTER_EVENT_COMPOSING) - xmlnode_insert_tag(event, "composing"); - xmlnode_put_attrib(event, "id", msgid); - - jab_send(jc, x); - xmlnode_free(x); - - jb_reset_keepalive(); -} -#endif - -// jb_send_chatstate(buddy, state) -// Send a chatstate or event (JEP-22/85) according to the buddy's capabilities. -// The message is sent to one of the resources with the highest priority. -#if defined JEP0022 || defined JEP0085 -void jb_send_chatstate(gpointer buddy, guint chatstate) -{ - const char *bjid; -#ifdef JEP0085 - GSList *resources, *p_res, *p_next; - struct jep0085 *jep85 = NULL; -#endif -#ifdef JEP0022 - struct jep0022 *jep22; -#endif - - bjid = buddy_getjid(buddy); - if (!bjid) return; - -#ifdef JEP0085 - /* Send the chatstate to the last resource (which should have the highest - priority). - If chatstate is "active", send an "active" state to all resources - which do not curently have this state. - */ - resources = buddy_getresources(buddy); - for (p_res = resources ; p_res ; p_res = p_next) { - p_next = g_slist_next(p_res); - jep85 = buddy_resource_jep85(buddy, p_res->data); - if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) { - // If p_next is NULL, this is the highest (prio) resource, i.e. - // the one we are probably writing to. - if (!p_next || (jep85->last_state_sent != ROSTER_EVENT_ACTIVE && - chatstate == ROSTER_EVENT_ACTIVE)) - jb_send_jep85_chatstate(bjid, p_res->data, chatstate); - } - g_free(p_res->data); - } - g_slist_free(resources); - // If the last resource had chatstates support when can return now, - // we don't want to send a JEP22 event. - if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) - return; -#endif -#ifdef JEP0022 - jep22 = buddy_resource_jep22(buddy, NULL); - if (jep22 && jep22->support == CHATSTATES_SUPPORT_OK) { - jb_send_jep22_event(bjid, chatstate); - } -#endif -} -#endif - -// chatstates_reset_probed(fulljid) -// If the JEP has been probed for this contact, set it back to unknown so -// that we probe it again. The parameter must be a full jid (w/ resource). -#if defined JEP0022 || defined JEP0085 -static void chatstates_reset_probed(const char *fulljid) -{ - char *rname, *barejid; - GSList *sl_buddy; - struct jep0085 *jep85; - struct jep0022 *jep22; - - rname = strchr(fulljid, JID_RESOURCE_SEPARATOR); - if (!rname++) - return; - - barejid = jidtodisp(fulljid); - sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); - g_free(barejid); - - if (!sl_buddy) - return; - - jep85 = buddy_resource_jep85(sl_buddy->data, rname); - jep22 = buddy_resource_jep22(sl_buddy->data, rname); - - if (jep85 && jep85->support == CHATSTATES_SUPPORT_PROBED) - jep85->support = CHATSTATES_SUPPORT_UNKNOWN; - if (jep22 && jep22->support == CHATSTATES_SUPPORT_PROBED) - jep22->support = CHATSTATES_SUPPORT_UNKNOWN; -} -#endif - -// jb_subscr_send_auth(jid) -// Allow jid to receive our presence updates -void jb_subscr_send_auth(const char *bjid) -{ - xmlnode x; - - x = jutil_presnew(JPACKET__SUBSCRIBED, (char *)bjid, NULL); - jab_send(jc, x); - xmlnode_free(x); -} - -// jb_subscr_cancel_auth(jid) -// Cancel jid's subscription to our presence updates -void jb_subscr_cancel_auth(const char *bjid) -{ - xmlnode x; - - x = jutil_presnew(JPACKET__UNSUBSCRIBED, (char *)bjid, NULL); - jab_send(jc, x); - xmlnode_free(x); -} - -// jb_subscr_request_auth(jid) -// Request a subscription to jid's presence updates -void jb_subscr_request_auth(const char *bjid) -{ - xmlnode x; - - x = jutil_presnew(JPACKET__SUBSCRIBE, (char *)bjid, NULL); - jab_send(jc, x); - xmlnode_free(x); -} - -// jb_subscr_request_cancel(jid) -// Request to cancel jour subscription to jid's presence updates -void jb_subscr_request_cancel(const char *bjid) -{ - xmlnode x; - - x = jutil_presnew(JPACKET__UNSUBSCRIBE, (char *)bjid, NULL); - jab_send(jc, x); - xmlnode_free(x); -} - -// Note: the caller should check the jid is correct -void jb_addbuddy(const char *bjid, const char *name, const char *group) -{ - xmlnode y, z; - eviqs *iqn; - char *cleanjid; - - if (!online) return; - - cleanjid = jidtodisp(bjid); // Stripping resource, just in case... - - // We don't check if the jabber user already exists in the roster, - // because it allows to re-ask for notification. - - iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); - y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); - - xmlnode_put_attrib(y, "jid", cleanjid); - - if (name) - xmlnode_put_attrib(y, "name", name); - - if (group) { - z = xmlnode_insert_tag(y, "group"); - xmlnode_insert_cdata(z, group, (unsigned) -1); - } - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - - jb_subscr_request_auth(cleanjid); - - roster_add_user(cleanjid, name, group, ROSTER_TYPE_USER, sub_pending, -1); - g_free(cleanjid); - buddylist_build(); - - update_roster = TRUE; -} - -void jb_delbuddy(const char *bjid) -{ - xmlnode y, z; - eviqs *iqn; - char *cleanjid; - - if (!online) return; - - cleanjid = jidtodisp(bjid); // Stripping resource, just in case... - - // If the current buddy is an agent, unsubscribe from it - if (roster_gettype(cleanjid) == ROSTER_TYPE_AGENT) { - scr_LogPrint(LPRINT_LOGNORM, "Unregistering from the %s agent", cleanjid); - - iqn = iqs_new(JPACKET__SET, NS_REGISTER, NULL, IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", cleanjid); - y = xmlnode_get_tag(iqn->xmldata, "query"); - xmlnode_insert_tag(y, "remove"); - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - } - - // Cancel the subscriptions - jb_subscr_cancel_auth(cleanjid); // Cancel "from" - jb_subscr_request_cancel(cleanjid); // Cancel "to" - - // Ask for removal from roster - iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); - y = xmlnode_get_tag(iqn->xmldata, "query"); - z = xmlnode_insert_tag(y, "item"); - xmlnode_put_attrib(z, "jid", cleanjid); - xmlnode_put_attrib(z, "subscription", "remove"); - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - - roster_del_user(cleanjid); - g_free(cleanjid); - buddylist_build(); - - update_roster = TRUE; -} - -void jb_updatebuddy(const char *bjid, const char *name, const char *group) -{ - xmlnode y; - eviqs *iqn; - char *cleanjid; - - if (!online) return; - - // XXX We should check name's and group's correctness - - cleanjid = jidtodisp(bjid); // Stripping resource, just in case... - - iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); - y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); - xmlnode_put_attrib(y, "jid", cleanjid); - xmlnode_put_attrib(y, "name", name); - - if (group) { - y = xmlnode_insert_tag(y, "group"); - xmlnode_insert_cdata(y, group, (unsigned) -1); - } - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - g_free(cleanjid); -} - -void jb_request(const char *fjid, enum iqreq_type reqtype) -{ - GSList *resources, *p_res; - GSList *roster_elt; - void (*request_fn)(const char *); - const char *strreqtype; - - if (!online) return; - - if (reqtype == iqreq_version) { - request_fn = &request_version; - strreqtype = "version"; - } else if (reqtype == iqreq_time) { - request_fn = &request_time; - strreqtype = "time"; - } else if (reqtype == iqreq_last) { - request_fn = &request_last; - strreqtype = "last"; - } else if (reqtype == iqreq_vcard) { - // Special case - } else - return; - - // vCard request - if (reqtype == iqreq_vcard) { - request_vcard(fjid); - scr_LogPrint(LPRINT_NORMAL, "Sent vCard request to <%s>", fjid); - return; - } - - if (strchr(fjid, JID_RESOURCE_SEPARATOR)) { - // This is a full JID - (*request_fn)(fjid); - scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); - return; - } - - // The resource has not been specified - roster_elt = roster_find(fjid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); - if (!roster_elt) { - scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); - (*request_fn)(fjid); // Let's send a request anyway... - scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); - return; - } - - // Send a request to each resource - resources = buddy_getresources(roster_elt->data); - if (!resources) { - scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); - (*request_fn)(fjid); // Let's send a request anyway... - scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); - } - for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) { - gchar *fulljid; - fulljid = g_strdup_printf("%s/%s", fjid, (char*)p_res->data); - (*request_fn)(fulljid); - scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fulljid); - g_free(fulljid); - g_free(p_res->data); - } - g_slist_free(resources); -} - -// Join a MUC room -void jb_room_join(const char *room, const char *nickname, const char *passwd) -{ - xmlnode x, y; - gchar *roomid; - GSList *room_elt; - - if (!online || !room) return; - if (!nickname) return; - - roomid = g_strdup_printf("%s/%s", room, nickname); - if (check_jid_syntax(roomid)) { - scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room, - nickname); - g_free(roomid); - return; - } - - room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); - // Add room if it doesn't already exist - if (!room_elt) { - room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM, - sub_none, -1); - } else { - // Make sure this is a room (it can be a conversion user->room) - buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); - } - // If insideroom is TRUE, this is a nickname change and we don't care here - if (!buddy_getinsideroom(room_elt->data)) { - // We're trying to enter a room - buddy_setnickname(room_elt->data, nickname); - } - - // Send the XML request - x = presnew(mystatus, roomid, mystatusmsg); - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc"); - if (passwd) { - xmlnode_insert_cdata(xmlnode_insert_tag(y, "password"), passwd, - (unsigned) -1); - } - - jab_send(jc, x); - xmlnode_free(x); - jb_reset_keepalive(); - g_free(roomid); -} - -// Unlock a MUC room -// room syntax: "room@server" -void jb_room_unlock(const char *room) -{ - xmlnode y, z; - eviqs *iqn; - - if (!online || !room) return; - - iqn = iqs_new(JPACKET__SET, "http://jabber.org/protocol/muc#owner", - "unlock", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", room); - y = xmlnode_get_tag(iqn->xmldata, "query"); - z = xmlnode_insert_tag(y, "x"); - xmlnode_put_attrib(z, "xmlns", "jabber:x:data"); - xmlnode_put_attrib(z, "type", "submit"); - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - jb_reset_keepalive(); -} - -// Destroy a MUC room -// room syntax: "room@server" -void jb_room_destroy(const char *room, const char *venue, const char *reason) -{ - xmlnode y, z; - eviqs *iqn; - - if (!online || !room) return; - - iqn = iqs_new(JPACKET__SET, "http://jabber.org/protocol/muc#owner", - "destroy", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", room); - y = xmlnode_get_tag(iqn->xmldata, "query"); - z = xmlnode_insert_tag(y, "destroy"); - - if (venue && *venue) - xmlnode_put_attrib(z, "jid", venue); - - if (reason) { - y = xmlnode_insert_tag(z, "reason"); - xmlnode_insert_cdata(y, reason, (unsigned) -1); - } - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - jb_reset_keepalive(); -} - -// Change role or affiliation of a MUC user -// room syntax: "room@server" -// Either the jid or the nickname must be set (when banning, only the jid is -// allowed) -// ra: new role or affiliation -// (ex. role none for kick, affil outcast for ban...) -// The reason can be null -// Return 0 if everything is ok -int jb_room_setattrib(const char *roomid, const char *fjid, const char *nick, - struct role_affil ra, const char *reason) -{ - xmlnode y, z; - eviqs *iqn; - - if (!online || !roomid) return 1; - if (!fjid && !nick) return 1; - - if (check_jid_syntax((char*)roomid)) { - scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid); - return 1; - } - if (fjid && check_jid_syntax((char*)fjid)) { - scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid); - return 1; - } - - if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid) - return 1; // Shouldn't happen (jid mandatory when banning) - - iqn = iqs_new(JPACKET__SET, "http://jabber.org/protocol/muc#admin", - "roleaffil", IQS_DEFAULT_TIMEOUT); - xmlnode_put_attrib(iqn->xmldata, "to", roomid); - xmlnode_put_attrib(iqn->xmldata, "type", "set"); - y = xmlnode_get_tag(iqn->xmldata, "query"); - z = xmlnode_insert_tag(y, "item"); - - if (fjid) { - xmlnode_put_attrib(z, "jid", fjid); - } else { // nickname - xmlnode_put_attrib(z, "nick", nick); - } - - if (ra.type == type_affil) - xmlnode_put_attrib(z, "affiliation", straffil[ra.val.affil]); - else if (ra.type == type_role) - xmlnode_put_attrib(z, "role", strrole[ra.val.role]); - - if (reason) { - y = xmlnode_insert_tag(z, "reason"); - xmlnode_insert_cdata(y, reason, (unsigned) -1); - } - - jab_send(jc, iqn->xmldata); - iqs_del(iqn->id); // XXX - jb_reset_keepalive(); - - return 0; -} - -// Invite a user to a MUC room -// room syntax: "room@server" -// reason can be null. -void jb_room_invite(const char *room, const char *fjid, const char *reason) -{ - xmlnode x, y, z; - - if (!online || !room || !fjid) return; - - x = jutil_msgnew(NULL, (char*)room, NULL, NULL); - - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); - - z = xmlnode_insert_tag(y, "invite"); - xmlnode_put_attrib(z, "to", fjid); - - if (reason) { - y = xmlnode_insert_tag(z, "reason"); - xmlnode_insert_cdata(y, reason, (unsigned) -1); - } - - jab_send(jc, x); - xmlnode_free(x); - jb_reset_keepalive(); -} - -// jb_is_bookmarked(roomjid) -// Return TRUE if there's a bookmark for the given jid. -guint jb_is_bookmarked(const char *bjid) -{ - xmlnode x; - - if (!bookmarks) - return FALSE; - - // Walk through the storage bookmark tags - x = xmlnode_get_firstchild(bookmarks); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p = xmlnode_get_name(x); - // If the node is a conference item, check the jid. - if (p && !strcmp(p, "conference")) { - const char *fjid = xmlnode_get_attrib(x, "jid"); - if (fjid && !strcasecmp(bjid, fjid)) - return TRUE; - } - } - return FALSE; -} - -// jb_get_bookmark_nick(roomjid) -// Return the room nickname if it is present in a bookmark. -const char *jb_get_bookmark_nick(const char *bjid) -{ - xmlnode x; - - if (!bookmarks || !bjid) - return NULL; - - // Walk through the storage bookmark tags - x = xmlnode_get_firstchild(bookmarks); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p = xmlnode_get_name(x); - // If the node is a conference item, check the jid. - if (p && !strcmp(p, "conference")) { - const char *fjid = xmlnode_get_attrib(x, "jid"); - if (fjid && !strcasecmp(bjid, fjid)) - return xmlnode_get_tag_data(x, "nick"); - } - } - return NULL; -} - - -// jb_get_all_storage_bookmarks() -// Return a GSList with all storage bookmarks. -// The caller should g_free the list and its contents. -GSList *jb_get_all_storage_bookmarks(void) -{ - xmlnode x; - GSList *sl_bookmarks = NULL; - - // If we have no bookmarks, probably the server doesn't support them. - if (!bookmarks) - return NULL; - - // Walk through the storage bookmark tags - x = xmlnode_get_firstchild(bookmarks); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p = xmlnode_get_name(x); - // If the node is a conference item, let's add the note to our list. - if (p && !strcmp(p, "conference")) { - struct bookmark *bm_elt; - const char *autojoin, *name, *nick; - const char *fjid = xmlnode_get_attrib(x, "jid"); - if (!fjid) - continue; - bm_elt = g_new0(struct bookmark, 1); - bm_elt->roomjid = g_strdup(fjid); - autojoin = xmlnode_get_attrib(x, "autojoin"); - nick = xmlnode_get_attrib(x, "nick"); - name = xmlnode_get_attrib(x, "name"); - if (autojoin && !strcmp(autojoin, "1")) - bm_elt->autojoin = 1; - if (nick) - bm_elt->nick = g_strdup(nick); - if (name) - bm_elt->name = g_strdup(name); - sl_bookmarks = g_slist_append(sl_bookmarks, bm_elt); - } - } - return sl_bookmarks; -} - -// jb_set_storage_bookmark(roomid, name, nick, passwd, autojoin, -// printstatus, autowhois) -// Update the private storage bookmarks: add a conference room. -// If name is nil, we remove the bookmark. -void jb_set_storage_bookmark(const char *roomid, const char *name, - const char *nick, const char *passwd, - int autojoin, enum room_printstatus pstatus, - enum room_autowhois awhois) -{ - xmlnode x; - bool changed = FALSE; - - if (!roomid) - return; - - // If we have no bookmarks, probably the server doesn't support them. - if (!bookmarks) { - scr_LogPrint(LPRINT_NORMAL, - "Sorry, your server doesn't seem to support private storage."); - return; - } - - // Walk through the storage tags - x = xmlnode_get_firstchild(bookmarks); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p = xmlnode_get_name(x); - // If the current node is a conference item, see if we have to replace it. - if (p && !strcmp(p, "conference")) { - const char *fjid = xmlnode_get_attrib(x, "jid"); - if (!fjid) - continue; - if (!strcmp(fjid, roomid)) { - // We've found a bookmark for this room. Let's hide it and we'll - // create a new one. - xmlnode_hide(x); - changed = TRUE; - if (!name) - scr_LogPrint(LPRINT_LOGNORM, "Deleting bookmark..."); - } - } - } - - // Let's create a node/bookmark for this roomid, if the name is not NULL. - if (name) { - x = xmlnode_insert_tag(bookmarks, "conference"); - xmlnode_put_attrib(x, "jid", roomid); - xmlnode_put_attrib(x, "name", name); - xmlnode_put_attrib(x, "autojoin", autojoin ? "1" : "0"); - if (nick) - xmlnode_insert_cdata(xmlnode_insert_tag(x, "nick"), nick, -1); - if (passwd) - xmlnode_insert_cdata(xmlnode_insert_tag(x, "password"), passwd, -1); - if (pstatus) - xmlnode_insert_cdata(xmlnode_insert_tag(x, "print_status"), - strprintstatus[pstatus], -1); - if (awhois) - xmlnode_put_attrib(x, "autowhois", (awhois == autowhois_on ? "1" : "0")); - changed = TRUE; - scr_LogPrint(LPRINT_LOGNORM, "Updating bookmarks..."); - } - - if (!changed) - return; - - if (online) - send_storage_bookmarks(); - else - scr_LogPrint(LPRINT_LOGNORM, - "Warning: you're not connected to the server."); -} - -static struct annotation *parse_storage_rosternote(xmlnode notenode) -{ - const char *p; - struct annotation *note = g_new0(struct annotation, 1); - p = xmlnode_get_attrib(notenode, "cdate"); - if (p) - note->cdate = from_iso8601(p, 1); - p = xmlnode_get_attrib(notenode, "mdate"); - if (p) - note->mdate = from_iso8601(p, 1); - note->text = g_strdup(xmlnode_get_data(notenode)); - note->jid = g_strdup(xmlnode_get_attrib(notenode, "jid")); - return note; -} - -// jb_get_all_storage_rosternotes() -// Return a GSList with all storage annotations. -// The caller should g_free the list and its contents. -GSList *jb_get_all_storage_rosternotes(void) -{ - xmlnode x; - GSList *sl_notes = NULL; - - // If we have no rosternotes, probably the server doesn't support them. - if (!rosternotes) - return NULL; - - // Walk through the storage rosternotes tags - x = xmlnode_get_firstchild(rosternotes); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p; - struct annotation *note; - p = xmlnode_get_name(x); - - // We want a note item - if (!p || strcmp(p, "note")) - continue; - // Just in case, check the jid... - if (!xmlnode_get_attrib(x, "jid")) - continue; - // Ok, let's add the note to our list - note = parse_storage_rosternote(x); - sl_notes = g_slist_append(sl_notes, note); - } - return sl_notes; -} - -// jb_get_storage_rosternotes(barejid, silent) -// Return the annotation associated with this jid. -// If silent is TRUE, no warning is displayed when rosternotes is disabled -// The caller should g_free the string and structure after use. -struct annotation *jb_get_storage_rosternotes(const char *barejid, int silent) -{ - xmlnode x; - - if (!barejid) - return NULL; - - // If we have no rosternotes, probably the server doesn't support them. - if (!rosternotes) { - if (!silent) - scr_LogPrint(LPRINT_NORMAL, "Sorry, " - "your server doesn't seem to support private storage."); - return NULL; - } - - // Walk through the storage rosternotes tags - x = xmlnode_get_firstchild(rosternotes); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *fjid; - const char *p; - p = xmlnode_get_name(x); - // We want a note item - if (!p || strcmp(p, "note")) - continue; - // Just in case, check the jid... - fjid = xmlnode_get_attrib(x, "jid"); - if (fjid && !strcmp(fjid, barejid)) // We've found a note for this contact. - return parse_storage_rosternote(x); - } - return NULL; // No note found -} - -// jb_set_storage_rosternotes(barejid, note) -// Update the private storage rosternotes: add/delete a note. -// If note is nil, we remove the existing note. -void jb_set_storage_rosternotes(const char *barejid, const char *note) -{ - xmlnode x; - bool changed = FALSE; - const char *cdate = NULL; - - if (!barejid) - return; - - // If we have no rosternotes, probably the server doesn't support them. - if (!rosternotes) { - scr_LogPrint(LPRINT_NORMAL, - "Sorry, your server doesn't seem to support private storage."); - return; - } - - // Walk through the storage tags - x = xmlnode_get_firstchild(rosternotes); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - const char *p = xmlnode_get_name(x); - // If the current node is a conference item, see if we have to replace it. - if (p && !strcmp(p, "note")) { - const char *fjid = xmlnode_get_attrib(x, "jid"); - if (!fjid) - continue; - if (!strcmp(fjid, barejid)) { - // We've found a note for this jid. Let's hide it and we'll - // create a new one. - cdate = xmlnode_get_attrib(x, "cdate"); - xmlnode_hide(x); - changed = TRUE; - break; - } - } - } - - // Let's create a node for this jid, if the note is not NULL. - if (note) { - char mdate[20]; - time_t now; - time(&now); - to_iso8601(mdate, now); - if (!cdate) - cdate = mdate; - x = xmlnode_insert_tag(rosternotes, "note"); - xmlnode_put_attrib(x, "jid", barejid); - xmlnode_put_attrib(x, "cdate", cdate); - xmlnode_put_attrib(x, "mdate", mdate); - xmlnode_insert_cdata(x, note, -1); - changed = TRUE; - } - - if (!changed) - return; - - if (online) - send_storage_rosternotes(); - else - scr_LogPrint(LPRINT_LOGNORM, - "Warning: you're not connected to the server."); -} - -#ifdef HAVE_GPGME -// keys_mismatch(key, expectedkey) -// Return TRUE if both keys are non-null and "expectedkey" doesn't match -// the end of "key". -// If one of the keys is null, return FALSE. -// If expectedkey is less than 8 bytes long, return TRUE. -// -// Example: keys_mismatch("C9940A9BB0B92210", "B0B92210") will return FALSE. -static bool keys_mismatch(const char *key, const char *expectedkey) -{ - int lk, lek; - - if (!expectedkey || !key) - return FALSE; - - lk = strlen(key); - lek = strlen(expectedkey); - - // If the expectedkey is less than 8 bytes long, this is probably a - // user mistake so we consider it's a mismatch. - if (lek < 8) - return TRUE; - - if (lek < lk) - key += lk - lek; - - return strcasecmp(key, expectedkey); -} -#endif - -// check_signature(barejid, resourcename, xmldata, text) -// Verify the signature (in xmldata) of "text" for the contact -// barejid/resourcename. -// xmldata is the 'jabber:x:signed' stanza. -// If the key id is found, the contact's PGP data are updated. -static void check_signature(const char *barejid, const char *rname, - xmlnode xmldata, const char *text) -{ -#ifdef HAVE_GPGME - char *p, *key; - GSList *sl_buddy; - struct pgp_data *res_pgpdata; - gpgme_sigsum_t sigsum; - - // All parameters must be valid - if (!(xmldata && barejid && rname && text)) - return; - - if (!gpg_enabled()) - return; - - // Get the resource PGP data structure - sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); - if (!sl_buddy) - return; - res_pgpdata = buddy_resource_pgp(sl_buddy->data, rname); - if (!res_pgpdata) - return; - - p = xmlnode_get_name(xmldata); - if (!p || strcmp(p, "x")) - return; // We expect "" - - // Get signature - p = xmlnode_get_data(xmldata); - if (!p) - return; - - key = gpg_verify(p, text, &sigsum); - if (key) { - const char *expectedkey; - char *buf; - g_free(res_pgpdata->sign_keyid); - res_pgpdata->sign_keyid = key; - res_pgpdata->last_sigsum = sigsum; - if (sigsum & GPGME_SIGSUM_RED) { - buf = g_strdup_printf("Bad signature from <%s/%s>", barejid, rname); - scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } - // Verify that the key id is the one we expect. - expectedkey = settings_pgp_getkeyid(barejid); - if (keys_mismatch(key, expectedkey)) { - buf = g_strdup_printf("Warning: The KeyId from <%s/%s> doesn't match " - "the key you set up", barejid, rname); - scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } - } -#endif -} - -static void gotmessage(char *type, const char *from, const char *body, - const char *enc, const char *subject, time_t timestamp, - xmlnode xmldata_signed) -{ - char *bjid; - const char *rname, *s; - char *decrypted_pgp = NULL; - char *decrypted_otr = NULL; - int otr_msg = 0, free_msg = 0; - - bjid = jidtodisp(from); - - rname = strchr(from, JID_RESOURCE_SEPARATOR); - if (rname) rname++; - -#ifdef HAVE_GPGME - if (enc && gpg_enabled()) { - decrypted_pgp = gpg_decrypt(enc); - if (decrypted_pgp) { - body = decrypted_pgp; - } - } - // Check signature of an unencrypted message - if (xmldata_signed && gpg_enabled()) - check_signature(bjid, rname, xmldata_signed, decrypted_pgp); -#endif - -#ifdef HAVE_LIBOTR - if (otr_enabled()) { - decrypted_otr = (char*)body; - otr_msg = otr_receive(&decrypted_otr, bjid, &free_msg); - if (!decrypted_otr) { - goto gotmessage_return; - } - body = decrypted_otr; - } -#endif - - // Check for unexpected groupchat messages - // If we receive a groupchat message from a room we're not a member of, - // this is probably a server issue and the best we can do is to send - // a type unavailable. - if (type && !strcmp(type, "groupchat") && !roster_getnickname(bjid)) { - // It shouldn't happen, probably a server issue - GSList *room_elt; - char *mbuf; - - mbuf = g_strdup_printf("Unexpected groupchat packet!"); - scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); - scr_WriteIncomingMessage(bjid, mbuf, 0, HBB_PREFIX_INFO, 0); - g_free(mbuf); - - // Send back an unavailable packet - jb_setstatus(offline, bjid, "", TRUE); - - // MUC - // Make sure this is a room (it can be a conversion user->room) - room_elt = roster_find(bjid, jidsearch, 0); - if (!room_elt) { - room_elt = roster_add_user(bjid, NULL, NULL, ROSTER_TYPE_ROOM, - sub_none, -1); - } else { - buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); - } - - buddylist_build(); - scr_DrawRoster(); - goto gotmessage_return; - } - - // We don't call the message_in hook if 'block_unsubscribed' is true and - // this is a regular message from an unsubscribed user. - // System messages (from our server) are allowed. - if (!settings_opt_get_int("block_unsubscribed") || - (roster_getsubscription(bjid) & sub_from) || - (type && strcmp(type, "chat")) || - ((s = settings_opt_get("server")) != NULL && !strcasecmp(bjid, s))) { - gchar *fullbody = NULL; - guint encrypted; - - if (decrypted_pgp) - encrypted = ENCRYPTED_PGP; - else if (otr_msg) - encrypted = ENCRYPTED_OTR; - else - encrypted = 0; - - if (subject) { - if (body) - fullbody = g_strdup_printf("[%s]\n%s", subject, body); - else - fullbody = g_strdup_printf("[%s]\n", subject); - body = fullbody; - } - hk_message_in(bjid, rname, timestamp, body, type, encrypted); - g_free(fullbody); - } else { - scr_LogPrint(LPRINT_LOGNORM, "Blocked a message from <%s>", bjid); - } - -gotmessage_return: - // Clean up and exit - g_free(bjid); - g_free(decrypted_pgp); - if (free_msg) - g_free(decrypted_otr); -} - -static const char *defaulterrormsg(int code) -{ - const char *desc; - - switch(code) { - case 401: desc = "Unauthorized"; - break; - case 302: desc = "Redirect"; - break; - case 400: desc = "Bad request"; - break; - case 402: desc = "Payment Required"; - break; - case 403: desc = "Forbidden"; - break; - case 404: desc = "Not Found"; - break; - case 405: desc = "Not Allowed"; - break; - case 406: desc = "Not Acceptable"; - break; - case 407: desc = "Registration Required"; - break; - case 408: desc = "Request Timeout"; - break; - case 409: desc = "Conflict"; - break; - case 500: desc = "Internal Server Error"; - break; - case 501: desc = "Not Implemented"; - break; - case 502: desc = "Remote Server Error"; - break; - case 503: desc = "Service Unavailable"; - break; - case 504: desc = "Remote Server Timeout"; - break; - default: - desc = NULL; - } - - return desc; -} - -// display_server_error(x) -// Display the error to the user -// x: error tag xmlnode pointer -void display_server_error(xmlnode x) -{ - const char *desc = NULL; - char *sdesc; - int code = 0; - char *s; - const char *p; - - if (!x) return; - - /* RFC3920: - * The element: - * o MUST contain a child element corresponding to one of the defined - * stanza error conditions specified below; this element MUST be - * qualified by the 'urn:ietf:params:xml:ns:xmpp-stanzas' namespace. - */ - p = xmlnode_get_name(xmlnode_get_firstchild(x)); - if (p) - scr_LogPrint(LPRINT_LOGNORM, "Received error packet [%s]", p); - - // For backward compatibility - if ((s = xmlnode_get_attrib(x, "code")) != NULL) { - code = atoi(s); - // Default message - desc = defaulterrormsg(code); - } - - // Error tag data is better, if available - s = xmlnode_get_data(x); - if (s && *s) desc = s; - - // And sometimes there is a text message - s = xmlnode_get_tag_data(x, "text"); - if (s && *s) desc = s; - - // If we still have no description, let's give up - if (!desc) - return; - - // Strip trailing newlines - sdesc = g_strdup(desc); - for (s = sdesc; *s; s++) ; - if (s > sdesc) - s--; - while (s >= sdesc && (*s == '\n' || *s == '\r')) - *s-- = '\0'; - - scr_LogPrint(LPRINT_LOGNORM, "Error code from server: %d %s", code, sdesc); - g_free(sdesc); -} - -static void statehandler(jconn conn, int state) -{ - static int previous_state = -1; - - scr_LogPrint(LPRINT_DEBUG, "StateHandler called (state=%d).", state); - - switch(state) { - case JCONN_STATE_OFF: - if (previous_state != JCONN_STATE_OFF) - scr_LogPrint(LPRINT_LOGNORM, "[Jabber] Not connected to the server"); - - // Sometimes the state isn't correctly updated - if (jc) - jc->state = JCONN_STATE_OFF; - online = FALSE; - mystatus = offline; - // Free bookmarks - xmlnode_free(bookmarks); - bookmarks = NULL; - // Free roster - roster_free(); - xmlnode_free(rosternotes); - rosternotes = NULL; - // Update display - update_roster = TRUE; - scr_UpdateBuddyWindow(); - break; - - case JCONN_STATE_CONNECTED: - scr_LogPrint(LPRINT_LOGNORM, "[Jabber] Connected to the server"); - break; - - case JCONN_STATE_AUTH: - scr_LogPrint(LPRINT_LOGNORM, "[Jabber] Authenticating to the server"); - break; - - case JCONN_STATE_ON: - scr_LogPrint(LPRINT_LOGNORM, "[Jabber] Communication with the server " - "established"); - online = TRUE; - update_last_use(); - // We set AutoConnection to true after the 1st successful connection - AutoConnection = TRUE; - break; - - case JCONN_STATE_CONNECTING: - if (previous_state != state) - scr_LogPrint(LPRINT_LOGNORM, "[Jabber] Connecting to the server"); - break; - - default: - break; - } - previous_state = state; -} - -inline static xmlnode xml_get_xmlns(xmlnode xmldata, const char *xmlns) -{ - xmlnode x; - char *p; - - x = xmlnode_get_firstchild(xmldata); - for ( ; x; x = xmlnode_get_nextsibling(x)) { - if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) - break; - } - return x; -} - -static time_t xml_get_timestamp(xmlnode xmldata) -{ - xmlnode x; - char *p; - - x = xml_get_xmlns(xmldata, NS_XMPP_DELAY); - if (x && !strcmp(xmlnode_get_name(x), "delay") && - (p = xmlnode_get_attrib(x, "stamp")) != NULL) - return from_iso8601(p, 1); - x = xml_get_xmlns(xmldata, NS_DELAY); - if ((p = xmlnode_get_attrib(x, "stamp")) != NULL) - return from_iso8601(p, 1); - return 0; -} - -// muc_get_item_info(...) -// Get room member's information from xmlndata. -// The variables must be initialized before calling this function, -// because they are not touched if the relevant information is missing. -static void muc_get_item_info(const char *from, xmlnode xmldata, - enum imrole *mbrole, enum imaffiliation *mbaffil, - const char **mbjid, const char **mbnick, - const char **actorjid, const char **reason) -{ - xmlnode y, z; - char *p; - - y = xmlnode_get_tag(xmldata, "item"); - if (!y) - return; - - p = xmlnode_get_attrib(y, "affiliation"); - if (p) { - if (!strcmp(p, "owner")) *mbaffil = affil_owner; - else if (!strcmp(p, "admin")) *mbaffil = affil_admin; - else if (!strcmp(p, "member")) *mbaffil = affil_member; - else if (!strcmp(p, "outcast")) *mbaffil = affil_outcast; - else if (!strcmp(p, "none")) *mbaffil = affil_none; - else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown affiliation \"%s\"", - from, p); - } - p = xmlnode_get_attrib(y, "role"); - if (p) { - if (!strcmp(p, "moderator")) *mbrole = role_moderator; - else if (!strcmp(p, "participant")) *mbrole = role_participant; - else if (!strcmp(p, "visitor")) *mbrole = role_visitor; - else if (!strcmp(p, "none")) *mbrole = role_none; - else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"", - from, p); - } - *mbjid = xmlnode_get_attrib(y, "jid"); - *mbnick = xmlnode_get_attrib(y, "nick"); - // For kick/ban, there can be actor and reason tags - *reason = xmlnode_get_tag_data(y, "reason"); - z = xmlnode_get_tag(y, "actor"); - if (z) - *actorjid = xmlnode_get_attrib(z, "jid"); -} - -// muc_handle_join(...) -// Handle a join event in a MUC room. -// This function will return the new_member value TRUE if somebody else joins -// the room (and FALSE if _we_ are joining the room). -static bool muc_handle_join(const GSList *room_elt, const char *rname, - const char *roomjid, const char *ournick, - enum room_printstatus printstatus, - time_t usttime, int log_muc_conf) -{ - bool new_member = FALSE; // True if somebody else joins the room (not us) - gchar *mbuf; - - if (!buddy_getinsideroom(room_elt->data)) { - // We weren't inside the room yet. Now we are. - // However, this could be a presence packet from another room member - - buddy_setinsideroom(room_elt->data, TRUE); - // Set the message flag unless we're already in the room buffer window - scr_setmsgflag_if_needed(roomjid, FALSE); - // Add a message to the tracelog file - mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick); - scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); - g_free(mbuf); - mbuf = g_strdup_printf("You have joined as \"%s\"", ournick); - - // The 1st presence message could be for another room member - if (strcmp(ournick, rname)) { - // Display current mbuf and create a new message for the member - // Note: the usttime timestamp is related to the other member, - // so we use 0 here. - scr_WriteIncomingMessage(roomjid, mbuf, 0, - HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); - if (log_muc_conf) - hlog_write_message(roomjid, 0, -1, mbuf); - g_free(mbuf); - if (printstatus != status_none) - mbuf = g_strdup_printf("%s has joined", rname); - else - mbuf = NULL; - new_member = TRUE; - } - } else { - mbuf = NULL; - if (strcmp(ournick, rname)) { - if (printstatus != status_none) - mbuf = g_strdup_printf("%s has joined", rname); - new_member = TRUE; - } - } - - if (mbuf) { - guint msgflags = HBB_PREFIX_INFO; - if (!settings_opt_get_int("muc_flag_joins")) - msgflags |= HBB_PREFIX_NOFLAG; - scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0); - if (log_muc_conf) - hlog_write_message(roomjid, 0, -1, mbuf); - g_free(mbuf); - } - - return new_member; -} - -static void handle_presence_muc(const char *from, xmlnode xmldata, - const char *roomjid, const char *rname, - enum imstatus ust, char *ustmsg, - time_t usttime, char bpprio) -{ - xmlnode y; - char *p; - char *mbuf; - const char *ournick; - enum imrole mbrole = role_none; - enum imaffiliation mbaffil = affil_none; - enum room_printstatus printstatus; - enum room_autowhois autowhois; - const char *mbjid = NULL, *mbnick = NULL; - const char *actorjid = NULL, *reason = NULL; - bool new_member = FALSE; // True if somebody else joins the room (not us) - guint statuscode = 0; - guint nickchange = 0; - GSList *room_elt; - int log_muc_conf; - guint msgflags; - - log_muc_conf = settings_opt_get_int("log_muc_conf"); - - room_elt = roster_find(roomjid, jidsearch, 0); - if (!room_elt) { - // Add room if it doesn't already exist - // It shouldn't happen, there is probably something wrong (server or - // network issue?) - room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM, - sub_none, -1); - scr_LogPrint(LPRINT_LOGNORM, "Strange MUC presence message"); - } else { - // Make sure this is a room (it can be a conversion user->room) - buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); - } - - // Get room member's information - muc_get_item_info(from, xmldata, &mbrole, &mbaffil, &mbjid, &mbnick, - &actorjid, &reason); - - // Get our room nickname - ournick = buddy_getnickname(room_elt->data); - - if (!ournick) { - // It shouldn't happen, probably a server issue - mbuf = g_strdup_printf("Unexpected groupchat packet!"); - - scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); - scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO, 0); - g_free(mbuf); - // Send back an unavailable packet - jb_setstatus(offline, roomjid, "", TRUE); - scr_DrawRoster(); - return; - } - - // Get the status code - // 201: a room has been created - // 301: the user has been banned from the room - // 303: new room nickname - // 307: the user has been kicked from the room - // 321,322,332: the user has been removed from the room - y = xmlnode_get_tag(xmldata, "status"); - if (y) { - p = xmlnode_get_attrib(y, "code"); - if (p) - statuscode = atoi(p); - } - - // Get the room's "print_status" settings - printstatus = buddy_getprintstatus(room_elt->data); - if (printstatus == status_default) { - printstatus = (guint) settings_opt_get_int("muc_print_status"); - if (printstatus > 3) - printstatus = status_default; - } - - // A new room has been created; accept MUC default config - if (statuscode == 201) - jb_room_unlock(roomjid); - - // Check for nickname change - if (statuscode == 303 && mbnick) { - mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick); - scr_WriteIncomingMessage(roomjid, mbuf, usttime, - HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); - if (log_muc_conf) - hlog_write_message(roomjid, 0, -1, mbuf); - g_free(mbuf); - buddy_resource_setname(room_elt->data, rname, mbnick); - // Maybe it's _our_ nickname... - if (ournick && !strcmp(rname, ournick)) - buddy_setnickname(room_elt->data, mbnick); - nickchange = TRUE; - } - - // Check for departure/arrival - if (!mbnick && ust == offline) { - // Somebody is leaving - enum { leave=0, kick, ban } how = leave; - bool we_left = FALSE; - - if (statuscode == 307) - how = kick; - else if (statuscode == 301) - how = ban; - - // If this is a leave, check if it is ourself - if (ournick && !strcmp(rname, ournick)) { - we_left = TRUE; // _We_ have left! (kicked, banned, etc.) - buddy_setinsideroom(room_elt->data, FALSE); - buddy_setnickname(room_elt->data, NULL); - buddy_del_all_resources(room_elt->data); - buddy_settopic(room_elt->data, NULL); - scr_UpdateChatStatus(FALSE); - update_roster = TRUE; - } - - // The message depends on _who_ left, and _how_ - if (how) { - gchar *mbuf_end; - // Forced leave - if (actorjid) { - mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s", - (how == ban ? "banned" : "kicked"), - roomjid, actorjid, reason); - } else { - mbuf_end = g_strdup_printf("%s from %s.", - (how == ban ? "banned" : "kicked"), - roomjid); - } - if (we_left) - mbuf = g_strdup_printf("You have been %s", mbuf_end); - else - mbuf = g_strdup_printf("%s has been %s", rname, mbuf_end); - - g_free(mbuf_end); - } else { - // Natural leave - if (we_left) { - xmlnode destroynode = xmlnode_get_tag(xmldata, "destroy"); - if (destroynode) { - if ((reason = xmlnode_get_tag_data(destroynode, "reason"))) { - mbuf = g_strdup_printf("You have left %s, " - "the room has been destroyed: %s", - roomjid, reason); - } else { - mbuf = g_strdup_printf("You have left %s, " - "the room has been destroyed", roomjid); - } - } else { - mbuf = g_strdup_printf("You have left %s", roomjid); - } - } else { - if (ust != offline) { - // This can happen when a network failure occurs, - // this isn't an official leave but the user isn't there anymore. - mbuf = g_strdup_printf("%s has disappeared!", rname); - ust = offline; - } else { - if (ustmsg) - mbuf = g_strdup_printf("%s has left: %s", rname, ustmsg); - else - mbuf = g_strdup_printf("%s has left", rname); - } - } - } - - // Display the mbuf message if we're concerned - // or if the print_status isn't set to none. - if (we_left || printstatus != status_none) { - msgflags = HBB_PREFIX_INFO; - if (!we_left && settings_opt_get_int("muc_flag_joins") != 2) - msgflags |= HBB_PREFIX_NOFLAG; - scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0); - } - - if (log_muc_conf) - hlog_write_message(roomjid, 0, -1, mbuf); - - if (we_left) { - scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); - g_free(mbuf); - return; - } - g_free(mbuf); - } else if (buddy_getstatus(room_elt->data, rname) == offline && - ust != offline) { - // Somebody is joining - new_member = muc_handle_join(room_elt, rname, roomjid, ournick, - printstatus, usttime, log_muc_conf); - } else { - // This is a simple member status change - - if (printstatus == status_all && !nickchange) { - mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname, - imstatus2char[ust], ((ustmsg) ? ustmsg : "")); - scr_WriteIncomingMessage(roomjid, mbuf, usttime, - HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); - g_free(mbuf); - } - } - - // Sanity check, shouldn't happen... - if (!rname) - return; - - // Update room member status - roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime, - mbrole, mbaffil, mbjid); - - autowhois = buddy_getautowhois(room_elt->data); - if (autowhois == autowhois_default) - autowhois = (settings_opt_get_int("muc_auto_whois") ? - autowhois_on : autowhois_off); - - if (new_member && autowhois == autowhois_on) { - // FIXME: This will fail for some UTF-8 nicknames. - gchar *joiner_nick = from_utf8(rname); - cmd_room_whois(room_elt->data, joiner_nick, FALSE); - g_free(joiner_nick); - } - - scr_DrawRoster(); -} - -static void handle_packet_presence(jconn conn, char *type, char *from, - xmlnode xmldata) -{ - char *p, *r; - char *ustmsg; - const char *rname; - enum imstatus ust; - char bpprio; - time_t timestamp = 0L; - xmlnode muc_packet; - - rname = strchr(from, JID_RESOURCE_SEPARATOR); - if (rname) rname++; - - if (settings_opt_get_int("ignore_self_presence")) { - const char *self_fjid = jid_full(jc->user); - if (self_fjid && !strcasecmp(self_fjid, from)) { - return; // Ignoring self presence - } - } - - r = jidtodisp(from); - - // Check for MUC presence packet - muc_packet = xml_get_xmlns(xmldata, "http://jabber.org/protocol/muc#user"); - - if (type && !strcmp(type, TMSG_ERROR)) { - xmlnode x; - scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r); - x = xmlnode_get_tag(xmldata, TMSG_ERROR); - display_server_error(x); - - // Let's check it isn't a nickname conflict. - // XXX Note: We should handle the string condition. - if ((p = xmlnode_get_attrib(x, "code")) != NULL) { - if (atoi(p) == 409) { - // 409 = conlict (nickname is in use or registered by another user) - // If we are not inside this room, we should reset the nickname - GSList *room_elt = roster_find(r, jidsearch, 0); - if (room_elt && !buddy_getinsideroom(room_elt->data)) - buddy_setnickname(room_elt->data, NULL); - } - } - - g_free(r); - return; - } - - p = xmlnode_get_tag_data(xmldata, "priority"); - if (p && *p) bpprio = (gchar)atoi(p); - else bpprio = 0; - - ust = available; - p = xmlnode_get_tag_data(xmldata, "show"); - if (p) { - if (!strcmp(p, "away")) ust = away; - else if (!strcmp(p, "dnd")) ust = dontdisturb; - else if (!strcmp(p, "xa")) ust = notavail; - else if (!strcmp(p, "chat")) ust = freeforchat; - } - - if (type && !strcmp(type, "unavailable")) - ust = offline; - - ustmsg = xmlnode_get_tag_data(xmldata, "status"); - - // Timestamp? - timestamp = xml_get_timestamp(xmldata); - - if (muc_packet) { - // This is a MUC presence message - handle_presence_muc(from, muc_packet, r, rname, - ust, ustmsg, timestamp, bpprio); - } else { - // Not a MUC message, so this is a regular buddy... - // Call hk_statuschange() if status has changed or if the - // status message is different - const char *m; - m = roster_getstatusmsg(r, rname); - if ((ust != roster_getstatus(r, rname)) || - (!ustmsg && m && m[0]) || (ustmsg && (!m || strcmp(ustmsg, m)))) - hk_statuschange(r, rname, bpprio, timestamp, ust, ustmsg); - // Presence signature processing - if (!ustmsg) - ustmsg = ""; // Some clients omit the element :-( - check_signature(r, rname, xml_get_xmlns(xmldata, NS_SIGNED), ustmsg); - } - - g_free(r); -} - -// got_invite(from, to, reason, passwd) -// This function should be called when receiving an invitation from user -// "from", to enter the room "to". Optional reason and room password can -// be provided. -static void got_invite(char* from, char *to, char* reason, char* passwd) -{ - eviqs *evn; - event_muc_invitation *invitation; - GString *sbuf; - char *barejid; - GSList *room_elt; - - sbuf = g_string_new(""); - if (reason) { - g_string_printf(sbuf, - "Received an invitation to <%s>, from <%s>, reason: %s", - to, from, reason); - } else { - g_string_printf(sbuf, "Received an invitation to <%s>, from <%s>", - to, from); - } - - barejid = jidtodisp(from); - scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str); - - evn = evs_new(EVS_TYPE_INVITATION, EVS_MAX_TIMEOUT); - if (evn) { - evn->callback = &evscallback_invitation; - invitation = g_new(event_muc_invitation, 1); - invitation->to = g_strdup(to); - invitation->from = g_strdup(from); - invitation->passwd = g_strdup(passwd); - invitation->reason = g_strdup(reason); - evn->data = invitation; - evn->desc = g_strdup_printf("<%s> invites you to %s ", from, to); - g_string_printf(sbuf, "Please use /event %s accept|reject", evn->id); - } else { - g_string_printf(sbuf, "Unable to create a new event!"); - } - scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str); - g_string_free(sbuf, TRUE); - g_free(barejid); - - // Make sure the MUC room barejid is a room in the roster - barejid = jidtodisp(to); - room_elt = roster_find(barejid, jidsearch, 0); - if (room_elt) - buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); - - g_free(barejid); -} - -// Specific MUC message handling (for example invitation processing) -static void got_muc_message(char *from, xmlnode x) -{ - xmlnode invite = xmlnode_get_tag(x, "invite"); - if (invite) - { - char* invite_from; - char *reason = NULL; - char *password = NULL; - xmlnode r; - - invite_from = xmlnode_get_attrib(invite, "from"); - r = xmlnode_get_tag(invite, "reason"); - if (r) - reason = xmlnode_get_tag_data(r, NULL); - r = xmlnode_get_tag(invite, "password"); - if (r) - password = xmlnode_get_tag_data(r, NULL); - if (invite_from) - got_invite(invite_from, from, reason, password); - } - // TODO - // handle status code = 100 ( not anonymous ) - // handle status code = 170 ( changement de config ) - // 10.2.1 Notification of Configuration Changes - // declined invitation -} - -static void handle_packet_message(jconn conn, char *type, char *from, - xmlnode xmldata) -{ - char *p, *r, *s; - xmlnode x; - char *body = NULL; - char *enc = NULL; - char *subject = NULL; - time_t timestamp = 0L; - - body = xmlnode_get_tag_data(xmldata, "body"); - - x = xml_get_xmlns(xmldata, NS_ENCRYPTED); - if (x && (p = xmlnode_get_data(x)) != NULL) - enc = p; - - p = xmlnode_get_tag_data(xmldata, "subject"); - - if (xmlnode_get_tag(xmldata, "subject")) { - if (!type || strcmp(type, TMSG_GROUPCHAT)) { // Chat message - subject = p; - } else { // Room topic - GSList *roombuddy; - gchar *mbuf = NULL; - gchar *subj = p; - - // In a groupchat message, the subject can be NULL when - // the topic is cleared! - if (!p) - p = ""; - - // Get the room (s) and the nickname (r) - s = g_strdup(from); - r = strchr(s, JID_RESOURCE_SEPARATOR); - if (r) *r++ = 0; - else r = s; - // Set the new topic - roombuddy = roster_find(s, jidsearch, 0); - if (roombuddy) - buddy_settopic(roombuddy->data, subj); - // Display inside the room window - if (r == s) { - // No specific resource (this is certainly history) - if (subj && *subj) - mbuf = g_strdup_printf("The topic has been set to: %s", subj); - } else { - if (subj) - mbuf = g_strdup_printf("%s has set the topic to: %s", r, subj); - else - mbuf = g_strdup_printf("%s has cleared the topic", r); - } - if (mbuf) { - scr_WriteIncomingMessage(s, mbuf, 0, - HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); - if (settings_opt_get_int("log_muc_conf")) - hlog_write_message(s, 0, -1, mbuf); - g_free(mbuf); - } - g_free(s); - // The topic is displayed in the chat status line, so refresh now. - scr_UpdateChatStatus(TRUE); - } - } - - // Timestamp? - timestamp = xml_get_timestamp(xmldata); - - if (type && !strcmp(type, TMSG_ERROR)) { - x = xmlnode_get_tag(xmldata, TMSG_ERROR); - display_server_error(x); -#if defined JEP0022 || defined JEP0085 - // If the JEP85/22 support is probed, set it back to unknown so that - // we probe it again. - chatstates_reset_probed(from); -#endif - } else { - handle_state_events(from, xmldata); - } - if (from && (body || subject)) - gotmessage(type, from, body, enc, subject, timestamp, - xml_get_xmlns(xmldata, NS_SIGNED)); - - if (from) { - x = xml_get_xmlns(xmldata, "http://jabber.org/protocol/muc#user"); - if (x && !strcmp(xmlnode_get_name(x), "x")) - got_muc_message(from, x); - } -} - -static void handle_state_events(char *from, xmlnode xmldata) -{ -#if defined JEP0022 || defined JEP0085 - xmlnode state_ns = NULL; - const char *body; - char *rname, *bjid; - GSList *sl_buddy; - guint events; - struct jep0022 *jep22 = NULL; - struct jep0085 *jep85 = NULL; - enum { - JEP_none, - JEP_85, - JEP_22 - } which_jep = JEP_none; - - rname = strchr(from, JID_RESOURCE_SEPARATOR); - if (rname) - ++rname; - else - rname = from + strlen(from); - bjid = jidtodisp(from); - sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); - g_free(bjid); - - /* XXX Actually that's wrong, since it filters out server "offline" - messages (for JEP-0022). This JEP is (almost) deprecated so - we don't really care. */ - if (!sl_buddy) { - return; - } - - /* Let's see chich JEP the contact uses. If possible, we'll use - JEP-85, if not we'll look for JEP-22 support. */ - events = buddy_resource_getevents(sl_buddy->data, rname); - - jep85 = buddy_resource_jep85(sl_buddy->data, rname); - if (jep85) { - state_ns = xml_get_xmlns(xmldata, NS_CHATSTATES); - if (state_ns) - which_jep = JEP_85; - } - - if (which_jep != JEP_85) { /* Fall back to JEP-0022 */ - jep22 = buddy_resource_jep22(sl_buddy->data, rname); - if (jep22) { - state_ns = xml_get_xmlns(xmldata, NS_EVENT); - if (state_ns) - which_jep = JEP_22; - } - } - - if (!which_jep) { /* Sender does not use chat states */ - return; - } - - body = xmlnode_get_tag_data(xmldata, "body"); - - if (which_jep == JEP_85) { /* JEP-0085 */ - const char *p; - jep85->support = CHATSTATES_SUPPORT_OK; - - p = xmlnode_get_name(state_ns); - if (!strcmp(p, "composing")) { - jep85->last_state_rcvd = ROSTER_EVENT_COMPOSING; - } else if (!strcmp(p, "active")) { - jep85->last_state_rcvd = ROSTER_EVENT_ACTIVE; - } else if (!strcmp(p, "paused")) { - jep85->last_state_rcvd = ROSTER_EVENT_PAUSED; - } else if (!strcmp(p, "inactive")) { - jep85->last_state_rcvd = ROSTER_EVENT_INACTIVE; - } else if (!strcmp(p, "gone")) { - jep85->last_state_rcvd = ROSTER_EVENT_GONE; - } - events = jep85->last_state_rcvd; - } else { /* JEP-0022 */ -#ifdef JEP0022 - const char *msgid; - jep22->support = CHATSTATES_SUPPORT_OK; - jep22->last_state_rcvd = ROSTER_EVENT_NONE; - - msgid = xmlnode_get_attrib(xmldata, "id"); - - if (xmlnode_get_tag(state_ns, "composing")) { - // Clear composing if the message contains a body - if (body) - events &= ~ROSTER_EVENT_COMPOSING; - else - events |= ROSTER_EVENT_COMPOSING; - jep22->last_state_rcvd |= ROSTER_EVENT_COMPOSING; - - } else { - events &= ~ROSTER_EVENT_COMPOSING; - } - - // Cache the message id - g_free(jep22->last_msgid_rcvd); - if (msgid) - jep22->last_msgid_rcvd = g_strdup(msgid); - else - jep22->last_msgid_rcvd = NULL; - - if (xmlnode_get_tag(state_ns, "delivered")) { - jep22->last_state_rcvd |= ROSTER_EVENT_DELIVERED; - - // Do we have to send back an ACK? - if (body) - jb_send_jep22_event(from, ROSTER_EVENT_DELIVERED); - } -#endif - } - - buddy_resource_setevents(sl_buddy->data, rname, events); - - update_roster = TRUE; -#endif -} - -static int evscallback_subscription(eviqs *evp, guint evcontext) -{ - char *barejid; - char *buf; - - if (evcontext == EVS_CONTEXT_TIMEOUT) { - scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", - evp->id); - return 0; - } - if (evcontext == EVS_CONTEXT_CANCEL) { - scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id); - return 0; - } - if (!(evcontext & EVS_CONTEXT_USER)) - return 0; - - // Sanity check - if (!evp->data) { - // Shouldn't happen, data should be set to the barejid. - scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); - return 0; - } - - // Ok, let's work now. - // evcontext: 0, 1 == reject, accept - - barejid = evp->data; - - if (evcontext & ~EVS_CONTEXT_USER) { - // Accept subscription request - jb_subscr_send_auth(barejid); - buf = g_strdup_printf("<%s> is allowed to receive your presence updates", - barejid); - } else { - // Reject subscription request - jb_subscr_cancel_auth(barejid); - buf = g_strdup_printf("<%s> won't receive your presence updates", barejid); - if (settings_opt_get_int("delete_on_reject")) { - // Remove the buddy from the roster if there is no current subscription - if (roster_getsubscription(barejid) == sub_none) - jb_delbuddy(barejid); - } - } - scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - return 0; -} - -static void decline_invitation(event_muc_invitation *invitation, char *reason) -{ - // cut and paste from jb_room_invite - xmlnode x,y,z; - - if (!invitation) return; - if (!invitation->to || !invitation->from) return; - - x = jutil_msgnew(NULL, (char*)invitation->to, NULL, NULL); - - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); - - z = xmlnode_insert_tag(y, "decline"); - xmlnode_put_attrib(z, "to", invitation->from); - - if (reason) { - y = xmlnode_insert_tag(z, "reason"); - xmlnode_insert_cdata(y, reason, (unsigned) -1); - } - - jab_send(jc, x); - xmlnode_free(x); - jb_reset_keepalive(); -} - -static int evscallback_invitation(eviqs *evp, guint evcontext) -{ - event_muc_invitation *invitation = evp->data; - - // Sanity check - if (!invitation) { - // Shouldn't happen. - scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); - return 0; - } - - if (evcontext == EVS_CONTEXT_TIMEOUT) { - scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", evp->id); - goto evscallback_invitation_free; - } - if (evcontext == EVS_CONTEXT_CANCEL) { - scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id); - goto evscallback_invitation_free; - } - if (!(evcontext & EVS_CONTEXT_USER)) - goto evscallback_invitation_free; - // Ok, let's work now. - // evcontext: 0, 1 == reject, accept - - if (evcontext & ~EVS_CONTEXT_USER) { - char *nickname = default_muc_nickname(invitation->to); - jb_room_join(invitation->to, nickname, invitation->passwd); - g_free(nickname); - } else { - scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to); - decline_invitation(invitation, NULL); - } - -evscallback_invitation_free: - g_free(invitation->to); - g_free(invitation->from); - g_free(invitation->passwd); - g_free(invitation->reason); - g_free(invitation); - evp->data = NULL; - return 0; -} - -static void handle_packet_s10n(jconn conn, char *type, char *from, - xmlnode xmldata) -{ - char *r; - char *buf; - int newbuddy; - - r = jidtodisp(from); - - newbuddy = !roster_find(r, jidsearch, 0); - - if (!strcmp(type, "subscribe")) { - /* The sender wishes to subscribe to our presence */ - char *msg; - int isagent; - eviqs *evn; - - isagent = (roster_gettype(r) & ROSTER_TYPE_AGENT) != 0; - msg = xmlnode_get_tag_data(xmldata, "status"); - - buf = g_strdup_printf("<%s> wants to subscribe to your presence updates", - from); - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - - if (msg) { - buf = g_strdup_printf("<%s> said: %s", from, msg); - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - replace_nl_with_dots(buf); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } - - // Create a new event item - evn = evs_new(EVS_TYPE_SUBSCRIPTION, EVS_MAX_TIMEOUT); - if (evn) { - evn->callback = &evscallback_subscription; - evn->data = g_strdup(r); - evn->desc = g_strdup_printf("<%s> wants to subscribe to your " - "presence updates", r); - buf = g_strdup_printf("Please use /event %s accept|reject", evn->id); - } else { - buf = g_strdup_printf("Unable to create a new event!"); - } - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } else if (!strcmp(type, "unsubscribe")) { - /* The sender is unsubscribing from our presence */ - jb_subscr_cancel_auth(from); - buf = g_strdup_printf("<%s> is unsubscribing from your " - "presence updates", from); - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } else if (!strcmp(type, "subscribed")) { - /* The sender has allowed us to receive their presence */ - buf = g_strdup_printf("<%s> has allowed you to receive their " - "presence updates", from); - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } else if (!strcmp(type, "unsubscribed")) { - /* The subscription request has been denied or a previously-granted - subscription has been cancelled */ - roster_unsubscribed(from); - update_roster = TRUE; - buf = g_strdup_printf("<%s> has cancelled your subscription to " - "their presence updates", from); - scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); - scr_LogPrint(LPRINT_LOGNORM, "%s", buf); - g_free(buf); - } else { - scr_LogPrint(LPRINT_LOGNORM, "Received unrecognized packet from <%s>, " - "type=%s", from, (type ? type : "")); - newbuddy = FALSE; - } - - if (newbuddy) - update_roster = TRUE; - g_free(r); -} - -static void packethandler(jconn conn, jpacket packet) -{ - char *p; - char *from=NULL, *type=NULL; - - jb_reset_keepalive(); // reset keepalive timeout - jpacket_reset(packet); - - if (!packet->type) { - scr_LogPrint(LPRINT_LOG, "Packet type = 0"); - return; - } - - p = xmlnode_get_attrib(packet->x, "type"); - if (p) type = p; - - p = xmlnode_get_attrib(packet->x, "from"); - if (p) from = p; - - if (!from && packet->type != JPACKET_IQ) { - scr_LogPrint(LPRINT_LOGNORM, "Error in stream packet"); - return; - } - - switch (packet->type) { - case JPACKET_MESSAGE: - handle_packet_message(conn, type, from, packet->x); - break; - - case JPACKET_IQ: - handle_packet_iq(conn, type, from, packet->x); - break; - - case JPACKET_PRESENCE: - handle_packet_presence(conn, type, from, packet->x); - break; - - case JPACKET_S10N: - handle_packet_s10n(conn, type, from, packet->x); - break; - - default: - scr_LogPrint(LPRINT_LOG, "Unhandled packet type (%d)", packet->type); - } -} - -/* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/jabglue.h --- a/mcabber/src/jabglue.h Thu Oct 08 19:40:23 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -#ifndef __JABGLUE_H__ -#define __JABGLUE_H__ 1 - -#include - -#include "roster.h" -#include "../libjabber/jabber.h" - -#if HAVE_CONFIG_H -# include -#endif - -#if ! HAVE_DECL_STRPTIME - extern char *strptime (); -#endif - -extern jconn jc; -extern guint AutoConnection; - -extern char imstatus2char[]; -// Status chars: '_', 'o', 'i', 'f', 'd', 'n', 'a' - -enum agtype { - unknown, - groupchat, - transport, - search -}; - -enum iqreq_type { - iqreq_none, - iqreq_version, - iqreq_time, - iqreq_last, - iqreq_vcard -}; - -struct annotation { - time_t cdate; - time_t mdate; - gchar *jid; - gchar *text; -}; - -struct bookmark { - gchar *roomjid; - gchar *name; - gchar *nick; - guint autojoin; - /* enum room_printstatus pstatus; */ - /* enum room_autowhois awhois; */ -}; - -char *jidtodisp(const char *fjid); -char *compose_jid(const char *username, const char *servername, - const char *resource); -jconn jb_connect(const char *fjid, const char *server, unsigned int port, - int ssl, const char *pass); -unsigned char jb_getonline(void); -void jb_disconnect(void); -void jb_main(void); -void jb_subscr_send_auth(const char *bjid); -void jb_subscr_cancel_auth(const char *bjid); -void jb_subscr_request_auth(const char *bjid); -void jb_subscr_request_cancel(const char *bjid); -void jb_addbuddy(const char *bjid, const char *name, const char *group); -void jb_delbuddy(const char *bjid); -void jb_updatebuddy(const char *bjid, const char *name, const char *group); -enum imstatus jb_getstatus(void); -const char *jb_getstatusmsg(void); -void jb_setstatus(enum imstatus st, const char *recipient, const char *msg, - int do_not_sign); -void jb_setprevstatus(void); -void jb_send_msg(const char *fjid, const char *text, int type, - const char *subject, const char *id, gint *encrypted, - const char *type_overwrite); -void jb_send_raw(const char *str); -void jb_send_chatstate(gpointer buddy, guint chatstate); -void jb_keepalive(void); -void jb_reset_keepalive(void); -void jb_set_keepalive_delay(unsigned int delay); -void jb_room_join(const char *room, const char *nickname, const char *passwd); -void jb_room_unlock(const char *room); -void jb_room_destroy(const char *room, const char *venue, const char *reason); -void jb_room_invite(const char *room, const char *fjid, const char *reason); -int jb_room_setattrib(const char *roomid, const char *fjid, const char *nick, - struct role_affil ra, const char *reason); -void jb_iqs_display_list(void); -void jb_request(const char *fjid, enum iqreq_type reqtype); -guint jb_is_bookmarked(const char *bjid); -const char *jb_get_bookmark_nick(const char *bjid); -GSList *jb_get_all_storage_bookmarks(void); -void jb_set_storage_bookmark(const char *roomid, const char *name, - const char *nick, const char *passwd, - int autojoin, enum room_printstatus pstatus, - enum room_autowhois awhois); -struct annotation *jb_get_storage_rosternotes(const char *barejid, int silent); -GSList *jb_get_all_storage_rosternotes(void); -void jb_set_storage_rosternotes(const char *barejid, const char *note); - -#endif /* __JABGLUE_H__ */ - -/* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/main.c --- a/mcabber/src/main.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/main.c Sun Oct 11 15:38:32 2009 +0200 @@ -31,7 +31,6 @@ #include #include -#include "jabglue.h" #include "screen.h" #include "settings.h" #include "roster.h" @@ -42,6 +41,7 @@ #include "pgp.h" #include "otr.h" #include "fifo.h" +#include "xmpp.h" #ifdef ENABLE_HGCSET # include "hgcset.h" @@ -52,6 +52,7 @@ #endif static unsigned int terminate_ui; +GMainLoop *main_loop = NULL; static struct termios *backup_termios; @@ -66,135 +67,10 @@ return ver; } -void mcabber_connect(void) -{ - const char *username, *password, *resource, *servername; - const char *proxy_host; - const char *resource_prefix = PACKAGE_NAME; - char *dynresource = NULL; - char *fjid; - int ssl; - int sslverify = -1; - const char *sslvopt = NULL, *cafile = NULL, *capath = NULL, *ciphers = NULL; - static char *cafile_xp, *capath_xp; - unsigned int port; - - servername = settings_opt_get("server"); - username = settings_opt_get("username"); - password = settings_opt_get("password"); - resource = settings_opt_get("resource"); - proxy_host = settings_opt_get("proxy_host"); - - // Free the ca*_xp strings if they've already been set. - g_free(cafile_xp); - g_free(capath_xp); - cafile_xp = capath_xp = NULL; - - if (!servername) { - scr_LogPrint(LPRINT_NORMAL, "Server name has not been specified!"); - return; - } - if (!username) { - scr_LogPrint(LPRINT_NORMAL, "User name has not been specified!"); - return; - } - if (!password) { - scr_LogPrint(LPRINT_NORMAL, "Password has not been specified!"); - return; - } - - port = (unsigned int) settings_opt_get_int("port"); - - ssl = settings_opt_get_int("ssl"); - sslvopt = settings_opt_get("ssl_verify"); - if (sslvopt) - sslverify = settings_opt_get_int("ssl_verify"); - cafile = settings_opt_get("ssl_cafile"); - capath = settings_opt_get("ssl_capath"); - ciphers = settings_opt_get("ssl_ciphers"); - -#if !defined(HAVE_OPENSSL) && !defined(HAVE_GNUTLS) - if (ssl) { - scr_LogPrint(LPRINT_LOGNORM, "** Error: SSL is NOT available, " - "do not set the option 'ssl'."); - return; - } else if (sslvopt || cafile || capath || ciphers) { - scr_LogPrint(LPRINT_LOGNORM, "** Warning: SSL is NOT available, " - "ignoring ssl-related settings"); - ssl = sslverify = 0; - cafile = capath = ciphers = NULL; - } -#elif defined HAVE_GNUTLS - if (ssl && sslverify != 0) { - scr_LogPrint(LPRINT_LOGNORM, "** Error: SSL certificate checking " - "is not supported yet with GnuTLS."); - scr_LogPrint(LPRINT_LOGNORM, - " * Please set 'ssl_verify' to 0 explicitly!"); - return; - } -#endif - cafile_xp = expand_filename(cafile); - capath_xp = expand_filename(capath); - cw_set_ssl_options(sslverify, cafile_xp, capath_xp, ciphers, servername); - // We can't free the ca*_xp variables now, because they're not duplicated - // in cw_set_ssl_options(). - - if (!resource) - resource = resource_prefix; - - if (!settings_opt_get("disable_random_resource")) { -#if HAVE_ARC4RANDOM - dynresource = g_strdup_printf("%s.%08x", resource, arc4random()); -#else - unsigned int tab[2]; - srand(time(NULL)); - tab[0] = (unsigned int) (0xffff * (rand() / (RAND_MAX + 1.0))); - tab[1] = (unsigned int) (0xffff * (rand() / (RAND_MAX + 1.0))); - dynresource = g_strdup_printf("%s.%04x%04x", resource, tab[0], tab[1]); -#endif - resource = dynresource; - } - - /* Connect to server */ - scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, "Connecting to server: %s", - servername); - if (port) - scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " using port %d", port); - scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " resource %s", resource); - - if (proxy_host) { - int proxy_port = settings_opt_get_int("proxy_port"); - if (proxy_port <= 0 || proxy_port > 65535) { - scr_LogPrint(LPRINT_LOGNORM, "Invalid proxy port: %d", proxy_port); - } else { - const char *proxy_user, *proxy_pass; - proxy_user = settings_opt_get("proxy_user"); - proxy_pass = settings_opt_get("proxy_pass"); - // Proxy initialization - cw_setproxy(proxy_host, proxy_port, proxy_user, proxy_pass); - scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " using proxy %s:%d", - proxy_host, proxy_port); - } - } - - fjid = compose_jid(username, servername, resource); -#if defined(HAVE_LIBOTR) - otr_init(fjid); -#endif - jc = jb_connect(fjid, servername, port, ssl, password); - g_free(fjid); - g_free(dynresource); - - if (!jc) - scr_LogPrint(LPRINT_LOGNORM, "Error connecting to (%s)", servername); - - jb_reset_keepalive(); -} - static void mcabber_terminate(const char *msg) { fifo_deinit(); - jb_disconnect(); + xmpp_disconnect(); scr_TerminateCurses(); // Restore term settings, if needed. @@ -259,7 +135,7 @@ /* Read the password. */ printf("Please enter %s: ", what); - fgets(password, passsize, stdin); + if (fgets(password, passsize, stdin) == NULL) return NULL; /* Restore terminal. */ tcsetattr(fileno(stdin), TCSAFLUSH, &orig); @@ -289,11 +165,6 @@ #ifdef HAVE_UNICODE puts("Compiled with unicode support."); #endif -#ifdef HAVE_OPENSSL - puts("Compiled with OpenSSL support."); -#elif defined HAVE_GNUTLS - puts("Compiled with GnuTLS support."); -#endif #ifdef HAVE_GPGME puts("Compiled with GPG support."); #endif @@ -376,14 +247,36 @@ terminate_ui = TRUE; } +gboolean mcabber_loop() +{ + keycode kcode; + + if (terminate_ui) { + g_main_loop_quit(main_loop); + return FALSE; + } + scr_DoUpdate(); + scr_Getch(&kcode); + + if (kcode.value != ERR) { + process_key(kcode); + } else { + scr_CheckAutoAway(FALSE); + + if (update_roster) + scr_DrawRoster(); + + hk_mainloop(); + } + return TRUE; +} + int main(int argc, char **argv) { char *configFile = NULL; const char *optstring; int optval, optval2; - unsigned int ping; int ret; - keycode kcode; credits(); @@ -484,12 +377,6 @@ if (optstring) hk_ext_cmd_init(optstring); - ping = 40; - if (settings_opt_get("pinginterval")) - ping = (unsigned int) settings_opt_get_int("pinginterval"); - jb_set_keepalive_delay(ping); - scr_LogPrint(LPRINT_DEBUG, "Ping interval established: %d secs", ping); - if (settings_opt_get_int("hide_offline_buddies") > 0) { // XXX Deprecated scr_RosterDisplay("ofdna"); scr_LogPrint(LPRINT_LOGNORM, @@ -511,39 +398,27 @@ /* Load previous roster state */ hlog_load_state(); + main_loop = g_main_loop_new(NULL, TRUE); + if (ret < 0) { scr_LogPrint(LPRINT_NORMAL, "No configuration file has been found."); scr_ShowBuddyWindow(); } else { /* Connection */ - mcabber_connect(); + xmpp_connect(); } scr_LogPrint(LPRINT_DEBUG, "Entering into main loop..."); - while (!terminate_ui) { - scr_DoUpdate(); - scr_Getch(&kcode); - - if (kcode.value != ERR) { - process_key(kcode); - } else { - scr_CheckAutoAway(FALSE); - - if (update_roster) - scr_DrawRoster(); - - jb_main(); - hk_mainloop(); - } - } + g_timeout_add(10, mcabber_loop, NULL); + g_main_loop_run(main_loop); scr_TerminateCurses(); fifo_deinit(); #ifdef HAVE_LIBOTR otr_terminate(); #endif - jb_disconnect(); + xmpp_disconnect(); #ifdef HAVE_GPGME gpg_terminate(); #endif diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/otr.c --- a/mcabber/src/otr.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/otr.c Sun Oct 11 15:38:32 2009 +0200 @@ -24,22 +24,22 @@ #ifdef HAVE_LIBOTR -#include "otr.h" +#include "hbuf.h" #include "logprint.h" -#include "hbuf.h" -#include "jab_priv.h" +#include "nohtml.h" +#include "otr.h" #include "roster.h" -#include "utils.h" #include "screen.h" #include "settings.h" -#include "nohtml.h" +#include "utils.h" +#include "xmpp.h" #define OTR_PROTOCOL_NAME "jabber" static OtrlUserState userstate = NULL; -static char * account = NULL; -static char * keyfile = NULL; -static char * fprfile = NULL; +static char *account = NULL; +static char *keyfile = NULL; +static char *fprfile = NULL; static int otr_is_enabled = FALSE; @@ -109,11 +109,11 @@ }; static void otr_message_disconnect(ConnContext *ctx); -static ConnContext * otr_get_context(const char *buddy); -static void otr_startstop(const char * buddy, int start); -static void otr_handle_smp_tlvs(OtrlTLV * tlvs, ConnContext * ctx); +static ConnContext *otr_get_context(const char *buddy); +static void otr_startstop(const char *buddy, int start); +static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx); -static char * otr_get_dir(void); +static char *otr_get_dir(void); void otr_init(const char *fjid) { @@ -149,7 +149,7 @@ void otr_terminate(void) { - ConnContext * ctx; + ConnContext *ctx; if (!otr_is_enabled) return; @@ -167,7 +167,7 @@ * This is reported to be a bug in libgcrypt :-/ * Mikael */ -#if defined(HAVE_GNUTLS) && !defined(HAVE_OPENSSL) +#if defined(HAVE_GNUTLS) && !defined(HAVE_OPENSSL) //TODO: broken now if (!settings_opt_get_int("ssl")) #endif otrl_userstate_free(userstate); @@ -177,7 +177,7 @@ keyfile = NULL; } -static char * otr_get_dir(void) +static char *otr_get_dir(void) { const char *configured_dir = settings_opt_get("otr_dir"); @@ -198,11 +198,11 @@ } } -static ConnContext * otr_get_context(const char *buddy) +static ConnContext *otr_get_context(const char *buddy) { int null = 0; - ConnContext * ctx; - char * lowcasebuddy = g_strdup(buddy); + ConnContext *ctx; + char *lowcasebuddy = g_strdup(buddy); mc_strtolower(lowcasebuddy); ctx = otrl_context_find(userstate, lowcasebuddy, account, OTR_PROTOCOL_NAME, @@ -219,9 +219,9 @@ ctx->protocol, ctx->username); } -static void otr_startstop(const char * buddy, int start) +static void otr_startstop(const char *buddy, int start) { - char * msg = NULL; + char *msg = NULL; ConnContext *ctx = otr_get_context(buddy); if (!userstate || !ctx) @@ -251,12 +251,12 @@ otr_startstop(buddy, 1); } -void otr_disconnect(const char * buddy) +void otr_disconnect(const char *buddy) { otr_startstop(buddy, 0); } -void otr_fingerprint(const char * buddy, const char * trust) +void otr_fingerprint(const char *buddy, const char *trust) { char fpr[45], *tr; ConnContext *ctx = otr_get_context(buddy); @@ -283,7 +283,7 @@ cb_write_fingerprints(NULL); } -static void otr_handle_smp_tlvs(OtrlTLV * tlvs, ConnContext * ctx) +static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx) { OtrlTLV *tlv = NULL; char *sbuf = NULL; @@ -358,13 +358,13 @@ * returns whether a otr_message was received * sets *otr_data to NULL, when it was an internal otr message */ -int otr_receive(char **otr_data, const char * buddy, int * free_msg) +int otr_receive(char **otr_data, const char *buddy, int *free_msg) { int ignore_message; char *newmessage = NULL; OtrlTLV *tlvs = NULL; OtrlTLV *tlv = NULL; - ConnContext * ctx; + ConnContext *ctx; ctx = otr_get_context(buddy); *free_msg = 0; @@ -406,7 +406,7 @@ gcry_error_t err; char *newmessage = NULL; char *htmlmsg; - ConnContext * ctx = otr_get_context(buddy); + ConnContext *ctx = otr_get_context(buddy); if (ctx->msgstate == OTRL_MSGSTATE_PLAINTEXT) err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname, @@ -434,10 +434,10 @@ } /* Prints OTR connection state */ -void otr_print_info(const char * buddy) +void otr_print_info(const char *buddy) { const char *state, *auth, *policy; - ConnContext * ctx = otr_get_context(buddy); + ConnContext *ctx = otr_get_context(buddy); OtrlPolicy p = cb_policy(ctx->app_data, ctx); if (!userstate || !ctx) @@ -491,9 +491,9 @@ ctx->username, state, auth, policy); } -static ConnContext * otr_context_encrypted(const char * buddy) +static ConnContext *otr_context_encrypted(const char *buddy) { - ConnContext * ctx = otr_get_context(buddy); + ConnContext *ctx = otr_get_context(buddy); if (!userstate || !ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED){ scr_LogPrint(LPRINT_LOGNORM, @@ -505,9 +505,9 @@ return ctx; } -void otr_smp_query(const char * buddy, const char * secret) +void otr_smp_query(const char *buddy, const char *secret) { - ConnContext * ctx = otr_context_encrypted(buddy); + ConnContext *ctx = otr_context_encrypted(buddy); if (!secret) { scr_LogPrint(LPRINT_LOGNORM, @@ -525,9 +525,9 @@ } } -void otr_smp_respond(const char * buddy, const char * secret) +void otr_smp_respond(const char *buddy, const char *secret) { - ConnContext * ctx = otr_context_encrypted(buddy); + ConnContext *ctx = otr_context_encrypted(buddy); if (!secret) { scr_LogPrint(LPRINT_LOGNORM, @@ -551,9 +551,9 @@ } } -void otr_smp_abort(const char * buddy) +void otr_smp_abort(const char *buddy) { - ConnContext * ctx = otr_context_encrypted(buddy); + ConnContext *ctx = otr_context_encrypted(buddy); if (ctx) { otrl_message_abort_smp(userstate, &ops, NULL, ctx); @@ -565,7 +565,7 @@ void otr_key(void) { - OtrlPrivKey * key; + OtrlPrivKey *key; char readable[45] = ""; if(!userstate) @@ -606,7 +606,7 @@ const char *protocol) { gcry_error_t e; - char * root; + char *root; scr_LogPrint(LPRINT_LOGNORM, "Generating new OTR key for %s. This may take a while...", @@ -643,10 +643,9 @@ const char *protocol, const char *recipient, const char *message) { - char * id = g_strdup("otrinject"); if (roster_gettype(recipient) == ROSTER_TYPE_USER) - jb_send_msg(recipient, message, ROSTER_TYPE_USER, "", id, NULL, NULL); - g_free(id); + xmpp_send_msg(recipient, message, ROSTER_TYPE_USER, "", TRUE, NULL, + LM_MESSAGE_SUB_TYPE_NOT_SET); } /* Display a notification message for a particular @@ -656,7 +655,7 @@ const char *username, const char *title, const char *primary, const char *secondary) { - char * type; + char *type; char *sbuf = NULL; switch (level) { case OTRL_NOTIFY_ERROR: type = "error"; break; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/pgp.c --- a/mcabber/src/pgp.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/pgp.c Sun Oct 11 15:38:32 2009 +0200 @@ -150,6 +150,9 @@ return g_strndup(p, q-p); } +// GCC ignores casts to void, thus we need to hack around that +static inline void ignore(void*x) {} + // passphrase_cb() // GPGME passphrase callback function. static gpgme_error_t passphrase_cb(void *hook, const char *uid_hint, @@ -159,7 +162,8 @@ // Abort if we do not have the password. if (!gpg.passphrase) { - write(fd, "\n", 1); + ignore((void*)write(fd, "\n", 1)); // We have an error anyway, thus it does + // not matter if we fail again. return gpg_error(GPG_ERR_CANCELED); } diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/screen.c --- a/mcabber/src/screen.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/screen.c Sun Oct 11 15:38:32 2009 +0200 @@ -58,6 +58,7 @@ #include "histolog.h" #include "settings.h" #include "utils.h" +#include "xmpp.h" #define get_color(col) (COLOR_PAIR(col)|COLOR_ATTRIB[col]) #define compose_color(col) (COLOR_PAIR(col->color_pair)|col->color_attrib) @@ -138,6 +139,7 @@ static int chatstate; /* (0=active, 1=composing, 2=paused) */ static bool lock_chatstate; static time_t chatstate_timestamp; +static guint chatstate_timeout_id = 0; int chatstates_disabled; #define MAX_KEYSEQ_LENGTH 8 @@ -159,9 +161,9 @@ unsigned int prefix_flags, int force_show, unsigned mucnicklen); -inline void scr_WriteMessage(const char *bjid, const char *text, - time_t timestamp, guint prefix_flags, - unsigned mucnicklen); +void scr_WriteMessage(const char *bjid, const char *text, + time_t timestamp, guint prefix_flags, + unsigned mucnicklen, gpointer xep184); inline void scr_UpdateBuddyWindow(void); inline void scr_set_chatmode(int enable); @@ -184,7 +186,7 @@ typedef struct { char *status, *wildcard; - ccolor * color; + ccolor *color; GPatternSpec *compiled; } rostercolor; @@ -194,7 +196,7 @@ typedef struct { bool manual; // Manually set? - ccolor * color; + ccolor *color; } nickcolor; static int nickcolcount = 0; @@ -235,11 +237,11 @@ return -1; } -static ccolor * get_user_color(const char *color) +static ccolor *get_user_color(const char *color) { bool isbright = FALSE; int cl; - ccolor * ccol; + ccolor *ccol; if (!strncmp(color, "bright", 6)) { isbright = TRUE; color += 6; @@ -317,7 +319,7 @@ g_free(mnick); need_update = TRUE; } else { - ccolor * cl = get_user_color(color); + ccolor *cl = get_user_color(color); if (!cl) { scr_LogPrint(LPRINT_NORMAL, "No such color name"); g_free(snick); @@ -389,7 +391,7 @@ return FALSE; } } else { - ccolor * cl = get_user_color(color); + ccolor *cl = get_user_color(color); if (!cl) { scr_LogPrint(LPRINT_NORMAL, "No such color name"); return FALSE; @@ -520,7 +522,7 @@ ncolors++; } else { char *end = ncolors; - ccolor * cl; + ccolor *cl; while (*end && (*end != ' ') && (*end != '\t')) end++; *end = '\0'; @@ -1381,7 +1383,7 @@ // Redraw the main (bottom) status line. void scr_UpdateMainStatus(int forceupdate) { - char *sm = from_utf8(jb_getstatusmsg()); + char *sm = from_utf8(xmpp_getstatusmsg()); const char *info = settings_opt_get("info"); werase(mainstatusWnd); @@ -1389,13 +1391,13 @@ char *info_locale = from_utf8(info); mvwprintw(mainstatusWnd, 0, 0, "%c[%c] %s: %s", (unread_msg(NULL) ? '#' : ' '), - imstatus2char[jb_getstatus()], + imstatus2char[xmpp_getstatus()], info_locale, (sm ? sm : "")); g_free(info_locale); } else mvwprintw(mainstatusWnd, 0, 0, "%c[%c] %s", (unread_msg(NULL) ? '#' : ' '), - imstatus2char[jb_getstatus()], (sm ? sm : "")); + imstatus2char[xmpp_getstatus()], (sm ? sm : "")); if (forceupdate) { top_panel(inputPanel); update_panels(); @@ -1730,7 +1732,7 @@ status = 'C'; else status = 'x'; - } else if (jb_getstatus() != offline) { + } else if (xmpp_getstatus() != offline) { enum imstatus budstate; budstate = buddy_getstatus(BUDDATA(current_buddy), NULL); if (budstate < imstatus_size) @@ -1813,7 +1815,7 @@ int rOffset; int cursor_backup; char status, pending; - enum imstatus currentstatus = jb_getstatus(); + enum imstatus currentstatus = xmpp_getstatus(); int x_pos; // We can reset update_roster @@ -1964,7 +1966,7 @@ name[0] = 0; if (isgrp) { - if (ishid){ + if (ishid) { int group_count = 0; foreach_group_member(BUDDATA(buddy), increment_if_buddy_not_filtered, &group_count); @@ -2102,21 +2104,21 @@ if (setaway) { const char *msg, *prevmsg; - oldstatus = jb_getstatus(); + oldstatus = xmpp_getstatus(); if (oldmsg) { g_free(oldmsg); oldmsg = NULL; } - prevmsg = jb_getstatusmsg(); + prevmsg = xmpp_getstatusmsg(); msg = settings_opt_get("message_autoaway"); if (!msg) msg = prevmsg; if (prevmsg) oldmsg = g_strdup(prevmsg); - jb_setstatus(away, NULL, msg, FALSE); + xmpp_setstatus(away, NULL, msg, FALSE); } else { // Back - jb_setstatus(oldstatus, NULL, (oldmsg ? oldmsg : ""), FALSE); + xmpp_setstatus(oldstatus, NULL, (oldmsg ? oldmsg : ""), FALSE); if (oldmsg) { g_free(oldmsg); oldmsg = NULL; @@ -2124,28 +2126,9 @@ } } -long int scr_GetAutoAwayTimeout(time_t now) -{ - enum imstatus cur_st; - unsigned int autoaway_timeout = settings_opt_get_int("autoaway"); - - if (Autoaway || !autoaway_timeout) - return 86400; - - cur_st = jb_getstatus(); - // Auto-away is disabled for the following states - if ((cur_st != available) && (cur_st != freeforchat)) - return 86400; - - if (now >= LastActivity + (time_t)autoaway_timeout) - return 0; - else - return LastActivity + (time_t)autoaway_timeout - now; -} - // set_chatstate(state) // Set the current chat state (0=active, 1=composing, 2=paused) -// If the chat state has changed, call jb_send_chatstate() +// If the chat state has changed, call xmpp_send_chatstate() static inline void set_chatstate(int state) { #if defined JEP0022 || defined JEP0085 @@ -2158,13 +2141,18 @@ if (current_buddy && buddy_gettype(BUDDATA(current_buddy)) == ROSTER_TYPE_USER) { guint jep_state; - if (chatstate == 1) + if (chatstate == 1) { + if (chatstate_timeout_id == 0) + chatstate_timeout_id = g_timeout_add_seconds(1, + scr_ChatStatesTimeout, + NULL); jep_state = ROSTER_EVENT_COMPOSING; + } else if (chatstate == 2) jep_state = ROSTER_EVENT_PAUSED; else jep_state = ROSTER_EVENT_ACTIVE; - jb_send_chatstate(BUDDATA(current_buddy), jep_state); + xmpp_send_chatstate(BUDDATA(current_buddy), jep_state); } if (!chatstate) chatstate_timestamp = 0; @@ -2173,20 +2161,24 @@ } #if defined JEP0022 || defined JEP0085 -long int scr_GetChatStatesTimeout(time_t now) +gboolean scr_ChatStatesTimeout(void) { + time_t now; + time(&now); // Check if we're currently composing... - if (chatstate != 1 || !chatstate_timestamp) - return 86400; + if (chatstate != 1 || !chatstate_timestamp) { + chatstate_timeout_id = 0; + return FALSE; + } // If the timeout is reached, let's change the state right now. if (now >= chatstate_timestamp + COMPOSING_TIMEOUT) { chatstate_timestamp = now; set_chatstate(2); - return 86400; + chatstate_timeout_id = 0; + return FALSE; } - - return chatstate_timestamp + COMPOSING_TIMEOUT - now; + return TRUE; } #endif @@ -2200,7 +2192,7 @@ if (!autoaway_timeout) return; if (!LastActivity || activity) time(&LastActivity); - cur_st = jb_getstatus(); + cur_st = xmpp_getstatus(); // Auto-away is disabled for the following states if ((cur_st != available) && (cur_st != freeforchat)) return; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/screen.h --- a/mcabber/src/screen.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/screen.h Sun Oct 11 15:38:32 2009 +0200 @@ -22,6 +22,7 @@ #include "hbuf.h" #include "logprint.h" +#include "roster.h" #define INPUTLINE_LENGTH 1024 @@ -119,11 +120,10 @@ bool Autoaway; -long int scr_GetAutoAwayTimeout(time_t now); void scr_CheckAutoAway(int activity); #if defined JEP0022 || defined JEP0085 -long int scr_GetChatStatesTimeout(time_t now); +gboolean scr_ChatStatesTimeout(); #endif int chatstates_disabled; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/settings.c --- a/mcabber/src/settings.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/settings.c Sun Oct 11 15:38:32 2009 +0200 @@ -19,15 +19,16 @@ * USA */ -#include +#include #include -#include +#include #include "settings.h" #include "commands.h" -#include "utils.h" #include "logprint.h" #include "otr.h" +#include "utils.h" +#include "xmpp.h" // Maximum line length // (probably best to use the same value as INPUTLINE_LENGTH) @@ -392,7 +393,7 @@ { char *nick; - nick = (char*)jb_get_bookmark_nick(roomid); + nick = (char*)xmpp_get_bookmark_nick(roomid); if (nick) return g_strdup(nick); @@ -537,7 +538,7 @@ /* otr settings */ #ifdef HAVE_LIBOTR -static void remove_default_policies(char * k, char * policy, void * defaultp) +static void remove_default_policies(char *k, char *policy, void *defaultp) { if (*(enum otr_policy *)policy == *(enum otr_policy *)defaultp) { g_free((enum otr_policy *) policy); @@ -578,7 +579,7 @@ guint settings_otr_getpolicy(const char *bjid) { #ifdef HAVE_LIBOTR - enum otr_policy * otrdata; + enum otr_policy *otrdata; if (!bjid) return default_policy; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/settings.h --- a/mcabber/src/settings.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/settings.h Sun Oct 11 15:38:32 2009 +0200 @@ -4,7 +4,7 @@ #include #include -#include "jabglue.h" +#include "roster.h" #ifndef isblank # define isblank(c) ((c) == 0x20 || (c) == 0x09) diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/utils.c --- a/mcabber/src/utils.c Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/utils.c Sun Oct 11 15:38:32 2009 +0200 @@ -26,6 +26,8 @@ #include #include +#include + /* For Cygwin (thanks go to Yitzchak Scott-Thoennes) */ #ifdef __CYGWIN__ # define timezonevar @@ -45,6 +47,55 @@ static int DebugEnabled; static char *FName; +// jidtodisp(jid) +// Strips the resource part from the jid +// The caller should g_free the result after use. +char *jidtodisp(const char *fjid) +{ + char *ptr; + char *alias; + + alias = g_strdup(fjid); + + if ((ptr = strchr(alias, JID_RESOURCE_SEPARATOR)) != NULL) { + *ptr = 0; + } + return alias; +} + +char *compose_jid(const char *username, const char *servername, + const char *resource) +{ + char *fjid; + + if (!strchr(username, JID_DOMAIN_SEPARATOR)) { + fjid = g_strdup_printf("%s%c%s%c%s", username, + JID_DOMAIN_SEPARATOR, servername, + JID_RESOURCE_SEPARATOR, resource); + } else { + fjid = g_strdup_printf("%s%c%s", username, + JID_RESOURCE_SEPARATOR, resource); + } + return fjid; +} + +gboolean jid_equal(const char *jid1, const char *jid2) +{ + char *a,*b; + int ret; + if (!jid1 && !jid2) + return TRUE; + if (!jid1 || !jid2) + return FALSE; + + a = jidtodisp(jid1); + b = jidtodisp(jid2); + ret = strcasecmp(a, b); + g_free(a); + g_free(b); + return (ret == 0) ? TRUE : FALSE; +} + // expand_filename(filename) // Expand "~/" with the $HOME env. variable in a file name. // The caller must free the string after use. @@ -60,6 +111,29 @@ return g_strdup(fname); } +void fingerprint_to_hex(const unsigned char *fpr, char hex[49]) +{ + int i; + char *p; + + for (p = hex, i = 0; i < 15; i++, p+=3) + g_sprintf(p, "%02X:", fpr[i]); + g_sprintf(p, "%02X", fpr[i]); + hex[48] = '\0'; +} + +gboolean hex_to_fingerprint(const char *hex, char fpr[16]) +{ + int i; + char *p; + + if (strlen(hex) != 47) + return FALSE; + for (i = 0, p = (char*)hex; *p && *(p+1); i++, p += 3) + fpr[i] = (char) g_ascii_strtoull (p, NULL, 16); + return TRUE; +} + void ut_InitDebug(int level, const char *filename) { FILE *fp; diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/utils.h --- a/mcabber/src/utils.h Thu Oct 08 19:40:23 2009 +0200 +++ b/mcabber/src/utils.h Sun Oct 11 15:38:32 2009 +0200 @@ -14,6 +14,14 @@ #define JID_DOMAIN_SEPARATOR '@' #define JID_DOMAIN_SEPARATORSTR "@" +char *jidtodisp(const char *fjid); +char *compose_jid(const char *username, const char *servername, + const char *resource); +gboolean jid_equal(const char *jid1, const char *jid2); + +void fingerprint_to_hex(const unsigned char *fpr, char hex[49]); +gboolean hex_to_fingerprint(const char * hex, char fpr[16]); + void ut_InitDebug(int level, const char *file); void ut_WriteLog(unsigned int flag, const char *data); diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,2154 @@ +/* + * xmpp.c -- Jabber protocol handling + * + * Copyright (C) 2008 Frank Zschockelt + * Copyright (C) 2005-2008 Mikael Berthe + * Parts come from the centericq project: + * Copyright (C) 2002-2005 by Konstantin Klyagin + * + * 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 +#include +#include + +#include "commands.h" +#include "events.h" +#include "histolog.h" +#include "hooks.h" +#include "logprint.h" +#include "otr.h" +#include "roster.h" +#include "screen.h" +#include "settings.h" +#include "utils.h" +#include "xmpp.h" +#include "xmpp_helper.h" +#include "xmpp_defines.h" + +#define RECONNECTION_TIMEOUT 60L + +LmConnection* lconnection; +static guint AutoConnection; + +inline void update_last_use(void); +inline gboolean xmpp_reconnect(); + +static enum imstatus mystatus = offline; +static enum imstatus mywantedstatus = available; +static gchar *mystatusmsg; + +char imstatus2char[imstatus_size+1] = { + '_', 'o', 'f', 'd', 'n', 'a', 'i', '\0' +}; + +static char *imstatus_showmap[] = { + "", + "", + "chat", + "dnd", + "xa", + "away", + "" +}; + +static LmMessageNode *bookmarks = NULL; +static LmMessageNode *rosternotes = NULL; + +struct xmpp_error { + guint code; + const char *code_str; + const char *meaning; + const char *condition; + const char *type; +} xmpp_errors[] = { + {XMPP_ERROR_REDIRECT, "302", + "Redirect", "redirect", "modify"}, + {XMPP_ERROR_BAD_REQUEST, "400", + "Bad Request", "bad-request", "modify"}, + {XMPP_ERROR_NOT_AUTHORIZED, "401", + "Not Authorized", "not-authorized", "auth"}, + {XMPP_ERROR_PAYMENT_REQUIRED, "402", + "Payment Required", "payment-required", "auth"}, + {XMPP_ERROR_FORBIDDEN, "403", + "Forbidden", "forbidden", "auth"}, + {XMPP_ERROR_NOT_FOUND, "404", + "Not Found", "item-not-found", "cancel"}, + {XMPP_ERROR_NOT_ALLOWED, "405", + "Not Allowed", "not-allowed", "cancel"}, + {XMPP_ERROR_NOT_ACCEPTABLE, "406", + "Not Acceptable", "not-acceptable", "modify"}, + {XMPP_ERROR_REGISTRATION_REQUIRED, "407", + "Registration required", "registration-required", "auth"}, + {XMPP_ERROR_REQUEST_TIMEOUT, "408", + "Request Timeout", "remote-server-timeout", "wait"}, + {XMPP_ERROR_CONFLICT, "409", + "Conflict", "conflict", "cancel"}, + {XMPP_ERROR_INTERNAL_SERVER_ERROR, "500", + "Internal Server Error", "internal-server-error", "wait"}, + {XMPP_ERROR_NOT_IMPLEMENTED, "501", + "Not Implemented", "feature-not-implemented", "cancel"}, + {XMPP_ERROR_REMOTE_SERVER_ERROR, "502", + "Remote Server Error", "service-unavailable", "wait"}, + {XMPP_ERROR_SERVICE_UNAVAILABLE, "503", + "Service Unavailable", "service-unavailable", "cancel"}, + {XMPP_ERROR_REMOTE_SERVER_TIMEOUT, "504", + "Remote Server Timeout", "remote-server-timeout", "wait"}, + {XMPP_ERROR_DISCONNECTED, "510", + "Disconnected", "service-unavailable", "cancel"}, + {0, NULL, NULL, NULL, NULL} +}; + +#include "xmpp_helper.c" +#include "xmpp_iq.c" +#include "xmpp_iqrequest.c" +#include "xmpp_muc.c" +#include "xmpp_s10n.c" + +static struct IqHandlers +{ + const gchar *xmlns; + LmHandleMessageFunction handler; +} iq_handlers[] = { + {NS_PING, &handle_iq_ping}, + {NS_VERSION, &handle_iq_version}, + {NS_TIME, &handle_iq_time}, + {NS_ROSTER, &handle_iq_roster}, + {NS_XMPP_TIME, &handle_iq_time202}, + {NS_LAST, &handle_iq_last}, + {NS_DISCO_INFO, &handle_iq_disco_info}, + {NS_DISCO_ITEMS,&handle_iq_disco_items}, + {NS_COMMANDS, &handle_iq_commands}, + {NULL, NULL} +}; + +void update_last_use(void) +{ + iqlast = time(NULL); +} + +// Note: the caller should check the jid is correct +void xmpp_addbuddy(const char *bjid, const char *name, const char *group) +{ + LmMessageNode *query, *y; + LmMessage *iq; + char *cleanjid; + + if (!lm_connection_is_authenticated(lconnection)) return; + + cleanjid = jidtodisp(bjid); // Stripping resource, just in case... + + // We don't check if the jabber user already exists in the roster, + // because it allows to re-ask for notification. + + iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + query = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", NS_ROSTER); + y = lm_message_node_add_child(query, "item", NULL); + lm_message_node_set_attribute(y, "jid", cleanjid); + + if (name) + lm_message_node_set_attribute(y, "name", name); + + if (group) + lm_message_node_add_child(y, "group", group); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); + + xmpp_send_s10n(cleanjid, LM_MESSAGE_SUB_TYPE_SUBSCRIBE); + + roster_add_user(cleanjid, name, group, ROSTER_TYPE_USER, sub_pending, -1); + g_free(cleanjid); + buddylist_build(); + + update_roster = TRUE; +} + +void xmpp_updatebuddy(const char *bjid, const char *name, const char *group) +{ + LmMessage *iq; + LmMessageNode *x; + char *cleanjid; + + if (!lm_connection_is_authenticated(lconnection)) return; + + // XXX We should check name's and group's correctness + + cleanjid = jidtodisp(bjid); // Stripping resource, just in case... + + iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + x = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(x, "xmlns", NS_ROSTER); + x = lm_message_node_add_child(x, "item", NULL); + lm_message_node_set_attributes(x, + "jid", cleanjid, + "name", name, + NULL); + + if (group) + lm_message_node_add_child(x, "group", group); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); + g_free(cleanjid); +} + +void xmpp_delbuddy(const char *bjid) +{ + LmMessageNode *y, *z; + LmMessage *iq; + char *cleanjid; + + if (!lm_connection_is_authenticated(lconnection)) return; + + cleanjid = jidtodisp(bjid); // Stripping resource, just in case... + + // If the current buddy is an agent, unsubscribe from it + if (roster_gettype(cleanjid) == ROSTER_TYPE_AGENT) { + scr_LogPrint(LPRINT_LOGNORM, "Unregistering from the %s agent", cleanjid); + + iq = lm_message_new_with_sub_type(cleanjid, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + y = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(y, "xmlns", NS_REGISTER); + lm_message_node_add_child(y, "remove", NULL); + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); + } + + // Cancel the subscriptions + xmpp_send_s10n(cleanjid, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED); //cancel "from" + xmpp_send_s10n(cleanjid, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE); //cancel "to" + + // Ask for removal from roster + iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + + y = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(y, "xmlns", NS_ROSTER); + z = lm_message_node_add_child(y, "item", NULL); + lm_message_node_set_attributes(z, + "jid", cleanjid, + "subscription", "remove", + NULL); + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); + + roster_del_user(cleanjid); + g_free(cleanjid); + buddylist_build(); + + update_roster = TRUE; +} + +void xmpp_request(const char *fjid, enum iqreq_type reqtype) +{ + GSList *resources, *p_res; + GSList *roster_elt; + const char *strreqtype, *xmlns; + + if (reqtype == iqreq_version) { + xmlns = NS_VERSION; + strreqtype = "version"; + } else if (reqtype == iqreq_time) { + xmlns = NS_TIME; + strreqtype = "time"; + } else if (reqtype == iqreq_last) { + xmlns = NS_LAST; + strreqtype = "last"; + } else if (reqtype == iqreq_vcard) { + xmlns = NS_VCARD; + strreqtype = "vCard"; + // Special case + } else + return; + + if (strchr(fjid, JID_RESOURCE_SEPARATOR)) { + // This is a full JID + xmpp_iq_request(fjid, xmlns); + scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); + return; + } + + // The resource has not been specified + roster_elt = roster_find(fjid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); + if (!roster_elt) { + scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); + xmpp_iq_request(fjid, xmlns); // Let's send a request anyway... + scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); + return; + } + + // Send a request to each resource + resources = buddy_getresources(roster_elt->data); + if (!resources) { + scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); + xmpp_iq_request(fjid, xmlns); // Let's send a request anyway... + scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); + } + for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) { + gchar *fulljid; + fulljid = g_strdup_printf("%s/%s", fjid, (char*)p_res->data); + xmpp_iq_request(fulljid, xmlns); + scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fulljid); + g_free(fulljid); + g_free(p_res->data); + } + g_slist_free(resources); +} + +// xmpp_send_msg(jid, text, type, subject, +// otrinject, *encrypted, type_overwrite) +// When encrypted is not NULL, the function set *encrypted to 1 if the +// message has been PGP-encrypted. If encryption enforcement is set and +// encryption fails, *encrypted is set to -1. +void xmpp_send_msg(const char *fjid, const char *text, int type, + const char *subject, gboolean otrinject, gint *encrypted, + LmMessageSubType type_overwrite) +{ + LmMessage *x; + LmMessageSubType subtype; +#ifdef HAVE_LIBOTR + int otr_msg = 0; +#endif +#if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 + char *rname, *barejid; + GSList *sl_buddy; +#endif +#if defined JEP0022 || defined JEP0085 + LmMessageNode *event; + guint use_jep85 = 0; + struct jep0085 *jep85 = NULL; +#endif + gchar *enc = NULL; + + if (encrypted) + *encrypted = 0; + + if (!lm_connection_is_authenticated(lconnection)) + return; + + if (!text && type == ROSTER_TYPE_USER) + return; + + if (type_overwrite != LM_MESSAGE_SUB_TYPE_NOT_SET) + subtype = type_overwrite; + else { + if (type == ROSTER_TYPE_ROOM) + subtype = LM_MESSAGE_SUB_TYPE_GROUPCHAT; + else + subtype = LM_MESSAGE_SUB_TYPE_CHAT; + } + +#if defined HAVE_GPGME || defined HAVE_LIBOTR || \ + defined JEP0022 || defined JEP0085 + rname = strchr(fjid, JID_RESOURCE_SEPARATOR); + barejid = jidtodisp(fjid); + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + + // If we can get a resource name, we use it. Else we use NULL, + // which hopefully will give us the most likely resource. + if (rname) + rname++; + +#ifdef HAVE_LIBOTR + if (otr_enabled() && !otrinject) { + if (type == ROSTER_TYPE_USER) { + otr_msg = otr_send((char **)&text, barejid); + if (!text) { + g_free(barejid); + if (encrypted) + *encrypted = -1; + return; + } + } + if (otr_msg && encrypted) + *encrypted = ENCRYPTED_OTR; + } +#endif + +#ifdef HAVE_GPGME + if (type == ROSTER_TYPE_USER && sl_buddy && gpg_enabled()) { + if (!settings_pgp_getdisabled(barejid)) { // not disabled for this contact? + guint force; + struct pgp_data *res_pgpdata; + force = settings_pgp_getforce(barejid); + res_pgpdata = buddy_resource_pgp(sl_buddy->data, rname); + if (force || (res_pgpdata && res_pgpdata->sign_keyid)) { + /* Remote client has PGP support (we have a signature) + * OR encryption is enforced (force = TRUE). + * If the contact has a specific KeyId, we'll use it; + * if not, we'll use the key used for the signature. + * Both keys should match, in theory (cf. XEP-0027). */ + const char *key; + key = settings_pgp_getkeyid(barejid); + if (!key && res_pgpdata) + key = res_pgpdata->sign_keyid; + if (key) + enc = gpg_encrypt(text, key); + if (!enc && force) { + if (encrypted) + *encrypted = -1; + g_free(barejid); + return; + } + } + } + } +#endif // HAVE_GPGME + + g_free(barejid); +#endif // HAVE_GPGME || defined JEP0022 || defined JEP0085 + + x = lm_message_new_with_sub_type(fjid, LM_MESSAGE_TYPE_MESSAGE, subtype); + lm_message_node_add_child(x->node, "body", + enc ? "This message is PGP-encrypted." : text); + + if (subject) + lm_message_node_add_child(x->node, "subject", subject); + + if (enc) { + LmMessageNode *y; + y = lm_message_node_add_child(x->node, "x", enc); + lm_message_node_set_attribute(y, "xmlns", NS_ENCRYPTED); + if (encrypted) + *encrypted = ENCRYPTED_PGP; + g_free(enc); + } + +#if defined JEP0022 || defined JEP0085 + // If typing notifications are disabled, we can skip all this stuff... + if (chatstates_disabled || type == ROSTER_TYPE_ROOM) + goto xmpp_send_msg_no_chatstates; + + if (sl_buddy) + jep85 = buddy_resource_jep85(sl_buddy->data, rname); +#endif + +#ifdef JEP0085 + /* JEP-0085 5.1 + * "Until receiving a reply to the initial content message (or a standalone + * notification) from the Contact, the User MUST NOT send subsequent chat + * state notifications to the Contact." + * In our implementation support is initially "unknown", then it's "probed" + * and can become "ok". + */ + if (jep85 && (jep85->support == CHATSTATES_SUPPORT_OK || + jep85->support == CHATSTATES_SUPPORT_UNKNOWN)) { + event = lm_message_node_add_child(x->node, "active", NULL); + lm_message_node_set_attribute(event, "xmlns", NS_CHATSTATES); + if (jep85->support == CHATSTATES_SUPPORT_UNKNOWN) + jep85->support = CHATSTATES_SUPPORT_PROBED; + else + use_jep85 = 1; + jep85->last_state_sent = ROSTER_EVENT_ACTIVE; + } +#endif +#ifdef JEP0022 + /* JEP-22 + * If the Contact supports JEP-0085, we do not use JEP-0022. + * If not, we try to fall back to JEP-0022. + */ + if (!use_jep85) { + struct jep0022 *jep22 = NULL; + event = lm_message_node_add_child(x->node, "x", NULL); + lm_message_node_set_attribute(event, "xmlns", NS_EVENT); + lm_message_node_add_child(event, "composing", NULL); + + if (sl_buddy) + jep22 = buddy_resource_jep22(sl_buddy->data, rname); + if (jep22) + jep22->last_state_sent = ROSTER_EVENT_ACTIVE; + + // An id is mandatory when using JEP-0022. + if (text || subject) { + const gchar *msgid = lm_message_get_id(x); + // Let's update last_msgid_sent + if (jep22) { + g_free(jep22->last_msgid_sent); + jep22->last_msgid_sent = g_strdup(msgid); + } + } + } +#endif + +xmpp_send_msg_no_chatstates: + if (mystatus != invisible) + update_last_use(); + lm_connection_send(lconnection, x, NULL); + lm_message_unref(x); +} + +#ifdef JEP0085 +// xmpp_send_jep85_chatstate() +// Send a JEP-85 chatstate. +static void xmpp_send_jep85_chatstate(const char *bjid, const char *resname, + guint state) +{ + LmMessage *m; + LmMessageNode *event; + GSList *sl_buddy; + const char *chattag; + char *rjid, *fjid = NULL; + struct jep0085 *jep85 = NULL; + + if (!lm_connection_is_authenticated(lconnection)) return; + + sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); + + // If we have a resource name, we use it. Else we use NULL, + // which hopefully will give us the most likely resource. + if (sl_buddy) + jep85 = buddy_resource_jep85(sl_buddy->data, resname); + + if (!jep85 || (jep85->support != CHATSTATES_SUPPORT_OK)) + return; + + if (state == jep85->last_state_sent) + return; + + if (state == ROSTER_EVENT_ACTIVE) + chattag = "active"; + else if (state == ROSTER_EVENT_COMPOSING) + chattag = "composing"; + else if (state == ROSTER_EVENT_PAUSED) + chattag = "paused"; + else { + scr_LogPrint(LPRINT_LOGNORM, "Error: unsupported JEP-85 state (%d)", state); + return; + } + + jep85->last_state_sent = state; + + if (resname) + fjid = g_strdup_printf("%s/%s", bjid, resname); + + rjid = resname ? fjid : (char*)bjid; + m = lm_message_new_with_sub_type(rjid, LM_MESSAGE_TYPE_MESSAGE, + LM_MESSAGE_SUB_TYPE_CHAT); + + event = lm_message_node_add_child(m->node, chattag, NULL); + lm_message_node_set_attribute(event, "xmlns", NS_CHATSTATES); + + lm_connection_send(lconnection, m, NULL); + lm_message_unref(m); + + g_free(fjid); +} +#endif + +#ifdef JEP0022 +// xmpp_send_jep22_event() +// Send a JEP-22 message event (delivered, composing...). +static void xmpp_send_jep22_event(const char *fjid, guint type) +{ + LmMessage *x; + LmMessageNode *event; + const char *msgid; + char *rname, *barejid; + GSList *sl_buddy; + struct jep0022 *jep22 = NULL; + guint jep22_state; + + if (!lm_connection_is_authenticated(lconnection)) return; + + rname = strchr(fjid, JID_RESOURCE_SEPARATOR); + barejid = jidtodisp(fjid); + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + g_free(barejid); + + // If we can get a resource name, we use it. Else we use NULL, + // which hopefully will give us the most likely resource. + if (rname) + rname++; + if (sl_buddy) + jep22 = buddy_resource_jep22(sl_buddy->data, rname); + + if (!jep22) + return; // XXX Maybe we could try harder (other resources?) + + msgid = jep22->last_msgid_rcvd; + + // For composing events (composing, active, inactive, paused...), + // JEP22 only has 2 states; we'll use composing and active. + if (type == ROSTER_EVENT_COMPOSING) + jep22_state = ROSTER_EVENT_COMPOSING; + else if (type == ROSTER_EVENT_ACTIVE || + type == ROSTER_EVENT_PAUSED) + jep22_state = ROSTER_EVENT_ACTIVE; + else + jep22_state = 0; // ROSTER_EVENT_NONE + + if (jep22_state) { + // Do not re-send a same event + if (jep22_state == jep22->last_state_sent) + return; + jep22->last_state_sent = jep22_state; + } + + x = lm_message_new_with_sub_type(fjid, LM_MESSAGE_TYPE_MESSAGE, + LM_MESSAGE_SUB_TYPE_CHAT); + + event = lm_message_node_add_child(x->node, "x", NULL); + lm_message_node_set_attribute(event, "xmlns", NS_EVENT); + if (type == ROSTER_EVENT_DELIVERED) + lm_message_node_add_child(event, "delivered", NULL); + else if (type == ROSTER_EVENT_COMPOSING) + lm_message_node_add_child(event, "composing", NULL); + lm_message_node_add_child(event, "id", msgid); + + lm_connection_send(lconnection, x, NULL); + lm_message_unref(x); +} +#endif + +// xmpp_send_chatstate(buddy, state) +// Send a chatstate or event (JEP-22/85) according to the buddy's capabilities. +// The message is sent to one of the resources with the highest priority. +#if defined JEP0022 || defined JEP0085 +void xmpp_send_chatstate(gpointer buddy, guint chatstate) +{ + const char *bjid; +#ifdef JEP0085 + GSList *resources, *p_res, *p_next; + struct jep0085 *jep85 = NULL; +#endif +#ifdef JEP0022 + struct jep0022 *jep22; +#endif + + bjid = buddy_getjid(buddy); + if (!bjid) return; + +#ifdef JEP0085 + /* Send the chatstate to the last resource (which should have the highest + priority). + If chatstate is "active", send an "active" state to all resources + which do not curently have this state. + */ + resources = buddy_getresources(buddy); + for (p_res = resources ; p_res ; p_res = p_next) { + p_next = g_slist_next(p_res); + jep85 = buddy_resource_jep85(buddy, p_res->data); + if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) { + // If p_next is NULL, this is the highest (prio) resource, i.e. + // the one we are probably writing to. + if (!p_next || (jep85->last_state_sent != ROSTER_EVENT_ACTIVE && + chatstate == ROSTER_EVENT_ACTIVE)) + xmpp_send_jep85_chatstate(bjid, p_res->data, chatstate); + } + g_free(p_res->data); + } + g_slist_free(resources); + // If the last resource had chatstates support when can return now, + // we don't want to send a JEP22 event. + if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) + return; +#endif +#ifdef JEP0022 + jep22 = buddy_resource_jep22(buddy, NULL); + if (jep22 && jep22->support == CHATSTATES_SUPPORT_OK) { + xmpp_send_jep22_event(bjid, chatstate); + } +#endif +} +#endif + + +// chatstates_reset_probed(fulljid) +// If the JEP has been probed for this contact, set it back to unknown so +// that we probe it again. The parameter must be a full jid (w/ resource). +#if defined JEP0022 || defined JEP0085 +static void chatstates_reset_probed(const char *fulljid) +{ + char *rname, *barejid; + GSList *sl_buddy; + struct jep0085 *jep85; + struct jep0022 *jep22; + + rname = strchr(fulljid, JID_RESOURCE_SEPARATOR); + if (!rname++) + return; + + barejid = jidtodisp(fulljid); + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + g_free(barejid); + + if (!sl_buddy) + return; + + jep85 = buddy_resource_jep85(sl_buddy->data, rname); + jep22 = buddy_resource_jep22(sl_buddy->data, rname); + + if (jep85 && jep85->support == CHATSTATES_SUPPORT_PROBED) + jep85->support = CHATSTATES_SUPPORT_UNKNOWN; + if (jep22 && jep22->support == CHATSTATES_SUPPORT_PROBED) + jep22->support = CHATSTATES_SUPPORT_UNKNOWN; +} +#endif + +#ifdef HAVE_GPGME +// keys_mismatch(key, expectedkey) +// Return TRUE if both keys are non-null and "expectedkey" doesn't match +// the end of "key". +// If one of the keys is null, return FALSE. +// If expectedkey is less than 8 bytes long, return TRUE. +// +// Example: keys_mismatch("C9940A9BB0B92210", "B0B92210") will return FALSE. +static bool keys_mismatch(const char *key, const char *expectedkey) +{ + int lk, lek; + + if (!expectedkey || !key) + return FALSE; + + lk = strlen(key); + lek = strlen(expectedkey); + + // If the expectedkey is less than 8 bytes long, this is probably a + // user mistake so we consider it's a mismatch. + if (lek < 8) + return TRUE; + + if (lek < lk) + key += lk - lek; + + return strcasecmp(key, expectedkey); +} +#endif + +// check_signature(barejid, resourcename, xmldata, text) +// Verify the signature (in xmldata) of "text" for the contact +// barejid/resourcename. +// xmldata is the 'jabber:x:signed' stanza. +// If the key id is found, the contact's PGP data are updated. +static void check_signature(const char *barejid, const char *rname, + LmMessageNode *node, const char *text) +{ +#ifdef HAVE_GPGME + const char *p, *key; + GSList *sl_buddy; + struct pgp_data *res_pgpdata; + gpgme_sigsum_t sigsum; + + // All parameters must be valid + if (!(node && barejid && rname && text)) + return; + + if (!gpg_enabled()) + return; + + // Get the resource PGP data structure + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + if (!sl_buddy) + return; + res_pgpdata = buddy_resource_pgp(sl_buddy->data, rname); + if (!res_pgpdata) + return; + + if (!node->name || strcmp(node->name, "x")) //XXX: probably useless + return; // We expect "" + + // Get signature + p = lm_message_node_get_value(node); + if (!p) + return; + + key = gpg_verify(p, text, &sigsum); + if (key) { + const char *expectedkey; + char *buf; + g_free(res_pgpdata->sign_keyid); + res_pgpdata->sign_keyid = (char *)key; + res_pgpdata->last_sigsum = sigsum; + if (sigsum & GPGME_SIGSUM_RED) { + buf = g_strdup_printf("Bad signature from <%s/%s>", barejid, rname); + scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } + // Verify that the key id is the one we expect. + expectedkey = settings_pgp_getkeyid(barejid); + if (keys_mismatch(key, expectedkey)) { + buf = g_strdup_printf("Warning: The KeyId from <%s/%s> doesn't match " + "the key you set up", barejid, rname); + scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } + } +#endif +} + +static LmSSLResponse ssl_cb(LmSSL *ssl, LmSSLStatus status, gpointer ud) +{ + scr_LogPrint(LPRINT_LOGNORM, "SSL status:%d", status); + + switch (status) { + case LM_SSL_STATUS_NO_CERT_FOUND: + scr_LogPrint(LPRINT_LOGNORM, "No certificate found!"); + break; + case LM_SSL_STATUS_UNTRUSTED_CERT: + scr_LogPrint(LPRINT_LOGNORM, "Certificate is not trusted!"); + break; + case LM_SSL_STATUS_CERT_EXPIRED: + scr_LogPrint(LPRINT_LOGNORM, "Certificate has expired!"); + break; + case LM_SSL_STATUS_CERT_NOT_ACTIVATED: + scr_LogPrint(LPRINT_LOGNORM, "Certificate has not been activated!"); + break; + case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH: + scr_LogPrint(LPRINT_LOGNORM, + "Certificate hostname does not match expected hostname!"); + break; + case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: { + char fpr[49]; + fingerprint_to_hex((const unsigned char*)lm_ssl_get_fingerprint(ssl), + fpr); + scr_LogPrint(LPRINT_LOGNORM, + "Certificate fingerprint does not match expected fingerprint!"); + scr_LogPrint(LPRINT_LOGNORM, "Remote fingerprint: %s", fpr); + + scr_LogPrint(LPRINT_LOGNORM, "Expected fingerprint: %s", + settings_opt_get("ssl_fingerprint")); + + return LM_SSL_RESPONSE_STOP; + break; + } + case LM_SSL_STATUS_GENERIC_ERROR: + scr_LogPrint(LPRINT_LOGNORM, "Generic SSL error!"); + break; + } + + if (!settings_opt_get_int("ssl_ignore_checks")) + return LM_SSL_RESPONSE_CONTINUE; + return LM_SSL_RESPONSE_STOP; +} + +static void connection_auth_cb(LmConnection *connection, gboolean success, + gpointer user_data) +{ + if (success) { + LmMessage *m; + + m = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_PRESENCE, + LM_MESSAGE_SUB_TYPE_AVAILABLE); + lm_connection_send(connection, m, NULL); + + lm_message_unref(m); + xmpp_setprevstatus(); + xmpp_iq_request(NULL, NS_ROSTER); + xmpp_request_storage("storage:bookmarks"); + xmpp_request_storage("storage:rosternotes"); + + AutoConnection = TRUE; + } else + scr_LogPrint(LPRINT_LOGNORM, "Authentication failed"); +} + +gboolean xmpp_reconnect() +{ + if (!lm_connection_is_authenticated(lconnection)) + xmpp_connect(); + return FALSE; +} + +static void _try_to_reconnect(void) +{ + if (AutoConnection) + g_timeout_add_seconds(RECONNECTION_TIMEOUT, xmpp_reconnect, NULL); +} + +static void connection_open_cb(LmConnection *connection, gboolean success, + gpointer user_data) +{ + const char *username, *password, *resource, *servername; + GError *error; + + if (success) { + servername = settings_opt_get("server"); + username = settings_opt_get("username"); + password = settings_opt_get("password"); + resource = strchr(lm_connection_get_jid(connection), + JID_RESOURCE_SEPARATOR); + if (resource) + resource++; + + if (!lm_connection_authenticate(lconnection, username, password, resource, + connection_auth_cb, NULL, FALSE, &error)) { + scr_LogPrint(LPRINT_LOGNORM, "Failed to authenticate: %s\n", + error->message); + _try_to_reconnect(); + } + } else { + scr_LogPrint(LPRINT_LOGNORM, "There was an error while connecting."); + _try_to_reconnect(); + } +} + +static void connection_close_cb(LmConnection *connection, + LmDisconnectReason reason, + gpointer user_data) +{ + const char *str; + + switch (reason) { + case LM_DISCONNECT_REASON_OK: + str = "LM_DISCONNECT_REASON_OK"; + break; + case LM_DISCONNECT_REASON_PING_TIME_OUT: + str = "LM_DISCONNECT_REASON_PING_TIME_OUT"; + break; + case LM_DISCONNECT_REASON_HUP: + str = "LM_DISCONNECT_REASON_HUP"; + break; + case LM_DISCONNECT_REASON_ERROR: + str = "LM_DISCONNECT_REASON_ERROR"; + break; + case LM_DISCONNECT_REASON_UNKNOWN: + default: + str = "LM_DISCONNECT_REASON_UNKNOWN"; + break; + } + + if (reason != LM_DISCONNECT_REASON_OK) + _try_to_reconnect(); + + // Free bookmarks + if (bookmarks) + lm_message_node_unref(bookmarks); + bookmarks = NULL; + // Free roster + roster_free(); + if (rosternotes) + lm_message_node_unref(rosternotes); + rosternotes = NULL; + // Update display + update_roster = TRUE; + scr_UpdateBuddyWindow(); + + scr_LogPrint(LPRINT_NORMAL, "Disconnected, reason:%d->'%s'\n", reason, str); +} + +static void handle_state_events(const char *from, LmMessageNode *node) +{ +#if defined JEP0022 || defined JEP0085 + LmMessageNode *state_ns = NULL; + const char *body; + char *rname, *bjid; + GSList *sl_buddy; + guint events; + struct jep0022 *jep22 = NULL; + struct jep0085 *jep85 = NULL; + enum { + JEP_none, + JEP_85, + JEP_22 + } which_jep = JEP_none; + + rname = strchr(from, JID_RESOURCE_SEPARATOR); + if (rname) + ++rname; + else + rname = (char *)from + strlen(from); + bjid = jidtodisp(from); + sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); + g_free(bjid); + + /* XXX Actually that's wrong, since it filters out server "offline" + messages (for JEP-0022). This JEP is (almost) deprecated so + we don't really care. */ + if (!sl_buddy) { + return; + } + + /* Let's see chich JEP the contact uses. If possible, we'll use + JEP-85, if not we'll look for JEP-22 support. */ + events = buddy_resource_getevents(sl_buddy->data, rname); + + jep85 = buddy_resource_jep85(sl_buddy->data, rname); + if (jep85) { + state_ns = lm_message_node_find_xmlns(node, NS_CHATSTATES); + if (state_ns) + which_jep = JEP_85; + } + + if (which_jep != JEP_85) { /* Fall back to JEP-0022 */ + jep22 = buddy_resource_jep22(sl_buddy->data, rname); + if (jep22) { + state_ns = lm_message_node_find_xmlns(node, NS_EVENT); + if (state_ns) + which_jep = JEP_22; + } + } + + if (!which_jep) { /* Sender does not use chat states */ + return; + } + + body = lm_message_node_get_child_value(node, "body"); + + if (which_jep == JEP_85) { /* JEP-0085 */ + jep85->support = CHATSTATES_SUPPORT_OK; + + if (!strcmp(state_ns->name, "composing")) { + jep85->last_state_rcvd = ROSTER_EVENT_COMPOSING; + } else if (!strcmp(state_ns->name, "active")) { + jep85->last_state_rcvd = ROSTER_EVENT_ACTIVE; + } else if (!strcmp(state_ns->name, "paused")) { + jep85->last_state_rcvd = ROSTER_EVENT_PAUSED; + } else if (!strcmp(state_ns->name, "inactive")) { + jep85->last_state_rcvd = ROSTER_EVENT_INACTIVE; + } else if (!strcmp(state_ns->name, "gone")) { + jep85->last_state_rcvd = ROSTER_EVENT_GONE; + } + events = jep85->last_state_rcvd; + } else { /* JEP-0022 */ +#ifdef JEP0022 + const char *msgid; + jep22->support = CHATSTATES_SUPPORT_OK; + jep22->last_state_rcvd = ROSTER_EVENT_NONE; + + msgid = lm_message_node_get_attribute(node, "id"); + + if (lm_message_node_get_child(state_ns, "composing")) { + // Clear composing if the message contains a body + if (body) + events &= ~ROSTER_EVENT_COMPOSING; + else + events |= ROSTER_EVENT_COMPOSING; + jep22->last_state_rcvd |= ROSTER_EVENT_COMPOSING; + + } else { + events &= ~ROSTER_EVENT_COMPOSING; + } + + // Cache the message id + g_free(jep22->last_msgid_rcvd); + if (msgid) + jep22->last_msgid_rcvd = g_strdup(msgid); + else + jep22->last_msgid_rcvd = NULL; + + if (lm_message_node_get_child(state_ns, "delivered")) { + jep22->last_state_rcvd |= ROSTER_EVENT_DELIVERED; + + // Do we have to send back an ACK? + if (body) + xmpp_send_jep22_event(from, ROSTER_EVENT_DELIVERED); + } +#endif + } + + buddy_resource_setevents(sl_buddy->data, rname, events); + + update_roster = TRUE; +#endif +} + +static void gotmessage(LmMessageSubType type, const char *from, + const char *body, const char *enc, const char *subject, + time_t timestamp, LmMessageNode *node_signed) +{ + char *bjid; + const char *rname, *s; + char *decrypted_pgp = NULL; + char *decrypted_otr = NULL; + int otr_msg = 0, free_msg = 0; + + bjid = jidtodisp(from); + + rname = strchr(from, JID_RESOURCE_SEPARATOR); + if (rname) rname++; + +#ifdef HAVE_GPGME + if (enc && gpg_enabled()) { + decrypted_pgp = gpg_decrypt(enc); + if (decrypted_pgp) { + body = decrypted_pgp; + } + } + // Check signature of an unencrypted message + if (node_signed && gpg_enabled()) + check_signature(bjid, rname, node_signed, decrypted_pgp); +#endif + +#ifdef HAVE_LIBOTR + if (otr_enabled()) { + decrypted_otr = (char*)body; + otr_msg = otr_receive(&decrypted_otr, bjid, &free_msg); + if (!decrypted_otr) { + goto gotmessage_return; + } + body = decrypted_otr; + } +#endif + + // Check for unexpected groupchat messages + // If we receive a groupchat message from a room we're not a member of, + // this is probably a server issue and the best we can do is to send + // a type unavailable. + if (type == LM_MESSAGE_SUB_TYPE_GROUPCHAT && !roster_getnickname(bjid)) { + // It shouldn't happen, probably a server issue + GSList *room_elt; + char *mbuf; + + mbuf = g_strdup_printf("Unexpected groupchat packet!"); + scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); + scr_WriteIncomingMessage(bjid, mbuf, 0, HBB_PREFIX_INFO, 0); + g_free(mbuf); + + // Send back an unavailable packet + xmpp_setstatus(offline, bjid, "", TRUE); + + // MUC + // Make sure this is a room (it can be a conversion user->room) + room_elt = roster_find(bjid, jidsearch, 0); + if (!room_elt) { + room_elt = roster_add_user(bjid, NULL, NULL, ROSTER_TYPE_ROOM, + sub_none, -1); + } else { + buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); + } + + buddylist_build(); + scr_DrawRoster(); + goto gotmessage_return; + } + + // We don't call the message_in hook if 'block_unsubscribed' is true and + // this is a regular message from an unsubscribed user. + // System messages (from our server) are allowed. + if ((!settings_opt_get_int("block_unsubscribed") || + (roster_getsubscription(bjid) & sub_from) || + (type == LM_MESSAGE_SUB_TYPE_CHAT)) || + ((s = settings_opt_get("server")) != NULL && !strcasecmp(bjid, s))) { + gchar *fullbody = NULL; + guint encrypted; + + if (decrypted_pgp) + encrypted = ENCRYPTED_PGP; + else if (otr_msg) + encrypted = ENCRYPTED_OTR; + else + encrypted = 0; + + if (subject) { + if (body) + fullbody = g_strdup_printf("[%s]\n%s", subject, body); + else + fullbody = g_strdup_printf("[%s]\n", subject); + body = fullbody; + } + hk_message_in(bjid, rname, timestamp, body, type, encrypted); + g_free(fullbody); + } else { + scr_LogPrint(LPRINT_LOGNORM, "Blocked a message from <%s>", bjid); + } + +gotmessage_return: + // Clean up and exit + g_free(bjid); + g_free(decrypted_pgp); + if (free_msg) + g_free(decrypted_otr); +} + + +static LmHandlerResult handle_messages(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *m, gpointer user_data) +{ + const char *p, *from=lm_message_get_from(m); + char *r, *s; + LmMessageNode *x; + const char *body = NULL; + const char *enc = NULL; + const char *subject = NULL; + time_t timestamp = 0L; + + body = lm_message_node_get_child_value(m->node, "body"); + + x = lm_message_node_find_xmlns(m->node, NS_ENCRYPTED); + if (x && (p = lm_message_node_get_value(x)) != NULL) + enc = p; + + p = lm_message_node_get_child_value(m->node, "subject"); + if (p != NULL) { + if (lm_message_get_sub_type(m) != LM_MESSAGE_SUB_TYPE_GROUPCHAT) { + // Chat message + subject = p; + } else { // Room topic + GSList *roombuddy; + gchar *mbuf; + const gchar *subj = p; + // Get the room (s) and the nickname (r) + s = g_strdup(lm_message_get_from(m)); + r = strchr(s, JID_RESOURCE_SEPARATOR); + if (r) *r++ = 0; + else r = s; + // Set the new topic + roombuddy = roster_find(s, jidsearch, 0); + if (roombuddy) + buddy_settopic(roombuddy->data, subj); + // Display inside the room window + if (r == s) { + // No specific resource (this is certainly history) + mbuf = g_strdup_printf("The topic has been set to: %s", subj); + } else { + mbuf = g_strdup_printf("%s has set the topic to: %s", r, subj); + } + scr_WriteIncomingMessage(s, mbuf, 0, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + if (settings_opt_get_int("log_muc_conf")) + hlog_write_message(s, 0, -1, mbuf); + g_free(s); + g_free(mbuf); + // The topic is displayed in the chat status line, so refresh now. + scr_UpdateChatStatus(TRUE); + } + } + + // Timestamp? + timestamp = lm_message_node_get_timestamp(m->node); + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) { + x = lm_message_node_get_child(m->node, "error"); + display_server_error(x); +#if defined JEP0022 || defined JEP0085 + // If the JEP85/22 support is probed, set it back to unknown so that + // we probe it again. + chatstates_reset_probed(from); +#endif + } else { + handle_state_events(from, m->node); + } + if (from && (body || subject)) + gotmessage(lm_message_get_sub_type(m), from, body, enc, subject, timestamp, + lm_message_node_find_xmlns(m->node, NS_SIGNED)); + + if (from) { + x = lm_message_node_find_xmlns(m->node, + "http://jabber.org/protocol/muc#user"); + if (x && !strcmp(x->name, "x")) + got_muc_message(from, x); + } + + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_presence(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *m, gpointer user_data) +{ + char *r; + const char *from, *rname, *p=NULL, *ustmsg=NULL; + enum imstatus ust; + char bpprio; + time_t timestamp = 0L; + LmMessageNode *muc_packet; + + //Check for MUC presence packet + muc_packet = lm_message_node_find_xmlns + (m->node, "http://jabber.org/protocol/muc#user"); + + from = lm_message_get_from(m); + + rname = strchr(from, JID_RESOURCE_SEPARATOR); + if (rname) rname++; + + if (settings_opt_get_int("ignore_self_presence")) { + const char *self_fjid = lm_connection_get_jid(connection); + if (self_fjid && !strcasecmp(self_fjid, from)) { + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; // Ignoring self presence + } + } + + r = jidtodisp(from); + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) { + LmMessageNode *x; + scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r); + x = lm_message_node_find_child(m->node, "error"); + display_server_error(x); + // Let's check it isn't a nickname conflict. + // XXX Note: We should handle the string condition. + if ((p = lm_message_node_get_attribute(x, "code")) != NULL) { + if (atoi(p) == 409) { + // 409 = conflict (nickname is in use or registered by another user) + // If we are not inside this room, we should reset the nickname + GSList *room_elt = roster_find(r, jidsearch, 0); + if (room_elt && !buddy_getinsideroom(room_elt->data)) + buddy_setnickname(room_elt->data, NULL); + } + } + + g_free(r); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + + p = lm_message_node_get_child_value(m->node, "priority"); + if (p && *p) bpprio = (gchar)atoi(p); + else bpprio = 0; + + ust = available; + + p = lm_message_node_get_child_value(m->node, "show"); + if (p) { + if (!strcmp(p, "away")) ust = away; + else if (!strcmp(p, "dnd")) ust = dontdisturb; + else if (!strcmp(p, "xa")) ust = notavail; + else if (!strcmp(p, "chat")) ust = freeforchat; + } + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_UNAVAILABLE) + ust = offline; + + ustmsg = lm_message_node_get_child_value(m->node, "status"); + + // Timestamp? + timestamp = lm_message_node_get_timestamp(m->node); + + if (muc_packet) { + // This is a MUC presence message + handle_muc_presence(from, muc_packet, r, rname, + ust, ustmsg, timestamp, bpprio); + } else { + // Not a MUC message, so this is a regular buddy... + // Call hk_statuschange() if status has changed or if the + // status message is different + const char *msg; + msg = roster_getstatusmsg(r, rname); + if ((ust != roster_getstatus(r, rname)) || + (!ustmsg && msg && msg[0]) || (ustmsg && (!msg || strcmp(ustmsg, msg)))) + hk_statuschange(r, rname, bpprio, timestamp, ust, ustmsg); + // Presence signature processing + if (!ustmsg) + ustmsg = ""; // Some clients omit the element :-( + check_signature(r, rname, lm_message_node_find_xmlns(m->node, NS_SIGNED), + ustmsg); + } + + g_free(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + + +static LmHandlerResult handle_iq(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *m, gpointer user_data) +{ + int i; + const char *xmlns = NULL; + LmMessageNode *x; + + for (x = m->node->children; x; x=x->next) { + xmlns = lm_message_node_get_attribute(x, "xmlns"); + if (xmlns) + for (i=0; iq_handlers[i].xmlns; ++i) + if (!strcmp(iq_handlers[i].xmlns, xmlns)) + return iq_handlers[i].handler(NULL, connection, m, user_data); + xmlns = NULL; + } + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) { + display_server_error(lm_message_node_get_child(m->node, "error")); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + + if ((lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_SET) || + (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_GET)) + send_iq_error(connection, m, XMPP_ERROR_NOT_IMPLEMENTED); + + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, "Unhandled IQ: %s", + lm_message_node_to_string(m->node)); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_s10n(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *m, gpointer user_data) +{ + char *r; + char *buf; + int newbuddy; + const char *from = lm_message_get_from(m); + + r = jidtodisp(from); + + newbuddy = !roster_find(r, jidsearch, 0); + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_SUBSCRIBE) { + /* The sender wishes to subscribe to our presence */ + const char *msg; + int isagent; + eviqs *evn; + + isagent = (roster_gettype(r) & ROSTER_TYPE_AGENT) != 0; + msg = lm_message_node_get_child_value(m->node, "status"); + + buf = g_strdup_printf("<%s> wants to subscribe to your presence updates", + from); + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + + if (msg) { + buf = g_strdup_printf("<%s> said: %s", from, msg); + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + replace_nl_with_dots(buf); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } + + // Create a new event item + evn = evs_new(EVS_TYPE_SUBSCRIPTION, EVS_MAX_TIMEOUT); + if (evn) { + evn->callback = &evscallback_subscription; + evn->data = g_strdup(r); + evn->desc = g_strdup_printf("<%s> wants to subscribe to your " + "presence updates", r); + buf = g_strdup_printf("Please use /event %s accept|reject", evn->id); + } else { + buf = g_strdup_printf("Unable to create a new event!"); + } + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } else if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE) { + /* The sender is unsubscribing from our presence */ + xmpp_send_s10n(from, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED); + buf = g_strdup_printf("<%s> is unsubscribing from your " + "presence updates", from); + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } else if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_SUBSCRIBED) { + /* The sender has allowed us to receive their presence */ + buf = g_strdup_printf("<%s> has allowed you to receive their " + "presence updates", from); + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } else if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED) { + /* The subscription request has been denied or a previously-granted + subscription has been cancelled */ + roster_unsubscribed(from); + update_roster = TRUE; + buf = g_strdup_printf("<%s> has cancelled your subscription to " + "their presence updates", from); + scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + } else { + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + + if (newbuddy) + update_roster = TRUE; + g_free(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +//TODO: Use the enum of loudmouth, when it's included in the header... +typedef enum { + LM_LOG_LEVEL_VERBOSE = 1 << (G_LOG_LEVEL_USER_SHIFT), + LM_LOG_LEVEL_NET = 1 << (G_LOG_LEVEL_USER_SHIFT + 1), + LM_LOG_LEVEL_PARSER = 1 << (G_LOG_LEVEL_USER_SHIFT + 2), + LM_LOG_LEVEL_SSL = 1 << (G_LOG_LEVEL_USER_SHIFT + 3), + LM_LOG_LEVEL_SASL = 1 << (G_LOG_LEVEL_USER_SHIFT + 4), + LM_LOG_LEVEL_ALL = (LM_LOG_LEVEL_NET | + LM_LOG_LEVEL_VERBOSE | + LM_LOG_LEVEL_PARSER | + LM_LOG_LEVEL_SSL | + LM_LOG_LEVEL_SASL) +} LmLogLevelFlags; + +static void lm_debug_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + if (settings_opt_get_int("tracelog_level") != 2) + return; + if (message) { + char *msg; + if (message[0] == '\n') + msg = g_strdup(&message[1]); + else + msg = g_strdup(message); + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = '\0'; + + if (log_level & LM_LOG_LEVEL_VERBOSE) { + scr_LogPrint(LPRINT_DEBUG, "LM-VERBOSE: %s", msg); + } + if ((LmLogLevelFlags)log_level & LM_LOG_LEVEL_NET) { + scr_LogPrint(LPRINT_DEBUG, "LM-NET: %s", msg); + } + else if (log_level & LM_LOG_LEVEL_PARSER) { + scr_LogPrint(LPRINT_DEBUG, "LM-PARSER: %s", msg); + } + else if (log_level & LM_LOG_LEVEL_SASL) { + scr_LogPrint(LPRINT_DEBUG, "LM-SASL: %s", msg); + } + else if (log_level & LM_LOG_LEVEL_SSL) { + scr_LogPrint(LPRINT_DEBUG, "LM-SSL: %s", msg); + } + g_free(msg); + } +} + + +void xmpp_connect(void) +{ + const char *username, *password, *resource, *servername, *ssl_fpr; + char *dynresource = NULL; + char fpr[16]; + const char *proxy_host; + const char *resource_prefix = PACKAGE_NAME; + char *fjid; + int ssl, tls; + LmSSL *lssl; + unsigned int port; + unsigned int ping; + LmMessageHandler *handler; + GError *error = NULL; + + if (lconnection && lm_connection_is_open(lconnection)) + xmpp_disconnect(); + + servername = settings_opt_get("server"); + username = settings_opt_get("username"); + password = settings_opt_get("password"); + resource = settings_opt_get("resource"); + proxy_host = settings_opt_get("proxy_host"); + ssl_fpr = settings_opt_get("ssl_fingerprint"); + + if (!servername) { + scr_LogPrint(LPRINT_LOGNORM, "Server name has not been specified!"); + return; + } + + if (!username) { + scr_LogPrint(LPRINT_LOGNORM, "User name has not been specified!"); + return; + } + if (!password) { + scr_LogPrint(LPRINT_LOGNORM, "Password has not been specified!"); + return; + } + + lconnection = lm_connection_new_with_context + (NULL, g_main_loop_get_context(main_loop)); + + g_log_set_handler("LM", LM_LOG_LEVEL_ALL, lm_debug_handler, NULL); + + ping = 40; + if (settings_opt_get("pinginterval")) + ping = (unsigned int) settings_opt_get_int("pinginterval"); + lm_connection_set_keep_alive_rate(lconnection, ping); + scr_LogPrint(LPRINT_DEBUG, "Ping interval established: %d secs", ping); + + lm_connection_set_disconnect_function(lconnection, connection_close_cb, + NULL, NULL); + + handler = lm_message_handler_new(handle_messages, NULL, NULL); + lm_connection_register_message_handler(lconnection, handler, + LM_MESSAGE_TYPE_MESSAGE, + LM_HANDLER_PRIORITY_NORMAL); + lm_message_handler_unref(handler); + + handler = lm_message_handler_new(handle_iq, NULL, NULL); + lm_connection_register_message_handler(lconnection, handler, + LM_MESSAGE_TYPE_IQ, + LM_HANDLER_PRIORITY_NORMAL); + lm_message_handler_unref(handler); + + handler = lm_message_handler_new(handle_presence, NULL, NULL); + lm_connection_register_message_handler(lconnection, handler, + LM_MESSAGE_TYPE_PRESENCE, + LM_HANDLER_PRIORITY_LAST); + lm_message_handler_unref(handler); + + handler = lm_message_handler_new(handle_s10n, NULL, NULL); + lm_connection_register_message_handler(lconnection, handler, + LM_MESSAGE_TYPE_PRESENCE, + LM_HANDLER_PRIORITY_NORMAL); + lm_message_handler_unref(handler); + + /* Connect to server */ + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, "Connecting to server: %s", + servername); + if (!resource) + resource = resource_prefix; + + if (!settings_opt_get("disable_random_resource")) { +#if HAVE_ARC4RANDOM + dynresource = g_strdup_printf("%s.%08x", resource, arc4random()); +#else + unsigned int tab[2]; + srand(time(NULL)); + tab[0] = (unsigned int) (0xffff * (rand() / (RAND_MAX + 1.0))); + tab[1] = (unsigned int) (0xffff * (rand() / (RAND_MAX + 1.0))); + dynresource = g_strdup_printf("%s.%04x%04x", resource, tab[0], tab[1]); +#endif + resource = dynresource; + } + + port = (unsigned int) settings_opt_get_int("port"); + + if (port) + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " using port %d", port); + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " resource %s", resource); + + if (proxy_host) { + int proxy_port = settings_opt_get_int("proxy_port"); + if (proxy_port <= 0 || proxy_port > 65535) { + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, "Invalid proxy port: %d", + proxy_port); + } else { + const char *proxy_user, *proxy_pass; + LmProxy *lproxy; + proxy_user = settings_opt_get("proxy_user"); + proxy_pass = settings_opt_get("proxy_pass"); + // Proxy initialization + lproxy = lm_proxy_new_with_server(LM_PROXY_TYPE_HTTP, + proxy_host, proxy_port); + lm_proxy_set_username(lproxy, proxy_user); + lm_proxy_set_password(lproxy, proxy_pass); + lm_connection_set_proxy(lconnection, lproxy); + lm_proxy_unref(lproxy); + scr_LogPrint(LPRINT_NORMAL|LPRINT_DEBUG, " using proxy %s:%d", + proxy_host, proxy_port); + } + } + + fjid = compose_jid(username, servername, resource); + lm_connection_set_jid(lconnection, fjid); +#if defined(HAVE_LIBOTR) + otr_init(fjid); +#endif + g_free(fjid); + g_free(dynresource); + + ssl = settings_opt_get_int("ssl"); + tls = settings_opt_get_int("tls"); + + if (!lm_ssl_is_supported()) { + if (ssl || tls) { + scr_LogPrint(LPRINT_LOGNORM, "** Error: SSL is NOT available, " + "please recompile loudmouth with SSL enabled."); + return; + } + } + + if (ssl && tls) { + scr_LogPrint(LPRINT_LOGNORM, "You can only set ssl or tls, not both."); + return; + } + + if (!port) + port = (ssl ? LM_CONNECTION_DEFAULT_PORT_SSL : LM_CONNECTION_DEFAULT_PORT); + lm_connection_set_port(lconnection, port); + scr_LogPrint(LPRINT_LOGNORM, "Port: %i\n", port); + + if (ssl_fpr && (!hex_to_fingerprint(ssl_fpr, fpr))) { + scr_LogPrint(LPRINT_LOGNORM, "** Plese set the fingerprint in the format " + "97:5C:00:3F:1D:77:45:25:E2:C5:70:EC:83:C8:87:EE"); + return; + } + + lssl = lm_ssl_new((ssl_fpr ? fpr : NULL), ssl_cb, NULL, NULL); + if (lssl) { + lm_ssl_use_starttls(lssl, !ssl, tls); + lm_connection_set_ssl(lconnection, lssl); + lm_ssl_unref(lssl); + } else if (ssl || tls) { + scr_LogPrint(LPRINT_LOGNORM, "** Error: Couldn't create SSL struct."); + return; + } + + if (!lm_connection_open(lconnection, connection_open_cb, + NULL, FALSE, &error)) { + _try_to_reconnect(); + scr_LogPrint(LPRINT_LOGNORM, "Failed to open: %s\n", error->message); + } +} + +// insert_entity_capabilities(presence_stanza) +// Entity Capabilities (XEP-0115) +static void insert_entity_capabilities(LmMessageNode * x) +{ + LmMessageNode *y; + const char *ver = entity_version(); + char *exts, *exts2; + + exts = NULL; + + y = lm_message_node_add_child(x, "c", NULL); + lm_message_node_set_attribute(y, "xmlns", NS_CAPS); + lm_message_node_set_attribute(y, "node", MCABBER_CAPS_NODE); + lm_message_node_set_attribute(y, "ver", ver); +#ifdef JEP0085 + if (!chatstates_disabled) { + exts2 = g_strjoin(" ", "csn", exts, NULL); + g_free(exts); + exts = exts2; + } +#endif + if (!settings_opt_get_int("iq_last_disable")) { + exts2 = g_strjoin(" ", "iql", exts, NULL); + g_free(exts); + exts = exts2; + } + if (exts) { + lm_message_node_set_attribute(y, "ext", exts); + g_free(exts); + } +} + +void xmpp_disconnect(void) +{ + if (!lconnection || !lm_connection_is_authenticated(lconnection)) + return; + + // Launch pre-disconnect internal hook + hook_execute_internal("hook-pre-disconnect"); + // Announce it to everyone else + xmpp_setstatus(offline, NULL, "", FALSE); + lm_connection_close(lconnection, NULL); +} + +void xmpp_setstatus(enum imstatus st, const char *recipient, const char *msg, + int do_not_sign) +{ + LmMessage *m; + + if (msg) { + // The status message has been specified. We'll use it, unless it is + // "-" which is a special case (option meaning "no status message"). + if (!strcmp(msg, "-")) + msg = ""; + } else { + // No status message specified; we'll use: + // a) the default status message (if provided by the user); + // b) the current status message; + // c) no status message (i.e. an empty one). + msg = settings_get_status_msg(st); + if (!msg) { + if (mystatusmsg) + msg = mystatusmsg; + else + msg = ""; + } + } + + // Only send the packet if we're online. + // (But we want to update internal status even when disconnected, + // in order to avoid some problems during network failures) + if (lm_connection_is_authenticated(lconnection)) { + const char *s_msg = (st != invisible ? msg : NULL); + m = lm_message_new_presence(st, recipient, s_msg); + insert_entity_capabilities(m->node); // Entity Capabilities (XEP-0115) +#ifdef HAVE_GPGME + if (!do_not_sign && gpg_enabled()) { + char *signature; + signature = gpg_sign(s_msg ? s_msg : ""); + if (signature) { + LmMessageNode *y; + y = lm_message_node_add_child(m->node, "x", signature); + lm_message_node_set_attribute(y, "xmlns", NS_SIGNED); + g_free(signature); + } + } +#endif + lm_connection_send(lconnection, m, NULL); + lm_message_unref(m); + } + + // If we didn't change our _global_ status, we are done + if (recipient) return; + + if (lm_connection_is_authenticated(lconnection)) { + // Send presence to chatrooms + if (st != invisible) { + struct T_presence room_presence; + room_presence.st = st; + room_presence.msg = msg; + foreach_buddy(ROSTER_TYPE_ROOM, &roompresence, &room_presence); + } + + // We'll have to update the roster if we switch to/from offline because + // we don't know the presences of buddies when offline... + if (mystatus == offline || st == offline) + update_roster = TRUE; + + hk_mystatuschange(0, mystatus, st, (st != invisible ? msg : "")); + mystatus = st; + } + + if (st) + mywantedstatus = st; + + if (msg != mystatusmsg) { + g_free(mystatusmsg); + if (*msg) + mystatusmsg = g_strdup(msg); + else + mystatusmsg = NULL; + } + + if (!Autoaway) + update_last_use(); + + // Update status line + scr_UpdateMainStatus(TRUE); +} + + +enum imstatus xmpp_getstatus(void) +{ + return mystatus; +} + +const char *xmpp_getstatusmsg(void) +{ + return mystatusmsg; +} + +// xmpp_setprevstatus() +// Set previous status. This wrapper function is used after a disconnection. +void xmpp_setprevstatus(void) +{ + xmpp_setstatus(mywantedstatus, NULL, mystatusmsg, FALSE); +} + +// send_storage(store) +// Send the node "store" to update the server. +// Note: the sender should check we're online. +void send_storage(LmMessageNode *store) +{ + LmMessage *iq; + LmMessageNode *query; + + if (!rosternotes) return; + + iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + query = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", NS_PRIVATE); + lm_message_node_insert_childnode(query, store); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); +} + + +// xmpp_is_bookmarked(roomjid) +// Return TRUE if there's a bookmark for the given jid. +guint xmpp_is_bookmarked(const char *bjid) +{ + LmMessageNode *x; + + if (!bookmarks) + return FALSE; + + // Walk through the storage bookmark tags + for (x = bookmarks->children ; x; x = x->next) { + // If the node is a conference item, check the jid. + if (x->name && !strcmp(x->name, "conference")) { + const char *fjid = lm_message_node_get_attribute(x, "jid"); + if (fjid && !strcasecmp(bjid, fjid)) + return TRUE; + } + } + return FALSE; +} + +// xmpp_get_bookmark_nick(roomjid) +// Return the room nickname if it is present in a bookmark. +const char *xmpp_get_bookmark_nick(const char *bjid) +{ + LmMessageNode *x; + + if (!bookmarks || !bjid) + return NULL; + + // Walk through the storage bookmark tags + for (x = bookmarks->children ; x; x = x->next) { + // If the node is a conference item, check the jid. + if (x->name && !strcmp(x->name, "conference")) { + const char *fjid = lm_message_node_get_attribute(x, "jid"); + if (fjid && !strcasecmp(bjid, fjid)) + return lm_message_node_get_child_value(x, "nick"); + } + } + return NULL; +} + + +// xmpp_get_all_storage_bookmarks() +// Return a GSList with all storage bookmarks. +// The caller should g_free the list (not the MUC jids). +GSList *xmpp_get_all_storage_bookmarks(void) +{ + LmMessageNode *x; + GSList *sl_bookmarks = NULL; + + // If we have no bookmarks, probably the server doesn't support them. + if (!bookmarks) + return NULL; + + // Walk through the storage bookmark tags + for (x = bookmarks->children ; x; x = x->next) { + // If the node is a conference item, let's add the note to our list. + if (x->name && !strcmp(x->name, "conference")) { + struct bookmark *bm_elt; + const char *autojoin, *name, *nick; + const char *fjid = lm_message_node_get_attribute(x, "jid"); + if (!fjid) + continue; + bm_elt = g_new0(struct bookmark, 1); + bm_elt->roomjid = g_strdup(fjid); + autojoin = lm_message_node_get_attribute(x, "autojoin"); + nick = lm_message_node_get_attribute(x, "nick"); + name = lm_message_node_get_attribute(x, "name"); + if (autojoin && !strcmp(autojoin, "1")) + bm_elt->autojoin = 1; + if (nick) + bm_elt->nick = g_strdup(nick); + if (name) + bm_elt->name = g_strdup(name); + sl_bookmarks = g_slist_append(sl_bookmarks, bm_elt); + } + } + return sl_bookmarks; +} + +// xmpp_set_storage_bookmark(roomid, name, nick, passwd, autojoin, +// printstatus, autowhois) +// Update the private storage bookmarks: add a conference room. +// If name is nil, we remove the bookmark. +void xmpp_set_storage_bookmark(const char *roomid, const char *name, + const char *nick, const char *passwd, + int autojoin, enum room_printstatus pstatus, + enum room_autowhois awhois) +{ + LmMessageNode *x; + bool changed = FALSE; + + if (!roomid) + return; + + // If we have no bookmarks, probably the server doesn't support them. + if (!bookmarks) { + scr_LogPrint(LPRINT_NORMAL, + "Sorry, your server doesn't seem to support private storage."); + return; + } + + // Walk through the storage tags + for (x = bookmarks->children ; x; x = x->next) { + // If the current node is a conference item, see if we have to replace it. + if (x->name && !strcmp(x->name, "conference")) { + const char *fjid = lm_message_node_get_attribute(x, "jid"); + if (!fjid) + continue; + if (!strcmp(fjid, roomid)) { + // We've found a bookmark for this room. Let's hide it and we'll + // create a new one. + lm_message_node_hide(x); + changed = TRUE; + if (!name) + scr_LogPrint(LPRINT_LOGNORM, "Deleting bookmark..."); + } + } + } + + // Let's create a node/bookmark for this roomid, if the name is not NULL. + if (name) { + x = lm_message_node_add_child(bookmarks, "conference", NULL); + lm_message_node_set_attributes(x, + "jid", roomid, + "name", name, + "autojoin", autojoin ? "1" : "0", + NULL); + if (nick) + lm_message_node_add_child(x, "nick", nick); + if (passwd) + lm_message_node_add_child(x, "password", passwd); + if (pstatus) + lm_message_node_add_child(x, "print_status", strprintstatus[pstatus]); + if (awhois) + lm_message_node_add_child(x, "autowhois", + (awhois == autowhois_on) ? "1" : "0"); + changed = TRUE; + scr_LogPrint(LPRINT_LOGNORM, "Updating bookmarks..."); + } + + if (!changed) + return; + + if (lm_connection_is_authenticated(lconnection)) + send_storage(bookmarks); + else + scr_LogPrint(LPRINT_LOGNORM, + "Warning: you're not connected to the server."); +} + +static struct annotation *parse_storage_rosternote(LmMessageNode *notenode) +{ + const char *p; + struct annotation *note = g_new0(struct annotation, 1); + p = lm_message_node_get_attribute(notenode, "cdate"); + if (p) + note->cdate = from_iso8601(p, 1); + p = lm_message_node_get_attribute(notenode, "mdate"); + if (p) + note->mdate = from_iso8601(p, 1); + note->text = g_strdup(lm_message_node_get_value(notenode)); + note->jid = g_strdup(lm_message_node_get_attribute(notenode, "jid")); + return note; +} + +// xmpp_get_all_storage_rosternotes() +// Return a GSList with all storage annotations. +// The caller should g_free the list and its contents. +GSList *xmpp_get_all_storage_rosternotes(void) +{ + LmMessageNode *x; + GSList *sl_notes = NULL; + + // If we have no rosternotes, probably the server doesn't support them. + if (!rosternotes) + return NULL; + + // Walk through the storage rosternotes tags + for (x = rosternotes->children ; x; x = x->next) { + struct annotation *note; + + // We want a note item + if (!x->name || strcmp(x->name, "note")) + continue; + // Just in case, check the jid... + if (!lm_message_node_get_attribute(x, "jid")) + continue; + // Ok, let's add the note to our list + note = parse_storage_rosternote(x); + sl_notes = g_slist_append(sl_notes, note); + } + return sl_notes; +} + +// xmpp_get_storage_rosternotes(barejid, silent) +// Return the annotation associated with this jid. +// If silent is TRUE, no warning is displayed when rosternotes is disabled +// The caller should g_free the string and structure after use. +struct annotation *xmpp_get_storage_rosternotes(const char *barejid, int silent) +{ + LmMessageNode *x; + + if (!barejid) + return NULL; + + // If we have no rosternotes, probably the server doesn't support them. + if (!rosternotes) { + if (!silent) + scr_LogPrint(LPRINT_NORMAL, "Sorry, " + "your server doesn't seem to support private storage."); + return NULL; + } + + // Walk through the storage rosternotes tags + for (x = rosternotes->children ; x; x = x->next) { + const char *fjid; + // We want a note item + if (!x->name || strcmp(x->name, "note")) + continue; + // Just in case, check the jid... + fjid = lm_message_node_get_attribute(x, "jid"); + if (fjid && !strcmp(fjid, barejid)) // We've found a note for this contact. + return parse_storage_rosternote(x); + } + return NULL; // No note found +} + +// xmpp_set_storage_rosternotes(barejid, note) +// Update the private storage rosternotes: add/delete a note. +// If note is nil, we remove the existing note. +void xmpp_set_storage_rosternotes(const char *barejid, const char *note) +{ + LmMessageNode *x; + bool changed = FALSE; + const char *cdate = NULL; + + if (!barejid) + return; + + // If we have no rosternotes, probably the server doesn't support them. + if (!rosternotes) { + scr_LogPrint(LPRINT_NORMAL, + "Sorry, your server doesn't seem to support private storage."); + return; + } + + // Walk through the storage tags + for (x = rosternotes->children ; x; x = x->next) { + // If the current node is a conference item, see if we have to replace it. + if (x->name && !strcmp(x->name, "note")) { + const char *fjid = lm_message_node_get_attribute(x, "jid"); + if (!fjid) + continue; + if (!strcmp(fjid, barejid)) { + // We've found a note for this jid. Let's hide it and we'll + // create a new one. + cdate = lm_message_node_get_attribute(x, "cdate"); + lm_message_node_hide(x); + changed = TRUE; + break; + } + } + } + + // Let's create a node for this jid, if the note is not NULL. + if (note) { + char mdate[20]; + time_t now; + time(&now); + to_iso8601(mdate, now); + if (!cdate) + cdate = mdate; + x = lm_message_node_add_child(rosternotes, "note", note); + lm_message_node_set_attributes(x, + "jid", barejid, + "cdate", cdate, + "mdate", mdate, + NULL); + changed = TRUE; + } + + if (!changed) + return; + + if (lm_connection_is_authenticated(lconnection)) + send_storage(rosternotes); + else + scr_LogPrint(LPRINT_LOGNORM, + "Warning: you're not connected to the server."); +} diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp.h Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,80 @@ +#ifndef __XMPP_H__ +#define __XMPP_H__ 1 + +#include +#include "roster.h" + +enum iqreq_type { + iqreq_none, + iqreq_version, + iqreq_time, + iqreq_last, + iqreq_vcard +}; + +struct annotation { + time_t cdate; + time_t mdate; + gchar *jid; + gchar *text; +}; + +struct bookmark { + gchar *roomjid; + gchar *name; + gchar *nick; + guint autojoin; + /* enum room_printstatus pstatus; */ + /* enum room_autowhois awhois; */ +}; + +extern LmConnection* lconnection; +extern LmSSL* lssl; +extern GMainLoop *main_loop; + +void xmpp_connect(void); +void xmpp_disconnect(void); + +void xmpp_room_join(const char *room, const char *nickname, const char *passwd); +int xmpp_room_setattrib(const char *roomid, const char *fjid, + const char *nick, struct role_affil ra, + const char *reason); +void xmpp_room_invite(const char *room, const char *fjid, const char *reason); +void xmpp_room_unlock(const char *room); +void xmpp_room_destroy(const char *room, const char *venue, const char *reason); + +void xmpp_addbuddy(const char *bjid, const char *name, const char *group); +void xmpp_updatebuddy(const char *bjid, const char *name, const char *group); +void xmpp_delbuddy(const char *bjid); + +void xmpp_send_msg(const char *fjid, const char *text, int type, + const char *subject, gboolean otrinject, gint *encrypted, + LmMessageSubType type_overwrite); + +void xmpp_send_s10n(const char *bjid, LmMessageSubType type); + +enum imstatus xmpp_getstatus(void); +const char *xmpp_getstatusmsg(void); +void xmpp_setprevstatus(void); + +void xmpp_setstatus(enum imstatus st, const char *recipient, + const char *msg, int do_not_sign); + +void xmpp_send_chatstate(gpointer buddy, guint chatstate); + +GSList *xmpp_get_all_storage_bookmarks(void); +GSList *xmpp_get_all_storage_rosternotes(void); +void xmpp_set_storage_bookmark(const char *roomid, const char *name, + const char *nick, const char *passwd, + int autojoin, enum room_printstatus pstatus, + enum room_autowhois awhois); +struct annotation *xmpp_get_storage_rosternotes(const char *barejid, + int silent); +void xmpp_set_storage_rosternotes(const char *barejid, const char *note); +guint xmpp_is_bookmarked(const char *bjid); +const char *xmpp_get_bookmark_nick(const char *bjid); + +void xmpp_request(const char *fjid, enum iqreq_type reqtype); +void request_vcard(const char *bjid); +void xmpp_request_storage(const gchar *storage); +#endif /* __XMPP_H__ */ diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_defines.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_defines.h Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,77 @@ +#ifndef __XMPP_DEFINES_H__ +#define __XMPP_DEFINES_H__ 1 + +#define NS_CLIENT "jabber:client" +#define NS_SERVER "jabber:server" +#define NS_DIALBACK "jabber:server:dialback" +#define NS_AUTH "jabber:iq:auth" +#define NS_AUTH_CRYPT "jabber:iq:auth:crypt" +#define NS_REGISTER "jabber:iq:register" +#define NS_ROSTER "jabber:iq:roster" +#define NS_OFFLINE "jabber:x:offline" +#define NS_AGENT "jabber:iq:agent" +#define NS_AGENTS "jabber:iq:agents" +#define NS_DELAY "jabber:x:delay" +#define NS_VERSION "jabber:iq:version" +#define NS_TIME "jabber:iq:time" +#define NS_VCARD "vcard-temp" +#define NS_PRIVATE "jabber:iq:private" +#define NS_SEARCH "jabber:iq:search" +#define NS_OOB "jabber:iq:oob" +#define NS_XOOB "jabber:x:oob" +#define NS_ADMIN "jabber:iq:admin" +#define NS_FILTER "jabber:iq:filter" +#define NS_AUTH_0K "jabber:iq:auth:0k" +#define NS_BROWSE "jabber:iq:browse" +#define NS_EVENT "jabber:x:event" +#define NS_CONFERENCE "jabber:iq:conference" +#define NS_SIGNED "jabber:x:signed" +#define NS_ENCRYPTED "jabber:x:encrypted" +#define NS_GATEWAY "jabber:iq:gateway" +#define NS_LAST "jabber:iq:last" +#define NS_ENVELOPE "jabber:x:envelope" +#define NS_EXPIRE "jabber:x:expire" +#define NS_XHTML "http://www.w3.org/1999/xhtml" +#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info" +#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" +#define NS_IQ_AUTH "http://jabber.org/features/iq-auth" +#define NS_REGISTER_FEATURE "http://jabber.org/features/iq-register" + +#define NS_CAPS "http://jabber.org/protocol/caps" +#define NS_CHATSTATES "http://jabber.org/protocol/chatstates" +#define NS_COMMANDS "http://jabber.org/protocol/commands" +#define NS_MUC "http://jabber.org/protocol/muc" + +#define NS_XDBGINSERT "jabber:xdb:ginsert" +#define NS_XDBNSLIST "jabber:xdb:nslist" + +#define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" +#define NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls" +#define NS_XMPP_STREAMS "urn:ietf:params:xml:ns:xmpp-streams" + +#define NS_XMPP_DELAY "urn:xmpp:delay" +#define NS_XMPP_TIME "urn:xmpp:time" +#define NS_PING "urn:xmpp:ping" + +#define NS_JABBERD_STOREDPRESENCE "http://jabberd.org/ns/storedpresence" +#define NS_JABBERD_HISTORY "http://jabberd.org/ns/history" + +#define XMPP_ERROR_REDIRECT 302 +#define XMPP_ERROR_BAD_REQUEST 400 +#define XMPP_ERROR_NOT_AUTHORIZED 401 +#define XMPP_ERROR_PAYMENT_REQUIRED 402 +#define XMPP_ERROR_FORBIDDEN 403 +#define XMPP_ERROR_NOT_FOUND 404 +#define XMPP_ERROR_NOT_ALLOWED 405 +#define XMPP_ERROR_NOT_ACCEPTABLE 406 +#define XMPP_ERROR_REGISTRATION_REQUIRED 407 +#define XMPP_ERROR_REQUEST_TIMEOUT 408 +#define XMPP_ERROR_CONFLICT 409 +#define XMPP_ERROR_INTERNAL_SERVER_ERROR 500 +#define XMPP_ERROR_NOT_IMPLEMENTED 501 +#define XMPP_ERROR_REMOTE_SERVER_ERROR 502 +#define XMPP_ERROR_SERVICE_UNAVAILABLE 503 +#define XMPP_ERROR_REMOTE_SERVER_TIMEOUT 504 +#define XMPP_ERROR_DISCONNECTED 510 + +#endif diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_helper.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_helper.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,290 @@ +/* + * xmpp_helper.c -- Jabber protocol helper functions + * + * Copyright (C) 2008 Frank Zschockelt + * Copyright (C) 2005-2008 Mikael Berthe + * Some parts initially came from the centericq project: + * Copyright (C) 2002-2005 by Konstantin Klyagin + * Some small parts come from the Pidgin project + * + * 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 "xmpp_helper.h" + +time_t iqlast; // last message/status change time + +const gchar* lm_message_node_get_child_value(LmMessageNode *node, + const gchar *child) +{ + LmMessageNode *tmp; + tmp = lm_message_node_find_child(node, child); + if (tmp) + return lm_message_node_get_value(tmp); + else return NULL; +} + +static LmMessageNode *hidden = NULL; + +void lm_message_node_hide(LmMessageNode *node) +{ + LmMessageNode *parent = node->parent, *prev_sibling = node->prev; + + if (hidden) { + hidden->children = hidden->next = hidden->prev = hidden->parent = NULL; + lm_message_node_unref(hidden); + } + + if (parent->children == node) + parent->children = node->next; + if (prev_sibling) + prev_sibling->next = node->next; + if (node->next) + node->next->prev = prev_sibling; +} + +//maybe not a good idea, because it uses internals of loudmouth... +//it's used for rosternotes/bookmarks +LmMessageNode *lm_message_node_new(const gchar *name, const gchar *xmlns) +{ + LmMessageNode *node; + + node = g_new0 (LmMessageNode, 1); + node->name = g_strdup (name); + node->value = NULL; + node->raw_mode = FALSE; + node->attributes = NULL; + node->next = NULL; + node->prev = NULL; + node->parent = NULL; + node->children = NULL; + + node->ref_count = 1; + lm_message_node_set_attribute(node, "xmlns", xmlns); + return node; +} + +void lm_message_node_insert_childnode(LmMessageNode *node, + LmMessageNode *child) +{ + LmMessageNode *x; + lm_message_node_deep_ref(child); + + if (node->children == NULL) + node->children = child; + else { + for (x = node->children; x->next; x = x->next) + ; + x->next = child; + } +} + +void lm_message_node_deep_ref(LmMessageNode *node) +{ + if (node == NULL) + return; + lm_message_node_ref(node); + lm_message_node_deep_ref(node->next); + lm_message_node_deep_ref(node->children); +} + +const gchar* lm_message_get_from(LmMessage *m) +{ + return lm_message_node_get_attribute(m->node, "from"); +} + +const gchar* lm_message_get_id(LmMessage *m) +{ + return lm_message_node_get_attribute(m->node, "id"); +} + +static LmMessage *lm_message_new_iq_from_query(LmMessage *m, + LmMessageSubType type) +{ + LmMessage *new; + const char *from = lm_message_node_get_attribute(m->node, "from"); + const char *id = lm_message_node_get_attribute(m->node, "id"); + + new = lm_message_new_with_sub_type(from, LM_MESSAGE_TYPE_IQ, + type); + if (id) + lm_message_node_set_attribute(new->node, "id", id); + + return new; +} + +// entity_version() +// Return a static version string for Entity Capabilities. +// It should be specific to the client version, please change the id +// if you alter mcabber's disco support (or add something to the version +// number) so that it doesn't conflict with the official client. +const char *entity_version(void) +{ + static char *ver; + const char *PVERSION = PACKAGE_VERSION; // "+xxx"; + + if (ver) + return ver; + +#ifdef HGCSET + ver = g_strdup_printf("%s-%s", PVERSION, HGCSET); +#else + ver = g_strdup(PVERSION); +#endif + + return ver; +} + +inline static LmMessageNode *lm_message_node_find_xmlns(LmMessageNode *node, + const char *xmlns) +{ + LmMessageNode *x; + const char *p; + + for (x = node->children ; x; x = x->next) { + if ((p = lm_message_node_get_attribute(x, "xmlns")) && !strcmp(p, xmlns)) + break; + } + return x; +} + +static time_t lm_message_node_get_timestamp(LmMessageNode *node) +{ + LmMessageNode *x; + const char *p; + + x = lm_message_node_find_xmlns(node, NS_XMPP_DELAY); + if (x && (!strcmp(x->name, "delay")) && + (p = lm_message_node_get_attribute(x, "stamp")) != NULL) + return from_iso8601(p, 1); + x = lm_message_node_find_xmlns(node, NS_DELAY); + if (x && (p = lm_message_node_get_attribute(x, "stamp")) != NULL) + return from_iso8601(p, 1); + return 0; +} + +// lm_message_new_presence(status, recipient, message) +// Create an xmlnode with default presence attributes +// Note: the caller must free the node after use +static LmMessage *lm_message_new_presence(enum imstatus st, + const char *recipient, + const char *msg) +{ + unsigned int prio; + LmMessage *x = lm_message_new(recipient, LM_MESSAGE_TYPE_PRESENCE); + + switch(st) { + case away: + case notavail: + case dontdisturb: + case freeforchat: + lm_message_node_add_child(x->node, "show", imstatus_showmap[st]); + break; + + case invisible: + lm_message_node_set_attribute(x->node, "type", "invisible"); + break; + + case offline: + lm_message_node_set_attribute(x->node, "type", "unavailable"); + break; + + default: + break; + } + + if (st == away || st == notavail) + prio = settings_opt_get_int("priority_away"); + else + prio = settings_opt_get_int("priority"); + + if (prio) { + char strprio[8]; + snprintf(strprio, 8, "%d", (int)prio); + lm_message_node_add_child(x->node, "priority", strprio); + } + + if (msg) + lm_message_node_add_child(x->node, "status", msg); + + return x; +} + +static const char *defaulterrormsg(guint code) +{ + int i = 0; + + for (i = 0; xmpp_errors[i].code; ++i) { + if (xmpp_errors[i].code == code) + return xmpp_errors[i].meaning; + } + return NULL; +} + +// display_server_error(x) +// Display the error to the user +// x: error tag xmlnode pointer +void display_server_error(LmMessageNode *x) +{ + const char *desc = NULL, *p=NULL, *s; + char *sdesc, *tmp; + int code = 0; + + if (!x) return; + + /* RFC3920: + * The element: + * o MUST contain a child element corresponding to one of the defined + * stanza error conditions specified below; this element MUST be + * qualified by the 'urn:ietf:params:xml:ns:xmpp-stanzas' namespace. + */ + if (x->children) + p = x->children->name; + if (p) + scr_LogPrint(LPRINT_LOGNORM, "Received error packet [%s]", p); + + // For backward compatibility + if ((s = lm_message_node_get_attribute(x, "code")) != NULL) { + code = atoi(s); + // Default message + desc = defaulterrormsg(code); + } + + // Error tag data is better, if available + s = lm_message_node_get_value(x); + if (s && *s) desc = s; + + // And sometimes there is a text message + s = lm_message_node_get_child_value(x, "text"); + + if (s && *s) desc = s; + + // If we still have no description, let's give up + if (!desc) + return; + + // Strip trailing newlines + sdesc = g_strdup(desc); + for (tmp = sdesc; *tmp; tmp++) ; + if (tmp > sdesc) + tmp--; + while (tmp >= sdesc && (*tmp == '\n' || *tmp == '\r')) + *tmp-- = '\0'; + + scr_LogPrint(LPRINT_LOGNORM, "Error code from server: %d %s", code, sdesc); + g_free(sdesc); +} + diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_helper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_helper.h Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,23 @@ +#ifndef __XMPPHELPER_H__ +#define __XMPPHELPER_H__ 1 + +extern time_t iqlast; /* last message/status change time */ + +struct T_presence { + enum imstatus st; + const char *msg; +}; + +LmMessageNode * lm_message_node_new(const gchar *name, const gchar *xmlns); +const gchar* lm_message_node_get_child_value(LmMessageNode * node, + const gchar *child); +void lm_message_node_hide(LmMessageNode * node); +void lm_message_node_insert_childnode(LmMessageNode * node, + LmMessageNode *child); +void lm_message_node_deep_ref(LmMessageNode * node); + +/* XEP-0115 (Entity Capabilities) node */ +#define MCABBER_CAPS_NODE "http://mcabber.com/caps" +const char *entity_version(void); + +#endif diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_iq.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_iq.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,820 @@ +/* See xmpp.c file for copyright and license details. */ + +static LmHandlerResult handle_iq_command_set_status(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, + gpointer ud); + +static LmHandlerResult handle_iq_command_leave_groupchats(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, + gpointer ud); + +inline double seconds_since_last_use(void); + +struct adhoc_command { + char *name; + char *description; + bool only_for_self; + LmHandleMessageFunction callback; +}; + +const struct adhoc_command adhoc_command_list[] = { + { "http://jabber.org/protocol/rc#set-status", + "Change client status", + 1, + &handle_iq_command_set_status }, + { "http://jabber.org/protocol/rc#leave-groupchats", + "Leave groupchat(s)", + 1, + &handle_iq_command_leave_groupchats }, + { NULL, NULL, 0, NULL }, +}; + +struct adhoc_status { + char *name; // the name used by adhoc + char *description; + char *status; // the string, used by setstus +}; +// It has to match imstatus of roster.h! +const struct adhoc_status adhoc_status_list[] = { + {"offline", "Offline", "offline"}, + {"online", "Online", "avail"}, + {"chat", "Chat", "free"}, + {"dnd", "Do not disturb", "dnd"}, + {"xd", "Extended away", "notavail"}, + {"away", "Away", "away"}, + {"invisible", "Invisible", "invisible"}, + {NULL, NULL, NULL}, +}; + +static char *generate_session_id(char *prefix) +{ + char *result; + static int counter = 0; + counter++; + // TODO better use timestamp? + result = g_strdup_printf("%s-%i", prefix, counter); + return result; +} + +static LmMessage *lm_message_new_iq_error(LmMessage *m, guint error) +{ + LmMessage *r; + LmMessageNode *err; + int i; + + for (i = 0; xmpp_errors[i].code; ++i) + if (xmpp_errors[i].code == error) + break; + g_return_val_if_fail(xmpp_errors[i].code > 0, NULL); + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_ERROR); + err = lm_message_node_add_child(r->node, "error", NULL); + lm_message_node_set_attribute(err, "code", xmpp_errors[i].code_str); + lm_message_node_set_attribute(err, "type", xmpp_errors[i].type); + lm_message_node_set_attribute + (lm_message_node_add_child(err, + xmpp_errors[i].condition, NULL), + "xmlns", NS_XMPP_STANZAS); + + return r; +} + +static void send_iq_error(LmConnection *c, LmMessage *m, guint error) +{ + LmMessage *r; + r = lm_message_new_iq_error(m, error); + lm_connection_send(c, r, NULL); + lm_message_unref(r); +} + +static void lm_message_node_add_dataform_result(LmMessageNode *node, + const char *message) +{ + LmMessageNode *x, *field; + + x = lm_message_node_add_child(node, "x", NULL); + lm_message_node_set_attributes(x, + "type", "result", + "xmlns", "jabber:x:data", + NULL); + field = lm_message_node_add_child(x, "field", NULL); + lm_message_node_set_attributes(field, + "type", "text-single", + "var", "message", + NULL); + lm_message_node_add_child(field, "value", message); +} + +static LmHandlerResult handle_iq_commands_list(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *iq; + LmMessageNode *query; + const char *requester_jid; + const struct adhoc_command *command; + const char *node; + gboolean from_self; + + iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + query = lm_message_node_add_child(iq->node, "query", NULL); + node = lm_message_node_get_attribute + (lm_message_node_get_child(m->node, "query"), + "node"); + if (node) + lm_message_node_set_attribute(query, "node", node); + + requester_jid = lm_message_get_from(m); + from_self = jid_equal(lm_connection_get_jid(c), requester_jid); + + for (command = adhoc_command_list ; command->name ; command++) { + if (!command->only_for_self || from_self) { + lm_message_node_set_attributes + (lm_message_node_add_child(query, "item", NULL), + "node", command->name, + "name", command->description, + "jid", lm_connection_get_jid(c), + NULL); + } + } + + lm_connection_send(c, iq, NULL); + lm_message_unref(iq); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_iq_command_set_status(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer ud) +{ + const char *action, *node; + char *sessionid; + LmMessage *iq; + LmMessageNode *command, *x, *y; + const struct adhoc_status *s; + + x = lm_message_node_get_child(m->node, "command"); + action = lm_message_node_get_attribute(x, "action"); + node = lm_message_node_get_attribute(x, "node"); + sessionid = (char *)lm_message_node_get_attribute(x, "sessionid"); + + iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + command = lm_message_node_add_child(iq->node, "command", NULL); + lm_message_node_set_attribute(command, "node", node); + lm_message_node_set_attribute(command, "xmlns", NS_COMMANDS); + + if (!sessionid) { + sessionid = generate_session_id("set-status"); + lm_message_node_set_attribute(command, "sessionid", sessionid); + g_free(sessionid); + sessionid = NULL; + lm_message_node_set_attribute(command, "status", "executing"); + + x = lm_message_node_add_child(command, "x", NULL); + lm_message_node_set_attribute(x, "type", "form"); + lm_message_node_set_attribute(x, "xmlns", "jabber:x:data"); + + lm_message_node_add_child(x, "title", "Change Status"); + + lm_message_node_add_child(x, "instructions", + "Choose the status and status message"); + + // TODO see if factorisation is possible + y = lm_message_node_add_child(x, "field", NULL); + lm_message_node_set_attribute(y, "type", "hidden"); + lm_message_node_set_attribute(y, "var", "FORM_TYPE"); + + lm_message_node_add_child(y, "value", "http://jabber.org/protocol/rc"); + + y = lm_message_node_add_child(x, "field", NULL); + lm_message_node_set_attributes(y, + "type", "list-single", + "var", "status", + "label", "Status", + NULL); + lm_message_node_add_child(y, "required", NULL); + + // XXX: ugly + lm_message_node_add_child(y, "value", + adhoc_status_list[xmpp_getstatus()].name); + for (s = adhoc_status_list; s->name; s++) { + LmMessageNode *option = lm_message_node_add_child(y, "option", NULL); + lm_message_node_add_child(option, "value", s->name); + lm_message_node_set_attribute(option, "label", s->description); + } + // TODO add priority ? + // I do not think this is useful, user should not have to care of the + // priority like gossip and gajim do (misc) + lm_message_node_set_attributes + (lm_message_node_add_child(x, "field", NULL), + "type", "text-multi", + "var", "status-message", + "label", "Message", + NULL); + } else if (action && !strcmp(action, "cancel")) { + lm_message_node_set_attribute(command, "status", "canceled"); + } else { // (if sessionid and not canceled) + y = lm_message_node_find_xmlns(x, "jabber:x:data"); //x?xmlns=jabber:x:data + if (y) { + const char *value=NULL, *message=NULL; + LmMessageNode *fields, *field; + field = fields = lm_message_node_get_child(y, "field"); //field?var=status + while (field && strcmp("status", + lm_message_node_get_attribute(field, "var"))) + field = field->next; + field = lm_message_node_get_child(field, "value"); + if (field) + value = lm_message_node_get_value(field); + field = fields; //field?var=status-message + while (field && strcmp("status-message", + lm_message_node_get_attribute(field, "var"))) + field = field->next; + field = lm_message_node_get_child(field, "value"); + if (field) + message = lm_message_node_get_value(field); + if (value) { + for (s = adhoc_status_list; !s->name || strcmp(s->name, value); s++); + if (s->name) { + char *status = g_strdup_printf("%s %s", s->status, + message ? message : ""); + cmd_setstatus(NULL, status); + g_free(status); + lm_message_node_set_attribute(command, "status", "completed"); + lm_message_node_add_dataform_result(command, + "Status has been changed"); + } + } + } + } + if (sessionid) + lm_message_node_set_attribute(command, "sessionid", sessionid); + lm_connection_send(c, iq, NULL); + lm_message_unref(iq); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static void _callback_foreach_buddy_groupchat(gpointer rosterdata, void *param) +{ + LmMessageNode *field, *value, *option; + const char *room_jid, *nickname; + char *desc; + + room_jid = buddy_getjid(rosterdata); + if (!room_jid) return; + nickname = buddy_getnickname(rosterdata); + if (!nickname) return; + field = param; + + option = lm_message_node_add_child(field, "option", NULL); + value = lm_message_node_add_child(option, "value", room_jid); + desc = g_strdup_printf("%s on %s", nickname, room_jid); + lm_message_node_set_attribute(option, "label", desc); + g_free(desc); +} + +static LmHandlerResult handle_iq_command_leave_groupchats(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, + gpointer ud) +{ + const char *action, *node; + char *sessionid; + LmMessage *iq; + LmMessageNode *command, *x; + + x = lm_message_node_get_child(m->node, "command"); + action = lm_message_node_get_attribute(x, "action"); + node = lm_message_node_get_attribute(x, "node"); + sessionid = (char*)lm_message_node_get_attribute(x, "sessionid"); + + iq = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + command = lm_message_node_add_child(iq->node, "command", NULL); + lm_message_node_set_attributes(command, + "node", node, + "xmlns", NS_COMMANDS, + NULL); + + if (!sessionid) { + LmMessageNode *field; + + sessionid = generate_session_id("leave-groupchats"); + lm_message_node_set_attribute(command, "sessionid", sessionid); + g_free(sessionid); + sessionid = NULL; + lm_message_node_set_attribute(command, "status", "executing"); + + x = lm_message_node_add_child(command, "x", NULL); + lm_message_node_set_attributes(x, + "type", "form", + "xmlns", "jabber:x:data", + NULL); + + lm_message_node_add_child(x, "title", "Leave groupchat(s)"); + + lm_message_node_add_child(x, "instructions", + "What groupchats do you want to leave?"); + + field = lm_message_node_add_child(x, "field", NULL); + lm_message_node_set_attributes(field, + "type", "hidden", + "var", "FORM_TYPE", + NULL); + + lm_message_node_add_child(field, "value", + "http://jabber.org/protocol/rc"); + + field = lm_message_node_add_child(x, "field", NULL); + lm_message_node_set_attributes(field, + "type", "list-multi", + "var", "groupchats", + "label", "Groupchats: ", + NULL); + lm_message_node_add_child(field, "required", NULL); + + foreach_buddy(ROSTER_TYPE_ROOM, &_callback_foreach_buddy_groupchat, field); + //TODO: return an error if we are not connected to groupchats + } else if (action && !strcmp(action, "cancel")) { + lm_message_node_set_attribute(command, "status", "canceled"); + } else { // (if sessionid and not canceled) + LmMessageNode *form = lm_message_node_find_xmlns(x, "jabber:x:data");//TODO + if (form) { + LmMessageNode *field; + + lm_message_node_set_attribute(command, "status", "completed"); + //TODO: implement sth. like "field?var=groupchats" in xmlnode... + field = lm_message_node_get_child(form, "field"); + while (field && strcmp("groupchats", + lm_message_node_get_attribute(field, "var"))) + field = field->next; + + for (x = field->children ; x ; x = x->next) + { + LmMessageNode *to_leave = lm_message_node_get_child(x, "value"); + if (to_leave) { + GList* b = buddy_search_jid(lm_message_node_get_value(to_leave)); + if (b) + cmd_room_leave(b->data, "Requested by remote command"); + } + } + lm_message_node_add_dataform_result(command, + "Groupchats have been left"); + } + } + if (sessionid) + lm_message_node_set_attribute(command, "sessionid", sessionid); + lm_connection_send(c, iq, NULL); + lm_message_unref(iq); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_iq_commands(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer ud) +{ + const char *requester_jid = NULL; + LmMessageNode *cmd; + const struct adhoc_command *command; + + // mcabber has only partial XEP-0146 support... + if (LM_MESSAGE_SUB_TYPE_SET != lm_message_get_sub_type(m)) + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + + requester_jid = lm_message_get_from(m); + + cmd = lm_message_node_get_child(m->node, "command"); + if (jid_equal(lm_connection_get_jid(c), requester_jid)) { + const char *action, *node; + action = lm_message_node_get_attribute(cmd, "action"); + node = lm_message_node_get_attribute(cmd, "node"); + // action can be NULL, in which case it seems to take the default, + // ie execute + if (!action || !strcmp(action, "execute") || !strcmp(action, "cancel") + || !strcmp(action, "next") || !strcmp(action, "complete")) { + for (command = adhoc_command_list; command->name; command++) { + if (!strcmp(node, command->name)) + command->callback(h, c, m, ud); + } + // "prev" action will get there, as we do not implement it, + // and do not authorize it + } else { + LmMessage *r; + LmMessageNode *err; + r = lm_message_new_iq_error(m, XMPP_ERROR_BAD_REQUEST); + err = lm_message_node_get_child(r->node, "error"); + lm_message_node_set_attribute + (lm_message_node_add_child(err, "malformed-action", NULL), + "xmlns", NS_COMMANDS); + lm_connection_send(c, r, NULL); + lm_message_unref(r); + } + } else { + send_iq_error(c, m, XMPP_ERROR_FORBIDDEN); + } + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + + +static LmHandlerResult handle_iq_disco_items(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessageNode *query; + const char *node; + query = lm_message_node_get_child(m->node, "query"); + node = lm_message_node_get_attribute(query, "node"); + if (node) { + if (!strcmp(node, NS_COMMANDS)) { + return handle_iq_commands_list(NULL, c, m, ud); + } else { + send_iq_error(c, m, XMPP_ERROR_NOT_IMPLEMENTED); + } + } else { + // not sure about this one + send_iq_error(c, m, XMPP_ERROR_NOT_IMPLEMENTED); + } + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + + +// disco_info_set_ext(ansquery, ext) +// Add features attributes to ansquery for extension ext. +static void disco_info_set_ext(LmMessageNode *ansquery, const char *ext) +{ + char *nodename = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, ext); + lm_message_node_set_attribute(ansquery, "node", nodename); + g_free(nodename); + if (!strcasecmp(ext, "csn")) { + // I guess it's ok to send this even if it's not compiled in. + lm_message_node_set_attribute(lm_message_node_add_child(ansquery, + "feature", NULL), + "var", NS_CHATSTATES); + } + if (!strcasecmp(ext, "iql")) { + // I guess it's ok to send this even if it's not compiled in. + lm_message_node_set_attribute(lm_message_node_add_child(ansquery, + "feature", NULL), + "var", NS_LAST); + } +} + +// disco_info_set_default(ansquery, entitycaps) +// Add features attributes to ansquery. If entitycaps is TRUE, assume +// that we're answering an Entity Caps request (if not, the request was +// a basic discovery query). +// Please change the entity version string if you modify mcabber disco +// source code, so that it doesn't conflict with the upstream client. +static void disco_info_set_default(LmMessageNode *ansquery, guint entitycaps) +{ + LmMessageNode *y; + char *eversion; + + eversion = g_strdup_printf("%s#%s", MCABBER_CAPS_NODE, entity_version()); + lm_message_node_set_attribute(ansquery, "node", eversion); + g_free(eversion); + + y = lm_message_node_add_child(ansquery, "identity", NULL); + + lm_message_node_set_attributes(y, + "category", "client", + "type", "pc", + "name", PACKAGE_NAME, + NULL); + + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_DISCO_INFO); + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_MUC); +#ifdef JEP0085 + // Advertise ChatStates only if we're not using Entity Capabilities + if (!entitycaps) + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_CHATSTATES); +#endif + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_TIME); + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_XMPP_TIME); + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_VERSION); + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_PING); + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_COMMANDS); + if (!entitycaps) + lm_message_node_set_attribute + (lm_message_node_add_child(ansquery, "feature", NULL), + "var", NS_LAST); +} + +static LmHandlerResult handle_iq_disco_info(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + LmMessageNode *query, *tmp; + const char *node = NULL; + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + query = lm_message_node_add_child(r->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", NS_DISCO_INFO); + tmp = lm_message_node_find_child(m->node, "query"); + if (tmp) + node = lm_message_node_get_attribute(tmp, "node"); + if (node && startswith(node, MCABBER_CAPS_NODE "#", FALSE)) { + const char *param = node+strlen(MCABBER_CAPS_NODE)+1; + if (!strcmp(param, entity_version())) + disco_info_set_default(query, TRUE); // client#version + else + disco_info_set_ext(query, param); // client#extension + } else { + // Basic discovery request + disco_info_set_default(query, FALSE); + } + + lm_connection_send(c, r, NULL); + lm_message_unref(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_iq_roster(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessageNode *y; + const char *fjid, *name, *group, *sub, *ask; + char *cleanalias; + enum subscr esub; + int need_refresh = FALSE; + guint roster_type; + + for (y = lm_message_node_find_child(lm_message_node_find_xmlns + (m->node, NS_ROSTER), + "item"); + y; + y = y->next) { + char *name_tmp = NULL; + + fjid = lm_message_node_get_attribute(y, "jid"); + name = lm_message_node_get_attribute(y, "name"); + sub = lm_message_node_get_attribute(y, "subscription"); + ask = lm_message_node_get_attribute(y, "ask"); + + if (lm_message_node_find_child(y, "group")) + group = lm_message_node_get_value(lm_message_node_find_child(y, "group")); + else + group = NULL; + + if (!fjid) + continue; + + cleanalias = jidtodisp(fjid); + + esub = sub_none; + if (sub) { + if (!strcmp(sub, "to")) esub = sub_to; + else if (!strcmp(sub, "from")) esub = sub_from; + else if (!strcmp(sub, "both")) esub = sub_both; + else if (!strcmp(sub, "remove")) esub = sub_remove; + } + + if (esub == sub_remove) { + roster_del_user(cleanalias); + scr_LogPrint(LPRINT_LOGNORM, "Buddy <%s> has been removed " + "from the roster", cleanalias); + g_free(cleanalias); + need_refresh = TRUE; + continue; + } + + if (ask && !strcmp(ask, "subscribe")) + esub |= sub_pending; + + if (!name) { + if (!settings_opt_get_int("roster_hide_domain")) { + name = cleanalias; + } else { + char *p; + name = name_tmp = g_strdup(cleanalias); + p = strchr(name_tmp, JID_DOMAIN_SEPARATOR); + if (p) *p = '\0'; + } + } + + // Tricky... :-\ My guess is that if there is no JID_DOMAIN_SEPARATOR, + // this is an agent. + if (strchr(cleanalias, JID_DOMAIN_SEPARATOR)) + roster_type = ROSTER_TYPE_USER; + else + roster_type = ROSTER_TYPE_AGENT; + + roster_add_user(cleanalias, name, group, roster_type, esub, 1); + + g_free(name_tmp); + g_free(cleanalias); + } + + buddylist_build(); + update_roster = TRUE; + if (need_refresh) + scr_UpdateBuddyWindow(); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_iq_ping(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + lm_connection_send(c, r, NULL); + lm_message_unref(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +double seconds_since_last_use(void) +{ + return difftime(time(NULL), iqlast); +} + +static LmHandlerResult handle_iq_last(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + LmMessageNode *query; + char *seconds; + + if (!settings_opt_get_int("iq_hide_requests")) { + scr_LogPrint(LPRINT_LOGNORM, "Received an IQ last time request from <%s>", + lm_message_get_from(m)); + } + + if (settings_opt_get_int("iq_last_disable") || + (settings_opt_get_int("iq_last_disable_when_notavail") && + xmpp_getstatus() == notavail)) + { + send_iq_error(c, m, XMPP_ERROR_SERVICE_UNAVAILABLE); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + query = lm_message_node_add_child(r->node, "query", NULL); + seconds = g_strdup_printf("%.0f", seconds_since_last_use()); + lm_message_node_set_attribute(query, "seconds", seconds); + g_free(seconds); + + lm_connection_send(c, r, NULL); + lm_message_unref(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult handle_iq_version(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + LmMessageNode *query; + char *os = NULL; + char *ver = mcabber_version(); + + if (!settings_opt_get_int("iq_hide_requests")) { + scr_LogPrint(LPRINT_LOGNORM, "Received an IQ version request from <%s>", + lm_message_get_from(m)); + } + if (!settings_opt_get_int("iq_version_hide_os")) { + struct utsname osinfo; + uname(&osinfo); + os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, + osinfo.machine); + } + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + + query = lm_message_node_add_child(r->node, "query", NULL); + + lm_message_node_add_child(query, "name", PACKAGE_NAME); + lm_message_node_add_child(query, "version", ver); + if (os) { + lm_message_node_add_child(query, "os", os); + g_free(os); + } + + g_free(ver); + lm_connection_send(c, r, NULL); + lm_message_unref(r); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +// This function borrows some code from the Pidgin project +static LmHandlerResult handle_iq_time(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + LmMessageNode *query; + char *buf, *utf8_buf; + time_t now_t; + struct tm *now; + + time(&now_t); + + if (!settings_opt_get_int("iq_hide_requests")) { + scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", + lm_message_get_from(m)); + } + + buf = g_new0(char, 512); + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + query = lm_message_node_add_child(r->node, "query", NULL); + + now = gmtime(&now_t); + + strftime(buf, 512, "%Y%m%dT%T", now); + lm_message_node_add_child(query, "utc", buf); + + now = localtime(&now_t); + + strftime(buf, 512, "%Z", now); + if ((utf8_buf = to_utf8(buf))) { + lm_message_node_add_child(query, "tz", utf8_buf); + g_free(utf8_buf); + } + + strftime(buf, 512, "%d %b %Y %T", now); + if ((utf8_buf = to_utf8(buf))) { + lm_message_node_add_child(query, "display", utf8_buf); + g_free(utf8_buf); + } + + lm_connection_send(c, r, NULL); + lm_message_unref(r); + g_free(buf); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +// This function borrows some code from the Pidgin project +static LmHandlerResult handle_iq_time202(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer ud) +{ + LmMessage *r; + LmMessageNode *query; + char *buf, *utf8_buf; + time_t now_t; + struct tm *now; + char const *sign; + int diff = 0; + + time(&now_t); + + if (!settings_opt_get_int("iq_hide_requests")) { + scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>", + lm_message_get_from(m)); + } + + buf = g_new0(char, 512); + + r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT); + query = lm_message_node_add_child(r->node, "time", NULL); + lm_message_node_set_attribute(query, "xmlns", NS_XMPP_TIME); + + now = localtime(&now_t); + + if (now->tm_isdst >= 0) { +#if defined HAVE_TM_GMTOFF + diff = now->tm_gmtoff; +#elif defined HAVE_TIMEZONE + tzset(); + diff = -timezone; +#endif + } + + if (diff < 0) { + sign = "-"; + diff = -diff; + } else { + sign = "+"; + } + diff /= 60; + snprintf(buf, 512, "%c%02d:%02d", *sign, diff / 60, diff % 60); + if ((utf8_buf = to_utf8(buf))) { + lm_message_node_add_child(query, "tzo", utf8_buf); + g_free(utf8_buf); + } + + now = gmtime(&now_t); + + strftime(buf, 512, "%Y-%m-%dT%TZ", now); + lm_message_node_add_child(query, "utc", buf); + + lm_connection_send(c, r, NULL); + lm_message_unref(r); + g_free(buf); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_iqrequest.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_iqrequest.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,600 @@ +/* See xmpp.c file for copyright and license details. */ + +static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data); +static LmHandlerResult cb_version(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data); +static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data); +static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data); +static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data); + +static struct IqRequestHandlers +{ + const gchar *xmlns; + const gchar *querytag; + LmHandleMessageFunction handler; +} iq_request_handlers[] = { + {NS_ROSTER, "query", &cb_roster}, + {NS_VERSION,"query", &cb_version}, + {NS_TIME, "query", &cb_time}, + {NS_LAST, "query", &cb_last}, + {NS_VCARD, "vCard", &cb_vcard}, + {NULL, NULL, NULL} +}; + +// Enum for vCard attributes +enum vcard_attr { + vcard_home = 1<<0, + vcard_work = 1<<1, + vcard_postal = 1<<2, + vcard_voice = 1<<3, + vcard_fax = 1<<4, + vcard_cell = 1<<5, + vcard_inet = 1<<6, + vcard_pref = 1<<7, +}; + +// xmlns has to be a namespace from iq_request_handlers[].xmlns +void xmpp_iq_request(const char *fulljid, const char *xmlns) +{ + LmMessage *iq; + LmMessageNode *query; + LmMessageHandler *handler; + int i; + + iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_GET); + for (i = 0; strcmp(iq_request_handlers[i].xmlns, xmlns) != 0 ; ++i) + ; + query = lm_message_node_add_child(iq->node, + iq_request_handlers[i].querytag, + NULL); + lm_message_node_set_attribute(query, "xmlns", xmlns); + handler = lm_message_handler_new(iq_request_handlers[i].handler, + NULL, FALSE); + lm_connection_send_with_reply(lconnection, iq, handler, NULL); + lm_message_handler_unref(handler); + lm_message_unref(iq); +} + +// This callback is reached when mcabber receives the first roster update +// after the connection. +static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *x; + const char *ns; + + // Only execute the hook if the roster has been successfully retrieved + if (lm_message_get_sub_type(m) != LM_MESSAGE_SUB_TYPE_RESULT) + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + + x = lm_message_node_find_child(m->node, "query"); + if (!x) + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + + ns = lm_message_node_get_attribute(x, "xmlns"); + if (ns && !strcmp(ns, NS_ROSTER)) + handle_iq_roster(NULL, c, m, user_data); + + // Post-login stuff + hook_execute_internal("hook-post-connect"); + + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult cb_version(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *ansqry; + const char *p, *bjid; + char *tmp; + char *buf; + + ansqry = lm_message_node_get_child(m->node, "query"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result!"); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + + // Display IQ result sender... + p = lm_message_get_from(m); + if (!p) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name)."); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + bjid = p; + + buf = g_strdup_printf("Received IQ:version result from <%s>", bjid); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + + // bjid should now really be the "bare JID", let's strip the resource + tmp = strchr(bjid, JID_RESOURCE_SEPARATOR); + if (tmp) *tmp = '\0'; + + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); + g_free(buf); + + // Get result data... + p = lm_message_node_get_child_value(ansqry, "name"); + if (p) { + buf = g_strdup_printf("Name: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + p = lm_message_node_get_child_value(ansqry, "version"); + if (p) { + buf = g_strdup_printf("Version: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + p = lm_message_node_get_child_value(ansqry, "os"); + if (p) { + buf = g_strdup_printf("OS: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *ansqry; + const char *p, *bjid; + char *tmp; + char *buf; + + ansqry = lm_message_node_get_child(m->node, "query"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result!"); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + // Display IQ result sender... + p = lm_message_get_from(m); + if (!p) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name)."); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + bjid = p; + + buf = g_strdup_printf("Received IQ:time result from <%s>", bjid); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + + // bjid should now really be the "bare JID", let's strip the resource + tmp = strchr(bjid, JID_RESOURCE_SEPARATOR); + if (tmp) *tmp = '\0'; + + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); + g_free(buf); + + // Get result data... + p = lm_message_node_get_child_value(ansqry, "utc"); + if (p) { + buf = g_strdup_printf("UTC: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + p = lm_message_node_get_child_value(ansqry, "tz"); + if (p) { + buf = g_strdup_printf("TZ: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + p = lm_message_node_get_child_value(ansqry, "display"); + if (p) { + buf = g_strdup_printf("Time: %s", p); + scr_WriteIncomingMessage(bjid, buf, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); + } + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *ansqry; + const char *p, *bjid; + char *buf, *tmp; + + ansqry = lm_message_node_get_child(m->node, "query"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result!"); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + // Display IQ result sender... + p = lm_message_get_from(m); + if (!p) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name)."); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + bjid = p; + + buf = g_strdup_printf("Received IQ:last result from <%s>", bjid); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + + // bjid should now really be the "bare JID", let's strip the resource + tmp = strchr(bjid, JID_RESOURCE_SEPARATOR); + if (tmp) *tmp = '\0'; + + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); + g_free(buf); + + // Get result data... + p = lm_message_node_get_attribute(ansqry, "seconds"); + if (p) { + long int s; + GString *sbuf; + sbuf = g_string_new("Idle time: "); + s = atol(p); + // Days + if (s > 86400L) { + g_string_append_printf(sbuf, "%ldd ", s/86400L); + s %= 86400L; + } + // hh:mm:ss + g_string_append_printf(sbuf, "%02ld:", s/3600L); + s %= 3600L; + g_string_append_printf(sbuf, "%02ld:%02ld", s/60L, s%60L); + scr_WriteIncomingMessage(bjid, sbuf->str, + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_string_free(sbuf, TRUE); + } else { + scr_WriteIncomingMessage(bjid, "No idle time reported.", + 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + } + p = lm_message_node_get_value(ansqry); + if (p) { + buf = g_strdup_printf("Status message: %s", p); + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); + g_free(buf); + } + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static void display_vcard_item(const char *bjid, const char *label, + enum vcard_attr vcard_attrib, const char *text) +{ + char *buf; + + if (!text || !bjid || !label) + return; + + buf = g_strdup_printf("%s: %s%s%s%s%s%s%s%s%s%s", label, + (vcard_attrib & vcard_home ? "[home]" : ""), + (vcard_attrib & vcard_work ? "[work]" : ""), + (vcard_attrib & vcard_postal ? "[postal]" : ""), + (vcard_attrib & vcard_voice ? "[voice]" : ""), + (vcard_attrib & vcard_fax ? "[fax]" : ""), + (vcard_attrib & vcard_cell ? "[cell]" : ""), + (vcard_attrib & vcard_inet ? "[inet]" : ""), + (vcard_attrib & vcard_pref ? "[pref]" : ""), + (vcard_attrib ? " " : ""), + text); + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); + g_free(buf); +} + +static void handle_vcard_node(const char *barejid, LmMessageNode *vcardnode) +{ + LmMessageNode *x; + const char *p; + + for (x = vcardnode->children ; x; x = x->next) { + const char *data; + enum vcard_attr vcard_attrib = 0; + + p = x->name; + data = lm_message_node_get_value(x); + if (!p || !data) + continue; + + if (!strcmp(p, "FN")) + display_vcard_item(barejid, "Name", vcard_attrib, data); + else if (!strcmp(p, "NICKNAME")) + display_vcard_item(barejid, "Nickname", vcard_attrib, data); + else if (!strcmp(p, "URL")) + display_vcard_item(barejid, "URL", vcard_attrib, data); + else if (!strcmp(p, "BDAY")) + display_vcard_item(barejid, "Birthday", vcard_attrib, data); + else if (!strcmp(p, "TZ")) + display_vcard_item(barejid, "Timezone", vcard_attrib, data); + else if (!strcmp(p, "TITLE")) + display_vcard_item(barejid, "Title", vcard_attrib, data); + else if (!strcmp(p, "ROLE")) + display_vcard_item(barejid, "Role", vcard_attrib, data); + else if (!strcmp(p, "DESC")) + display_vcard_item(barejid, "Comment", vcard_attrib, data); + else if (!strcmp(p, "N")) { + data = lm_message_node_get_child_value(x, "FAMILY"); + display_vcard_item(barejid, "Family Name", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "GIVEN"); + display_vcard_item(barejid, "Given Name", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "MIDDLE"); + display_vcard_item(barejid, "Middle Name", vcard_attrib, data); + } else if (!strcmp(p, "ORG")) { + data = lm_message_node_get_child_value(x, "ORGNAME"); + display_vcard_item(barejid, "Organisation name", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "ORGUNIT"); + display_vcard_item(barejid, "Organisation unit", vcard_attrib, data); + } else { + // The HOME, WORK and PREF attributes are common to the remaining fields + // (ADR, TEL & EMAIL) + if (lm_message_node_get_child(x, "HOME")) + vcard_attrib |= vcard_home; + if (lm_message_node_get_child(x, "WORK")) + vcard_attrib |= vcard_work; + if (lm_message_node_get_child(x, "PREF")) + vcard_attrib |= vcard_pref; + if (!strcmp(p, "ADR")) { // Address + if (lm_message_node_get_child(x, "POSTAL")) + vcard_attrib |= vcard_postal; + data = lm_message_node_get_child_value(x, "EXTADD"); + display_vcard_item(barejid, "Addr (ext)", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "STREET"); + display_vcard_item(barejid, "Street", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "LOCALITY"); + display_vcard_item(barejid, "Locality", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "REGION"); + display_vcard_item(barejid, "Region", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "PCODE"); + display_vcard_item(barejid, "Postal code", vcard_attrib, data); + data = lm_message_node_get_child_value(x, "CTRY"); + display_vcard_item(barejid, "Country", vcard_attrib, data); + } else if (!strcmp(p, "TEL")) { // Telephone + data = lm_message_node_get_child_value(x, "NUMBER"); + if (data) { + if (lm_message_node_get_child(x, "VOICE")) + vcard_attrib |= vcard_voice; + if (lm_message_node_get_child(x, "FAX")) + vcard_attrib |= vcard_fax; + if (lm_message_node_get_child(x, "CELL")) + vcard_attrib |= vcard_cell; + display_vcard_item(barejid, "Phone", vcard_attrib, data); + } + } else if (!strcmp(p, "EMAIL")) { // Email + if (lm_message_node_get_child(x, "INTERNET")) + vcard_attrib |= vcard_inet; + data = lm_message_node_get_child_value(x, "USERID"); + display_vcard_item(barejid, "Email", vcard_attrib, data); + } + } + } +} + +static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *ansqry; + const char *p, *bjid; + char *buf, *tmp; + + // Display IQ result sender... + p = lm_message_get_from(m); + if (!p) { + scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name)."); + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + } + bjid = p; + + buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + + // Get the vCard node + ansqry = lm_message_node_get_child(m->node, "vCard"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!"); + g_free(buf); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + + // bjid should really be the "bare JID", let's strip the resource + tmp = strchr(bjid, JID_RESOURCE_SEPARATOR); + if (tmp) *tmp = '\0'; + + scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0); + g_free(buf); + + // Get result data... + handle_vcard_node(bjid, ansqry); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +static void storage_bookmarks_parse_conference(LmMessageNode *node) +{ + const char *fjid, *name, *autojoin; + const char *pstatus, *awhois; + char *bjid; + GSList *room_elt; + + fjid = lm_message_node_get_attribute(node, "jid"); + if (!fjid) + return; + name = lm_message_node_get_attribute(node, "name"); + autojoin = lm_message_node_get_attribute(node, "autojoin"); + awhois = lm_message_node_get_attribute(node, "autowhois"); + pstatus = lm_message_node_get_child_value(node, "print_status"); + + bjid = jidtodisp(fjid); // Bare jid + + // Make sure this is a room (it can be a conversion user->room) + room_elt = roster_find(bjid, jidsearch, 0); + if (!room_elt) { + room_elt = roster_add_user(bjid, name, NULL, ROSTER_TYPE_ROOM, + sub_none, -1); + } else { + buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); + /* + // If the name is available, should we use it? + // I don't think so, it would be confusing because this item is already + // in the roster. + if (name) + buddy_setname(room_elt->data, name); + */ + } + + // Set the print_status and auto_whois values + if (pstatus) { + enum room_printstatus i; + for (i = status_none; i <= status_all; i++) + if (!strcasecmp(pstatus, strprintstatus[i])) + break; + if (i <= status_all) + buddy_setprintstatus(room_elt->data, i); + } + if (awhois) { + enum room_autowhois i = autowhois_default; + if (!strcmp(awhois, "1")) + i = autowhois_on; + else if (!strcmp(awhois, "0")) + i = autowhois_off; + if (i != autowhois_default) + buddy_setautowhois(room_elt->data, i); + } + + // Is autojoin set? + // If it is, we'll look up for more information (nick? password?) and + // try to join the room. + if (autojoin && !strcmp(autojoin, "1")) { + const char *nick, *passwd; + char *tmpnick = NULL; + nick = lm_message_node_get_child_value(node, "nick"); + passwd = lm_message_node_get_child_value(node, "password"); + if (!nick || !*nick) + nick = tmpnick = default_muc_nickname(NULL); + // Let's join now + scr_LogPrint(LPRINT_LOGNORM, "Auto-join bookmark <%s>", bjid); + xmpp_room_join(bjid, nick, passwd); + g_free(tmpnick); + } + g_free(bjid); +} + +static LmHandlerResult cb_storage_bookmarks(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *x, *ansqry; + char *p; + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) { + // No server support, or no bookmarks? + p = m->node->children->name; + if (p && !strcmp(p, "item-not-found")) { + // item-no-found means the server has Private Storage, but it's + // currently empty. + if (bookmarks) + lm_message_node_unref(bookmarks); + bookmarks = lm_message_node_new("storage", "storage:bookmarks"); + // We return 0 so that the IQ error message be + // not displayed, as it isn't a real error. + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; // Unhandled error + } + + ansqry = lm_message_node_get_child(m->node, "query"); + ansqry = lm_message_node_get_child(ansqry, "storage"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)"); + return 0; + } + + // Walk through the storage tags + for (x = ansqry->children ; x; x = x->next) { + // If the current node is a conference item, parse it and update the roster + if (x->name && !strcmp(x->name, "conference")) + storage_bookmarks_parse_conference(x); + } + // "Copy" the bookmarks node + if (bookmarks) + lm_message_node_unref(bookmarks); + lm_message_node_deep_ref(ansqry); + bookmarks = ansqry; + return 0; +} + + +static LmHandlerResult cb_storage_rosternotes(LmMessageHandler *h, + LmConnection *c, + LmMessage *m, gpointer user_data) +{ + LmMessageNode *ansqry; + + if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) { + const char *p; + // No server support, or no roster notes? + p = m->node->children->name; + if (p && !strcmp(p, "item-not-found")) { + // item-no-found means the server has Private Storage, but it's + // currently empty. + if (rosternotes) + lm_message_node_unref(rosternotes); + rosternotes = lm_message_node_new("storage", "storage:rosternotes"); + // We return 0 so that the IQ error message be + // not displayed, as it isn't a real error. + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; // Unhandled error + } + + ansqry = lm_message_node_get_child(m->node, "query"); + ansqry = lm_message_node_get_child(ansqry, "storage"); + if (!ansqry) { + scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! " + "(storage:rosternotes)"); + return LM_HANDLER_RESULT_REMOVE_MESSAGE; + } + // Copy the rosternotes node + if (rosternotes) + lm_message_node_unref(rosternotes); + lm_message_node_deep_ref(ansqry); + rosternotes = ansqry; + return 0; +} + + +static struct IqRequestStorageHandlers +{ + const gchar *storagens; + LmHandleMessageFunction handler; +} iq_request_storage_handlers[] = { + {"storage:rosternotes", &cb_storage_rosternotes}, + {"storage:bookmarks", &cb_storage_bookmarks}, + {NULL, NULL} +}; + +void xmpp_request_storage(const gchar *storage) +{ + LmMessage *iq; + LmMessageNode *query; + LmMessageHandler *handler; + int i; + + iq = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_GET); + query = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", NS_PRIVATE); + lm_message_node_set_attribute(lm_message_node_add_child + (query, "storage", NULL), + "xmlns", storage); + + for (i = 0; + strcmp(iq_request_storage_handlers[i].storagens, storage) != 0; + ++i) ; + + handler = lm_message_handler_new(iq_request_storage_handlers[i].handler, + NULL, FALSE); + lm_connection_send_with_reply(lconnection, iq, handler, NULL); + lm_message_handler_unref(handler); + lm_message_unref(iq); +} diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_muc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_muc.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,678 @@ +/* See xmpp.c file for copyright and license details. */ + +static void decline_invitation(event_muc_invitation *invitation, char *reason) +{ + // cut and paste from xmpp_room_invite + LmMessage *m; + LmMessageNode *x, *y; + + if (!invitation) return; + if (!invitation->to || !invitation->from) return; + + m = lm_message_new(invitation->to, LM_MESSAGE_TYPE_MESSAGE); + + x = lm_message_node_add_child(m->node, "x", NULL); + lm_message_node_set_attribute(x, "xmlns", + "http://jabber.org/protocol/muc#user"); + + y = lm_message_node_add_child(x, "decline", NULL); + lm_message_node_set_attribute(y, "to", invitation->from); + + if (reason) + lm_message_node_add_child(y, "reason", reason); + + lm_connection_send(lconnection, m, NULL); + lm_message_unref(m); +} + +static int evscallback_invitation(eviqs *evp, guint evcontext) +{ + event_muc_invitation *invitation = evp->data; + + // Sanity check + if (!invitation) { + // Shouldn't happen. + scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); + return 0; + } + + if (evcontext == EVS_CONTEXT_TIMEOUT) { + scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", evp->id); + goto evscallback_invitation_free; + } + if (evcontext == EVS_CONTEXT_CANCEL) { + scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id); + goto evscallback_invitation_free; + } + if (!(evcontext & EVS_CONTEXT_USER)) + goto evscallback_invitation_free; + // Ok, let's work now. + // evcontext: 0, 1 == reject, accept + + if (evcontext & ~EVS_CONTEXT_USER) { + char *nickname = default_muc_nickname(invitation->to); + xmpp_room_join(invitation->to, nickname, invitation->passwd); + g_free(nickname); + } else { + scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to); + decline_invitation(invitation, NULL); + } + +evscallback_invitation_free: + g_free(invitation->to); + g_free(invitation->from); + g_free(invitation->passwd); + g_free(invitation->reason); + g_free(invitation); + evp->data = NULL; + return 0; +} + +// Join a MUC room +void xmpp_room_join(const char *room, const char *nickname, const char *passwd) +{ + LmMessage *x; + LmMessageNode *y; + gchar *roomid; + GSList *room_elt; + + if (!lm_connection_is_authenticated(lconnection) || !room) return; + if (!nickname) return; + + roomid = g_strdup_printf("%s/%s", room, nickname); + if (check_jid_syntax(roomid)) { + scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room, + nickname); + g_free(roomid); + return; + } + + room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); + // Add room if it doesn't already exist + if (!room_elt) { + room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM, + sub_none, -1); + } else { + // Make sure this is a room (it can be a conversion user->room) + buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); + } + // If insideroom is TRUE, this is a nickname change and we don't care here + if (!buddy_getinsideroom(room_elt->data)) { + // We're trying to enter a room + buddy_setnickname(room_elt->data, nickname); + } + + // Send the XML request + x = lm_message_new(roomid, LM_MESSAGE_TYPE_PRESENCE); + + x = lm_message_new_presence(mystatus, roomid, mystatusmsg); + y = lm_message_node_add_child(x->node, "x", NULL); + lm_message_node_set_attribute(y, "xmlns", "http://jabber.org/protocol/muc"); + if (passwd) + lm_message_node_add_child(y, "password", passwd); + + lm_connection_send(lconnection, x, NULL); + lm_message_unref(x); + g_free(roomid); +} + +// Invite a user to a MUC room +// room syntax: "room@server" +// reason can be null. +void xmpp_room_invite(const char *room, const char *fjid, const char *reason) +{ + LmMessage *msg; + LmMessageNode *x, *y; + + if (!lm_connection_is_authenticated(lconnection) || !room || !fjid) return; + + msg = lm_message_new(room, LM_MESSAGE_TYPE_MESSAGE); + + x = lm_message_node_add_child(msg->node, "x", NULL); + lm_message_node_set_attribute(x, "xmlns", + "http://jabber.org/protocol/muc#user"); + + y = lm_message_node_add_child(x, "invite", NULL); + lm_message_node_set_attribute(y, "to", fjid); + + if (reason) + lm_message_node_add_child(y, "reason", reason); + + lm_connection_send(lconnection, msg, NULL); + lm_message_unref(msg); +} + +int xmpp_room_setattrib(const char *roomid, const char *fjid, + const char *nick, struct role_affil ra, + const char *reason) +{ + LmMessage *iq; + LmMessageNode *query, *x; + + if (!lm_connection_is_authenticated(lconnection) || !roomid) return 1; + if (!fjid && !nick) return 1; + + if (check_jid_syntax((char*)roomid)) { + scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid); + return 1; + } + if (fjid && check_jid_syntax((char*)fjid)) { + scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid); + return 1; + } + + if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid) + return 1; // Shouldn't happen (jid mandatory when banning) + + iq = lm_message_new_with_sub_type(roomid, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + query = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", + "http://jabber.org/protocol/muc#admin"); + x = lm_message_node_add_child(query, "item", NULL); + + if (fjid) { + lm_message_node_set_attribute(x, "jid", fjid); + } else { // nickname + lm_message_node_set_attribute(x, "nick", nick); + } + + if (ra.type == type_affil) + lm_message_node_set_attribute(x, "affiliation", straffil[ra.val.affil]); + else if (ra.type == type_role) + lm_message_node_set_attribute(x, "role", strrole[ra.val.role]); + + if (reason) + lm_message_node_add_child(x, "reason", reason); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); + + return 0; +} + +// Unlock a MUC room +// room syntax: "room@server" +void xmpp_room_unlock(const char *room) +{ + LmMessageNode *y, *z; + LmMessage *iq; + + if (!lm_connection_is_authenticated(lconnection) || !room) return; + + iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + lm_message_node_set_attribute(iq->node, "xmlns", + "http://jabber.org/protocol/muc#owner"); + + + y = lm_message_node_add_child(iq->node, "query", NULL); + z = lm_message_node_add_child(y, "x", NULL); + lm_message_node_set_attribute(z, "xmlns", "jabber:x:data"); + lm_message_node_set_attribute(z, "type", "submit"); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); +} + +// Destroy a MUC room +// room syntax: "room@server" +void xmpp_room_destroy(const char *room, const char *venue, const char *reason) +{ + LmMessage *iq; + LmMessageNode *query, *x; + + if (!lm_connection_is_authenticated(lconnection) || !room) return; + + iq = lm_message_new_with_sub_type(room, LM_MESSAGE_TYPE_IQ, + LM_MESSAGE_SUB_TYPE_SET); + query = lm_message_node_add_child(iq->node, "query", NULL); + lm_message_node_set_attribute(query, "xmlns", + "http://jabber.org/protocol/muc#owner"); + x = lm_message_node_add_child(query, "destroy", NULL); + + if (venue && *venue) + lm_message_node_set_attribute(x, "jid", venue); + + if (reason) + lm_message_node_add_child(x, "reason", reason); + + lm_connection_send(lconnection, iq, NULL); + lm_message_unref(iq); +} + +// muc_get_item_info(...) +// Get room member's information from xmlndata. +// The variables must be initialized before calling this function, +// because they are not touched if the relevant information is missing. +static void muc_get_item_info(const char *from, LmMessageNode *xmldata, + enum imrole *mbrole, enum imaffiliation *mbaffil, + const char **mbjid, const char **mbnick, + const char **actorjid, const char **reason) +{ + LmMessageNode *y, *z; + const char *p; + + y = lm_message_node_find_child(xmldata, "item"); + if (!y) + return; + + p = lm_message_node_get_attribute(y, "affiliation"); + if (p) { + if (!strcmp(p, "owner")) *mbaffil = affil_owner; + else if (!strcmp(p, "admin")) *mbaffil = affil_admin; + else if (!strcmp(p, "member")) *mbaffil = affil_member; + else if (!strcmp(p, "outcast")) *mbaffil = affil_outcast; + else if (!strcmp(p, "none")) *mbaffil = affil_none; + else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown affiliation \"%s\"", + from, p); + } + p = lm_message_node_get_attribute(y, "role"); + if (p) { + if (!strcmp(p, "moderator")) *mbrole = role_moderator; + else if (!strcmp(p, "participant")) *mbrole = role_participant; + else if (!strcmp(p, "visitor")) *mbrole = role_visitor; + else if (!strcmp(p, "none")) *mbrole = role_none; + else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"", + from, p); + } + *mbjid = lm_message_node_get_attribute(y, "jid"); + *mbnick = lm_message_node_get_attribute(y, "nick"); + // For kick/ban, there can be actor and reason tags + *reason = lm_message_node_get_child_value(y, "reason"); + z = lm_message_node_find_child(y, "actor"); + if (z) + *actorjid = lm_message_node_get_attribute(z, "jid"); +} + +// muc_handle_join(...) +// Handle a join event in a MUC room. +// This function will return the new_member value TRUE if somebody else joins +// the room (and FALSE if _we_ are joining the room). +static bool muc_handle_join(const GSList *room_elt, const char *rname, + const char *roomjid, const char *ournick, + enum room_printstatus printstatus, + time_t usttime, int log_muc_conf) +{ + bool new_member = FALSE; // True if somebody else joins the room (not us) + gchar *mbuf; + + if (!buddy_getinsideroom(room_elt->data)) { + // We weren't inside the room yet. Now we are. + // However, this could be a presence packet from another room member + + buddy_setinsideroom(room_elt->data, TRUE); + // Set the message flag unless we're already in the room buffer window + scr_setmsgflag_if_needed(roomjid, FALSE); + // Add a message to the tracelog file + mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick); + scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); + g_free(mbuf); + mbuf = g_strdup_printf("You have joined as \"%s\"", ournick); + + // The 1st presence message could be for another room member + if (strcmp(ournick, rname)) { + // Display current mbuf and create a new message for the member + // Note: the usttime timestamp is related to the other member, + // so we use 0 here. + scr_WriteIncomingMessage(roomjid, mbuf, 0, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + if (log_muc_conf) + hlog_write_message(roomjid, 0, -1, mbuf); + g_free(mbuf); + if (printstatus != status_none) + mbuf = g_strdup_printf("%s has joined", rname); + else + mbuf = NULL; + new_member = TRUE; + } + } else { + mbuf = NULL; + if (strcmp(ournick, rname)) { + if (printstatus != status_none) + mbuf = g_strdup_printf("%s has joined", rname); + new_member = TRUE; + } + } + + if (mbuf) { + guint msgflags = HBB_PREFIX_INFO; + if (!settings_opt_get_int("muc_flag_joins")) + msgflags |= HBB_PREFIX_NOFLAG; + scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0); + if (log_muc_conf) + hlog_write_message(roomjid, 0, -1, mbuf); + g_free(mbuf); + } + + return new_member; +} + +static void handle_muc_presence(const char *from, LmMessageNode *xmldata, + const char *roomjid, const char *rname, + enum imstatus ust, const char *ustmsg, + time_t usttime, char bpprio) +{ + LmMessageNode *y; + const char *p; + char *mbuf; + const char *ournick; + enum imrole mbrole = role_none; + enum imaffiliation mbaffil = affil_none; + enum room_printstatus printstatus; + enum room_autowhois autowhois; + const char *mbjid = NULL, *mbnick = NULL; + const char *actorjid = NULL, *reason = NULL; + bool new_member = FALSE; // True if somebody else joins the room (not us) + guint statuscode = 0; + guint nickchange = 0; + GSList *room_elt; + int log_muc_conf; + guint msgflags; + + log_muc_conf = settings_opt_get_int("log_muc_conf"); + + room_elt = roster_find(roomjid, jidsearch, 0); + if (!room_elt) { + // Add room if it doesn't already exist + // It shouldn't happen, there is probably something wrong (server or + // network issue?) + room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM, + sub_none, -1); + scr_LogPrint(LPRINT_LOGNORM, "Strange MUC presence message"); + } else { + // Make sure this is a room (it can be a conversion user->room) + buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); + } + + // Get room member's information + muc_get_item_info(from, xmldata, &mbrole, &mbaffil, &mbjid, &mbnick, + &actorjid, &reason); + + // Get our room nickname + ournick = buddy_getnickname(room_elt->data); + + if (!ournick) { + // It shouldn't happen, probably a server issue + mbuf = g_strdup_printf("Unexpected groupchat packet!"); + + scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); + scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO, 0); + g_free(mbuf); + // Send back an unavailable packet + xmpp_setstatus(offline, roomjid, "", TRUE); + scr_DrawRoster(); + return; + } + + // Get the status code + // 201: a room has been created + // 301: the user has been banned from the room + // 303: new room nickname + // 307: the user has been kicked from the room + // 321,322,332: the user has been removed from the room + y = lm_message_node_find_child(xmldata, "status"); + if (y) { + p = lm_message_node_get_attribute(y, "code"); + if (p) + statuscode = atoi(p); + } + + // Get the room's "print_status" settings + printstatus = buddy_getprintstatus(room_elt->data); + if (printstatus == status_default) { + printstatus = (guint) settings_opt_get_int("muc_print_status"); + if (printstatus > 3) + printstatus = status_default; + } + + // A new room has been created; accept MUC default config + if (statuscode == 201) + xmpp_room_unlock(roomjid); + + // Check for nickname change + if (statuscode == 303 && mbnick) { + mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick); + scr_WriteIncomingMessage(roomjid, mbuf, usttime, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + if (log_muc_conf) + hlog_write_message(roomjid, 0, -1, mbuf); + g_free(mbuf); + buddy_resource_setname(room_elt->data, rname, mbnick); + // Maybe it's _our_ nickname... + if (ournick && !strcmp(rname, ournick)) + buddy_setnickname(room_elt->data, mbnick); + nickchange = TRUE; + } + + // Check for departure/arrival + if (!mbnick && ust == offline) { + // Somebody is leaving + enum { leave=0, kick, ban } how = leave; + bool we_left = FALSE; + + if (statuscode == 307) + how = kick; + else if (statuscode == 301) + how = ban; + + // If this is a leave, check if it is ourself + if (ournick && !strcmp(rname, ournick)) { + we_left = TRUE; // _We_ have left! (kicked, banned, etc.) + buddy_setinsideroom(room_elt->data, FALSE); + buddy_setnickname(room_elt->data, NULL); + buddy_del_all_resources(room_elt->data); + buddy_settopic(room_elt->data, NULL); + scr_UpdateChatStatus(FALSE); + update_roster = TRUE; + } + + // The message depends on _who_ left, and _how_ + if (how) { + gchar *mbuf_end; + // Forced leave + if (actorjid) { + mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s", + (how == ban ? "banned" : "kicked"), + roomjid, actorjid, reason); + } else { + mbuf_end = g_strdup_printf("%s from %s.", + (how == ban ? "banned" : "kicked"), + roomjid); + } + if (we_left) + mbuf = g_strdup_printf("You have been %s", mbuf_end); + else + mbuf = g_strdup_printf("%s has been %s", rname, mbuf_end); + + g_free(mbuf_end); + } else { + // Natural leave + if (we_left) { + LmMessageNode *destroynode = lm_message_node_find_child(xmldata, + "destroy"); + if (destroynode) { + if ((reason = lm_message_node_get_child_value(destroynode, + "reason"))) { + mbuf = g_strdup_printf("You have left %s, " + "the room has been destroyed: %s", + roomjid, reason); + } else { + mbuf = g_strdup_printf("You have left %s, " + "the room has been destroyed", roomjid); + } + } else { + mbuf = g_strdup_printf("You have left %s", roomjid); + } + } else { + if (ust != offline) { + // This can happen when a network failure occurs, + // this isn't an official leave but the user isn't there anymore. + mbuf = g_strdup_printf("%s has disappeared!", rname); + ust = offline; + } else { + if (ustmsg) + mbuf = g_strdup_printf("%s has left: %s", rname, ustmsg); + else + mbuf = g_strdup_printf("%s has left", rname); + } + } + } + + // Display the mbuf message if we're concerned + // or if the print_status isn't set to none. + if (we_left || printstatus != status_none) { + msgflags = HBB_PREFIX_INFO; + if (!we_left && settings_opt_get_int("muc_flag_joins") != 2) + msgflags |= HBB_PREFIX_NOFLAG; + scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0); + } + + if (log_muc_conf) + hlog_write_message(roomjid, 0, -1, mbuf); + + if (we_left) { + scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); + g_free(mbuf); + return; + } + g_free(mbuf); + } else if (buddy_getstatus(room_elt->data, rname) == offline && + ust != offline) { + // Somebody is joining + new_member = muc_handle_join(room_elt, rname, roomjid, ournick, + printstatus, usttime, log_muc_conf); + } else { + // This is a simple member status change + + if (printstatus == status_all && !nickchange) { + mbuf = g_strdup_printf("Member status has changed: %s [%c] %s", rname, + imstatus2char[ust], ((ustmsg) ? ustmsg : "")); + scr_WriteIncomingMessage(roomjid, mbuf, usttime, + HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); + g_free(mbuf); + } + } + + // Sanity check, shouldn't happen... + if (!rname) + return; + + // Update room member status + roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime, + mbrole, mbaffil, mbjid); + + autowhois = buddy_getautowhois(room_elt->data); + if (autowhois == autowhois_default) + autowhois = (settings_opt_get_int("muc_auto_whois") ? + autowhois_on : autowhois_off); + + if (new_member && autowhois == autowhois_on) { + // FIXME: This will fail for some UTF-8 nicknames. + gchar *joiner_nick = from_utf8(rname); + cmd_room_whois(room_elt->data, joiner_nick, FALSE); + g_free(joiner_nick); + } + + scr_DrawRoster(); +} + +static void roompresence(gpointer room, void *presencedata) +{ + const char *bjid; + const char *nickname; + char *to; + struct T_presence *pres = presencedata; + + if (!buddy_getinsideroom(room)) + return; + + bjid = buddy_getjid(room); + if (!bjid) return; + nickname = buddy_getnickname(room); + if (!nickname) return; + + to = g_strdup_printf("%s/%s", bjid, nickname); + xmpp_setstatus(pres->st, to, pres->msg, TRUE); + g_free(to); +} + +// got_invite(from, to, reason, passwd) +// This function should be called when receiving an invitation from user +// "from", to enter the room "to". Optional reason and room password can +// be provided. +static void got_invite(const char* from, const char *to, const char* reason, + const char* passwd) +{ + eviqs *evn; + event_muc_invitation *invitation; + GString *sbuf; + char *barejid; + GSList *room_elt; + + sbuf = g_string_new(""); + if (reason) { + g_string_printf(sbuf, + "Received an invitation to <%s>, from <%s>, reason: %s", + to, from, reason); + } else { + g_string_printf(sbuf, "Received an invitation to <%s>, from <%s>", + to, from); + } + + barejid = jidtodisp(from); + scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str); + + evn = evs_new(EVS_TYPE_INVITATION, EVS_MAX_TIMEOUT); + if (evn) { + evn->callback = &evscallback_invitation; + invitation = g_new(event_muc_invitation, 1); + invitation->to = g_strdup(to); + invitation->from = g_strdup(from); + invitation->passwd = g_strdup(passwd); + invitation->reason = g_strdup(reason); + evn->data = invitation; + evn->desc = g_strdup_printf("<%s> invites you to %s ", from, to); + g_string_printf(sbuf, "Please use /event %s accept|reject", evn->id); + } else { + g_string_printf(sbuf, "Unable to create a new event!"); + } + scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str); + g_string_free(sbuf, TRUE); + g_free(barejid); + + // Make sure the MUC room barejid is a room in the roster + barejid = jidtodisp(to); + room_elt = roster_find(barejid, jidsearch, 0); + if (room_elt) + buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); + + g_free(barejid); +} + + +// Specific MUC message handling (for example invitation processing) +static void got_muc_message(const char *from, LmMessageNode *x) +{ + LmMessageNode *invite = lm_message_node_get_child(x, "invite"); + if (invite) + { + const char *invite_from; + const char *reason = NULL; + const char *password = NULL; + + invite_from = lm_message_node_get_attribute(invite, "from"); + reason = lm_message_node_get_child_value(invite, "reason"); + password = lm_message_node_get_child_value(invite, "password"); + if (invite_from) + got_invite(invite_from, from, reason, password); + } + // TODO + // handle status code = 100 ( not anonymous ) + // handle status code = 170 ( changement de config ) + // 10.2.1 Notification of Configuration Changes + // declined invitation +} + diff -r 4f59a414217e -r a087125d8fc8 mcabber/src/xmpp_s10n.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/xmpp_s10n.c Sun Oct 11 15:38:32 2009 +0200 @@ -0,0 +1,63 @@ +/* See xmpp.c file for copyright and license details. */ + +// xmpp_send_s10n(jid, subtype) +// Send a s10n message with the passed subtype +void xmpp_send_s10n(const char *bjid, LmMessageSubType type) +{ + LmMessage *x = lm_message_new_with_sub_type(bjid, + LM_MESSAGE_TYPE_PRESENCE, + type); + lm_connection_send(lconnection, x, NULL); + lm_message_unref(x); +} + +static int evscallback_subscription(eviqs *evp, guint evcontext) +{ + char *barejid; + char *buf; + + if (evcontext == EVS_CONTEXT_TIMEOUT) { + scr_LogPrint(LPRINT_LOGNORM, "Event %s timed out, cancelled.", + evp->id); + return 0; + } + if (evcontext == EVS_CONTEXT_CANCEL) { + scr_LogPrint(LPRINT_LOGNORM, "Event %s cancelled.", evp->id); + return 0; + } + if (!(evcontext & EVS_CONTEXT_USER)) + return 0; + + // Sanity check + if (!evp->data) { + // Shouldn't happen, data should be set to the barejid. + scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); + return 0; + } + + // Ok, let's work now. + // evcontext: 0, 1 == reject, accept + + barejid = evp->data; + + if (evcontext & ~EVS_CONTEXT_USER) { + // Accept subscription request + xmpp_send_s10n(barejid, LM_MESSAGE_SUB_TYPE_SUBSCRIBED); + buf = g_strdup_printf("<%s> is allowed to receive your presence updates", + barejid); + } else { + // Reject subscription request + xmpp_send_s10n(barejid, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED); + buf = g_strdup_printf("<%s> won't receive your presence updates", barejid); + if (settings_opt_get_int("delete_on_reject")) { + // Remove the buddy from the roster if there is no current subscription + if (roster_getsubscription(barejid) == sub_none) + xmpp_delbuddy(barejid); + } + } + scr_WriteIncomingMessage(barejid, buf, 0, HBB_PREFIX_INFO, 0); + scr_LogPrint(LPRINT_LOGNORM, "%s", buf); + g_free(buf); + return 0; +} +